Compare commits

..

250 Commits

Author SHA1 Message Date
Jianbo Sun
c96a92475d Merge pull request #974 from wonderflow/reg
minor change for CI name
2021-01-29 18:40:21 +08:00
天元
316b438674 minor change for CI name 2021-01-29 18:24:38 +08:00
Jianbo Sun
104f0827dc Merge pull request #958 from captainroy-hy/static-check-action
add staticcheck CI action
2021-01-29 18:14:56 +08:00
Jianbo Sun
0a81696315 Merge pull request #973 from wonderflow/testmaster
manually create release and automatically upload artifacts
2021-01-29 17:44:33 +08:00
roy wang
93ae8a9099 fix staticcheck issues
add staticcheck CI action

add staticcheck in Makefile

Signed-off-by: roywang <seiwy2010@gmail.com>
2021-01-29 18:42:03 +09:00
天元
ed436d4e6d merge chart and docker publish into registry 2021-01-29 17:12:18 +08:00
天元
e5e71dbc25 change from create release by github robot to manuelly
automatically upload artifacts after manually released
2021-01-29 17:11:58 +08:00
Jianbo Sun
af61a81828 Merge pull request #971 from wonderflow/fixc
fix inner containerizedworkload not work
2021-01-29 16:28:52 +08:00
天元
b88309a333 fix inner containerizedworkload not work 2021-01-29 15:51:29 +08:00
Jianbo Sun
c41bd241ce update kubevela installation guide (#955)
* update kubevela installation guide

* adress comments

* Update docs/en/install.md

Co-authored-by: Hongchao Deng <hongchaodeng1@gmail.com>

* Update docs/en/install.md

Co-authored-by: Hongchao Deng <hongchaodeng1@gmail.com>

* remove line

* address comments

Co-authored-by: Hongchao Deng <hongchaodeng1@gmail.com>
2021-01-29 15:46:58 +08:00
Jianbo Sun
5c188dd9cc Merge pull request #952 from wonderflow/removecode
remove unused dependency installation
2021-01-29 14:58:57 +08:00
Jianbo Sun
66fb99954e fix quick start guide as we don't have route trait installed as default (#954)
* fix quick start guide as we don't have route trait installed as default

* add a description for ingress trait
2021-01-29 14:56:38 +08:00
Jianbo Sun
f39660c286 Merge pull request #953 from wonderflow/svcd
deprecate unused vela commands
2021-01-29 13:48:31 +08:00
Jianbo Sun
07e16d9f8a Merge pull request #967 from wonderflow/arm64
build linux/arm64 cli command
2021-01-29 13:47:27 +08:00
Jianbo Sun
2abcb44ee2 Merge pull request #937 from wonderflow/outputs
allow multiple outputs for workloaddefintion
2021-01-29 12:39:36 +08:00
天元
d2ce5856a6 adress comment 2021-01-29 12:38:23 +08:00
天元
bed609e192 build linux/arm64 cli command 2021-01-29 12:18:38 +08:00
天元
6922f7cfab fix ci 2021-01-29 11:39:44 +08:00
天元
aed2494875 allow multiple outputs for workloaddefintion 2021-01-29 11:39:44 +08:00
天元
10076f8516 trait name should not contain dummy when traitdefinition not found 2021-01-29 11:39:44 +08:00
Jianbo Sun
a8b4004e3b Merge pull request #965 from captainroy-hy/not-depend-defref
allow traitDefinition to omit definitionRef
2021-01-29 11:36:22 +08:00
Jianbo Sun
a042b6b43d Merge pull request #963 from ryanzhang-oss/appDeployment-structure
further develop appDeployment controller
2021-01-29 11:19:59 +08:00
Jianbo Sun
130827629b Merge pull request #962 from allenhaozi/feat/update-del-app-prompt-msg
update delete app prompt information
2021-01-29 11:18:23 +08:00
mahao
82cdb615c0 update delete app prompt information
Signed-off-by: mahao <allenhaozi@gmail.com>
2021-01-29 11:00:44 +08:00
roy wang
7629399683 allow traitDefinition to omit definitionRef
Signed-off-by: roy wang <seiwy2010@gmail.com>
2021-01-29 11:31:03 +09:00
Ryan Zhang
ad496b132a further develop appDeployment controller 2021-01-28 17:59:31 -08:00
Zheng Xi Zhou
2a943c9429 Using Terraform as IaC module in KubeVela (#863)
* Integrate Terraform into KubeVela

Integrated Terrafrom into KubeVela to enable it to deploy
infrastruce resouces by `vela up`

* extend Terraform modules/files as WorkloadDefinition

stop printing terraform log to console

Support one workload consumes two cloud services

Refactor Terraform plugin based on Application Object

add testcase

* refactor code per reviewer's comments

fix rebase issue

* find lost code back

* refactor code to make the modification as little as to that of branch master

* remove blank lines from imports
2021-01-28 18:36:52 +08:00
天元
52aed26b96 update docs 2021-01-28 15:21:04 +08:00
天元
61c256a97c remove unused dependency installation as we have reduce 3rd party dependency , they will be installed as capability from registry 2021-01-28 14:55:25 +08:00
天元
8dbad9e8c1 remove relevant test code 2021-01-28 14:54:09 +08:00
天元
3e8f0b3299 remove vela <trait> command 2021-01-28 14:45:55 +08:00
天元
c1a14a70f5 remove vela comp deploy 2021-01-28 14:41:41 +08:00
just-do1
0a6065d7d0 [#929] Modification to comand vela show WORKLOAD_TYPE or TRAIT (#948)
* [#929] Modification to comand vela show WORKLOAD_TYPE or TRAIT

* update the describetion of --web

* [#929] update --web describtion

* update the doc of check-ref-doc.md
2021-01-28 12:28:47 +08:00
Jianbo Sun
fa58501a97 remove 3rd party dependency from default installation (#946)
* remove 3rd party dependency from default installation

* fix CI
2021-01-27 18:29:42 -08:00
Zheng Xi Zhou
aa03e9c9d4 OpenAPI: Application creation based on Application object (#924)
* OpenAPI: Application creation based on Application object

Implemented Application creation OpenAPI based on new Application object
To #913

* fix e2e problems

* fix import issue
2021-01-28 10:15:26 +08:00
Jaime Zhang
4d00ad78ae #884 #830 complete the trait info when it is applied to * (#890)
* #884 complete the trait info when it is applied to *

* add unit test for trait print which applied to *

* code optimization

* code optimization to go standard

* summarize all 'applies to' content to *
2021-01-27 19:57:47 +08:00
Ryan Zhang
5b26575c16 Merge pull request #945 from wonderflow/charts
Upload vela core chart to alibaba cloud oss for every release and master commit
2021-01-27 01:24:13 -08:00
天元
cf60e72fe9 use the number version 2021-01-27 17:02:10 +08:00
天元
a2707395e9 force push to cloud 2021-01-27 16:37:16 +08:00
天元
a420785dc2 add repo url 2021-01-27 16:32:58 +08:00
天元
ccf47a2189 fix no config 2021-01-27 16:20:55 +08:00
天元
3d98b94fd8 upload charts to alibaba cloud oss bucket 2021-01-27 16:17:23 +08:00
Ryan Zhang
6adb91fb50 Merge pull request #940 from ryanzhang-oss/appDeployment
Add rollout annotation logic in application
2021-01-27 00:14:40 -08:00
Jianbo Sun
d27aa77753 Merge pull request #938 from wonderflow/updatedep
upgrade github.com/stretchr/testify try fix CI
2021-01-27 15:06:58 +08:00
Ryan Zhang
462be588af address comments and fix CI 2021-01-26 20:47:56 -08:00
Ryan Zhang
c85bbe1ae2 add rolling annotation to the application 2021-01-26 00:29:49 -08:00
Ryan Zhang
a257f6e60c application controller ignore annotation 2021-01-26 00:03:53 -08:00
Ryan Zhang
0e987a08b6 Merge pull request #934 from wonderflow/cert-manager
support vela install with helm args and make cert-manager optional
2021-01-25 23:35:56 -08:00
Jianbo Sun
206d343785 Merge pull request #927 from ryanzhang-oss/appdeployment-controller
some initial code for app deployment controller/webhook
2021-01-26 15:24:00 +08:00
天元
1cf1e6c064 upgrade github.com/stretchr/testify try fix CI 2021-01-26 15:00:43 +08:00
Jianbo Sun
c1f50d622b Merge pull request #936 from kqzh/master
fix condition err always nil
2021-01-26 14:49:29 +08:00
Ryan Zhang
e664831ff6 application deployment 2021-01-25 22:17:35 -08:00
kqzh
3a73221661 fix err always nil 2021-01-26 13:58:10 +08:00
Jianbo Sun
97f45ae859 code refactor (#935)
* code refactor

* update boilerplate.go.txt
2021-01-26 10:26:41 +08:00
天元
4cd9a70cfe support vela install with helm args and make cert-manager optional 2021-01-25 19:16:18 +08:00
Weiping Cai
75ecf2f301 support env and config storage driver (#850)
* support env and config storage driver

Signed-off-by: Weiping Cai <weiping.cai@daocloud.io>

* use driver.LocalDriverName to replace  str

Signed-off-by: Weiping Cai <weiping.cai@daocloud.io>
2021-01-25 16:26:42 +08:00
Hongchao Deng
77642f069a Merge pull request #926 from hongchaodeng/design-update
* update APIServer + Catalog design

- add application creation workflow
- make application adaptable to multiple env and clusters
- add module into catalog package format and adapt to helm/terraform
2021-01-24 19:32:23 -08:00
Hongchao Deng
2720028e2a comment 2021-01-24 19:11:36 -08:00
Jianbo Sun
72ee26dbb4 add advanced trait tutorial (#921)
* add advanced trait tutorial

* add more intersiting trait

* init container and patch

* add more traits

* node affinity

* addressing comment
2021-01-25 10:53:36 +08:00
Jianbo Sun
9173ff828f Merge pull request #930 from leejanee/dry-run
Add dry-run command
2021-01-23 12:28:03 +08:00
Hongchao Deng
62ec540fcf update 2021-01-22 13:35:54 -08:00
lj176172
f6a3ade584 lint 2021-01-22 19:17:49 +08:00
lj176172
be49ea092b application dry-run 2021-01-22 19:05:55 +08:00
Hongchao Deng
b173224212 update APIServer + Catalog design
- add application creation workflow
- make application adaptable to multiple env and clusters
- add module into catalog package format and adapt to helm/terraform
2021-01-22 00:24:30 -08:00
Jianbo Sun
c71eea7f90 Merge pull request #923 from zeed-w-beez/master
happy new year
2021-01-22 12:37:08 +08:00
zeed-w-beez
5b1a55b58b happy new year
Use variable-year in copyrights.
2021-01-22 11:25:21 +08:00
Zheng Xi Zhou
eba7049f39 Add Getdefinition OpenAPI in Restful-api docs (#917)
Added Getdefinition api docs and update email contact
2021-01-22 10:20:22 +08:00
Jianbo Sun
65706f401b Merge pull request #857 from captainroy-hy/refactor-apply
using 3-way-merge-patch instead of "json merge patch for workload" and "update for trait"
2021-01-21 18:42:00 +08:00
roywang
59a6ef5140 implement util/apply with three-way diff
add/fix unit tests

fix e2e tests

update doc & add unit test

Signed-off-by: roy wang <seiwy2010@gmail.com>
2021-01-21 18:05:29 +09:00
Jianbo Sun
1fcd4ca55e Merge pull request #920 from ryanzhang-oss/app-deployment-controller
refactor application controller
2021-01-21 16:52:00 +08:00
Ryan Zhang
d74dbb4fda refactor application controller 2021-01-21 00:34:04 -08:00
Jianbo Sun
b6edd4bc7e Merge pull request #916 from resouer/dev
Fix ref doc guide
2021-01-21 14:04:18 +08:00
Harry Zhang
879c6c8878 Fix ref doc guide 2021-01-20 21:22:49 -08:00
Hongchao Deng
c722f561b0 Merge pull request #901 from zzxwill/ref-docs
Add `Writing Appfile` based on capability references docs
2021-01-20 19:20:32 -08:00
Jianbo Sun
0b5052ad91 Merge pull request #912 from resouer/dev
Update the concept doc to reflect app crd
2021-01-21 10:52:04 +08:00
Jianbo Sun
4661297ca5 Merge pull request #902 from ryanzhang-oss/rollout-structure
Rollout code framework
2021-01-21 10:02:37 +08:00
Harry Zhang
87cc86dde2 Update the concept doc to reflect app crd 2021-01-20 17:33:20 -08:00
Ryan Zhang
adbe1f9368 add the rollout code framework 2021-01-20 13:08:00 -08:00
Zheng Xi Zhou
f0d8bd078b address comments
Co-authored-by: Jianbo Sun <wonderflow.sun@gmail.com>
2021-01-20 15:56:20 +08:00
zzxwill
78b86d84b6 Add Writing Appfile based on capability references docs
Introduced `vela show` with and without flag `--no-website`, and
official site to help setting properties for workload types and
traits.
2021-01-20 15:56:20 +08:00
Jianbo Sun
ba4374dc27 Merge pull request #900 from sunny0826/docs
update docs
2021-01-20 15:35:13 +08:00
guoxudong
806c396264 update docs 2021-01-20 13:37:43 +08:00
Jianbo Sun
721ca9ff92 Merge pull request #886 from zzxwill/ref-docs
Generate the reference doc for a workload type or trait in the local host website and in a table style on Cli console
2021-01-20 10:34:03 +08:00
Ryan Zhang
023d24d392 draft 2021-01-19 15:50:38 -08:00
zzxwill
a674174cda add more unittest 2021-01-19 21:56:26 +08:00
zzxwill
48f3ed94b7 convert configuration files to variables
open the exact reference doc link for a capability

add option `--no-website` to support display reference docs on console
2021-01-19 15:16:40 +08:00
Jianbo Sun
47f35e6d62 Merge pull request #861 from rain18/health
feature: add healthcheck policy for workload and trait by cue template
2021-01-19 13:23:58 +08:00
zhangrun.zr
f55dd467b9 feature: add healthcheck policy for workload and trait by cue template
Signed-off-by: zhangrun.zr <zhangrun.zr@alibaba-inc.com>
2021-01-19 13:03:05 +08:00
Ryan Zhang
7524aeee31 Merge pull request #852 from rain18/task
feature: add http task for application cue template
2021-01-18 20:11:59 -08:00
Hongchao Deng
cb368c2f8c roadmap: add template, rewrite 2020 winter, add 2021 spring (#891)
* roadmap: add template, rewrite 2020 winter, add 2021 spring

Signed-off-by: Hongchao Deng <hongchaodeng1@gmail.com>

* Update docs/en/roadmap/2020-12-roadmap.md

Co-authored-by: Zheng Xi Zhou <zzxwill@gmail.com>

* update

Signed-off-by: Hongchao Deng <hongchaodeng1@gmail.com>

Co-authored-by: Zheng Xi Zhou <zzxwill@gmail.com>
2021-01-19 09:57:27 +08:00
Jianbo Sun
64c560583e Merge pull request #894 from captainroy-hy/fix-unstable-ut-4
fix unstable unit test
2021-01-19 09:55:33 +08:00
roy wang
580056b209 fix unstable unit test
Signed-off-by: roy wang <seiwy2010@gmail.com>
2021-01-18 18:59:58 +09:00
zhangrun.zr
2706e63743 fix: use httptest instead of echo and rename context
Signed-off-by: zhangrun.zr <zhangrun.zr@alibaba-inc.com>
2021-01-18 15:52:22 +08:00
zzxwill
3546001bf6 Generate a local site to host all reference docs
By Cli `vela reference` to generate reference docs for all workload
types and traits, and host them in a local website.

To fix #880
2021-01-18 12:18:15 +08:00
Jianbo Sun
40aa97363e Merge pull request #787 from ryanzhang-oss/rollout
rollout CRD API Spec
2021-01-18 11:01:59 +08:00
Ryan Zhang
f6345534e6 fix field name 2021-01-15 19:19:32 -08:00
Ryan Zhang
df32d4b1ba update rollout CRD spec 2021-01-15 19:19:32 -08:00
Hongchao Deng
a10dccf5bd Vela APIServer and Catalog Design (#881)
* APIServer + Catalog Architecture Design

Signed-off-by: Hongchao Deng <hongchaodeng1@gmail.com>

* update
2021-01-15 11:22:59 -08:00
Jianbo Sun
f40a41dbc1 Merge pull request #888 from resouer/fix-msg
Add more details for platform builder
2021-01-15 19:51:28 +08:00
zhangrun.zr
732d8f76d3 feature: add http task for application cue template
Signed-off-by: zhangrun.zr <zhangrun.zr@alibaba-inc.com>
2021-01-15 19:20:39 +08:00
Jianbo Sun
4732bd943d Update docs/en/concepts.md
Co-authored-by: Zheng Xi Zhou <zzxwill@gmail.com>
2021-01-15 19:05:40 +08:00
Jianbo Sun
89863b30e8 fix ci and refactor code (#887)
* adjust CI scripts

* fix go ci order

* try fix

* use appfile to update trait

* fix vela status

* use assert.ObjectAreEqual to check diff for map case

* remove application controller own AC and Components

* tune place

* fix lint

* update

* remove error check of vela init test

Co-authored-by: Ryan Zhang <yangzhangrice@hotmail.com>
2021-01-15 19:04:12 +08:00
Harry Zhang
00ba0697dc Update concepts and readme to reflect recent change 2021-01-14 22:14:57 -08:00
Harry Zhang
30585f80e6 Init platform builder doc 2021-01-14 21:38:03 -08:00
Zheng Xi Zhou
83ce5ec724 Add ConflictsWith and more sections for Rollout (#869)
Added `ConflictsWith` and `How Rollout Works` section to Rollout Reference Docs.
To fix #777
2021-01-14 17:22:55 +08:00
Jianbo Sun
4467084c0e Merge pull request #875 from wonderflow/vela-up
add tests for application controller
2021-01-11 21:23:41 +08:00
天元
1f1f3af7b7 refacter and add tests 2021-01-11 20:48:17 +08:00
Ryan Zhang
d38c08af56 Merge pull request #846 from leejanee/vela-up
vela up generate application object instead of AC and Component
2021-01-10 22:10:39 -08:00
天元
2761e7afb9 use map[string]string for scope 2021-01-11 10:54:57 +08:00
天元
8410f03eb0 addressing comments 2021-01-11 10:45:13 +08:00
Jianbo Sun
e51c283c1d Merge pull request #868 from zzxwill/apischema
Add unit-test for generateOpenAPISchema
2021-01-09 21:48:33 +08:00
天元
f694d1ad5d add tests 2021-01-08 18:16:03 +08:00
zzxwill
674408784b address comments and add one more testcase 2021-01-08 15:46:30 +08:00
majian
19e8aa2af6 Dashboard fix (#871)
* 1.fix repeated click does not show component bug
2.typed
3.fix locales

* capability rename

Co-authored-by: Zheng Xi Zhou <zzxwill@gmail.com>
2021-01-08 10:54:15 +08:00
天元
3dd954541e add tests 2021-01-07 20:24:25 +08:00
天元
ba614da809 fix ci 2021-01-07 19:40:32 +08:00
天元
b92e2a92fc try test again 2021-01-07 19:28:19 +08:00
天元
718a4b1999 fix ci 2021-01-07 17:52:15 +08:00
天元
de83320306 remove unused code 2021-01-07 13:07:28 +08:00
天元
4cfee561b9 refactor and add scope to application 2021-01-07 13:07:12 +08:00
Jianbo Sun
6b78945c18 Merge pull request #858 from Incubator4th/route-provider
Add provider parameter to route trait
2021-01-07 11:49:41 +08:00
incubator4th
72d6981628 set provider can be empty 2021-01-06 17:22:16 +08:00
zzxwill
2243632d0c Add unit-test for generateOpenAPISchema
Added title for all fields and added unit-test for generateOpenAPISchema FixOpenSchema,
2021-01-06 14:36:36 +08:00
Jianbo Sun
775991cfaa Merge pull request #784 from zzxwill/form-render
Implement API for generating OpenAPI schema for definition
2021-01-06 11:58:20 +08:00
Zheng Xi Zhou
da097989f8 Update pkg/appfile/service.go
Co-authored-by: Hongchao Deng <hongchaodeng1@gmail.com>
2021-01-06 11:05:37 +08:00
zzxwill
53164a4d2f Implement API for generating OpenAPI schema for definition
Fetched cue parameters from workloaddefinition/traitdefinition, generated
OpenAPI v3 schema, fixed problems of tainted `description` filed, added filed
"title" required by form-render component, added it in API server router

To fix #680
2021-01-05 21:57:38 +08:00
天元
3d3b3239d8 add trait type 2021-01-05 21:18:27 +08:00
天元
b1a97b08ec add workload type to label 2021-01-05 21:08:41 +08:00
incubator4th
72663f68cb add provider to route.cue 2021-01-05 21:06:55 +08:00
天元
8c7db9b0e0 larger time 2021-01-05 19:31:11 +08:00
天元
c72941f916 check application 2021-01-05 19:18:48 +08:00
天元
cc590d7c42 using vela up to deploy 2021-01-05 18:10:22 +08:00
天元
5e06e41477 try fix ci 2021-01-05 17:15:55 +08:00
天元
6e658d1ea8 Merge branch 'master' into vela-up 2021-01-05 17:15:03 +08:00
Jianbo Sun
4832d95506 Merge pull request #854 from wonderflow/contribute
refine contributing doc
2021-01-05 13:33:46 +08:00
Jianbo Sun
61b9816296 Merge pull request #853 from wonderflow/tests
add test for component revision hook
2021-01-05 12:09:57 +08:00
天元
9a613da8c5 refine contributing doc 2021-01-05 12:09:23 +08:00
guoxudong
72ee5db872 Fix `each child in a list should have a unique "key" prop.' (#844)
* fix capability

* fix
2021-01-04 13:30:59 -08:00
lj176172
cb68136f93 remove 2021-01-04 17:26:34 +08:00
lj176172
a181ff46b6 extend exec-timeout period 2021-01-04 16:28:38 +08:00
lj176172
2e1433c366 extend exec-timeout period 2021-01-04 16:04:54 +08:00
lj176172
bac35a425f extend exec-timeout period 2021-01-04 15:53:03 +08:00
lj176172
08d0b4830a recover 2020-12-31 18:41:46 +08:00
lj176172
a1d9b3d032 remove trait attach 2020-12-31 18:31:24 +08:00
Jianbo Sun
8d0595ed4e Update cmd/core/main.go 2020-12-31 17:13:13 +08:00
天元
01bd05d0a5 add test for component revision hook 2020-12-31 16:41:55 +08:00
lj176172
76d585795b fix ls command 2020-12-31 16:18:37 +08:00
lj176172
4088a20252 ApplyApp 2020-12-31 12:26:05 +08:00
Jianbo Sun
810cbcaae4 Merge pull request #841 from zzxwill/issue-trait-no-definition
Allow trait to work without TraitDefinition
2020-12-31 10:52:01 +08:00
zzxwill
dfdb833abe Check trait CR is created and update ApplicationConfiguration 2020-12-31 09:16:56 +08:00
Jianbo Sun
f10e53c1eb Merge pull request #847 from wonderflow/application
refine error message: trait definition not found
2020-12-30 19:01:05 +08:00
lj176172
a88d0a5660 lint code 2020-12-30 18:26:31 +08:00
天元
02bb9a1dc1 refine error message: trait definition not found 2020-12-30 18:25:30 +08:00
lj176172
950238aa11 export scopes 2020-12-30 18:19:38 +08:00
lj176172
b52fc09fd6 lint code 2020-12-30 14:13:27 +08:00
lj176172
062c906e95 rebase master 2020-12-30 14:08:54 +08:00
Jianbo Sun
69e860a1e8 Merge pull request #843 from zzxwill/dashboard-start
Refine Dashboard README
2020-12-30 13:11:54 +08:00
zzxwill
0bd85d359a Refine Dashboard README
Refined dashboard readme with all-in-one start command
2020-12-30 11:06:51 +08:00
Jianbo Sun
1abbe1f7cf Merge pull request #842 from ryanzhang-oss/minor-improve
Use the correct cue parse api
2020-12-30 10:19:06 +08:00
Jianbo Sun
88143ae64a Merge pull request #834 from zzxwill/workload
Add description field for Capability/Workloads list
2020-12-30 10:08:13 +08:00
Ryan Zhang
b25e911a74 use the correct cue parse api 2020-12-29 13:24:04 -08:00
zzxwill
d8d891f6c9 Allow trait to work without TraitDefinition
Fix the issue of applying trait if its traitdefinition
doesn't exits.

To fix issue #839
2020-12-30 00:14:26 +08:00
Jianbo Sun
a7f823940c Merge pull request #832 from wonderflow/application
refactor application object to have basic schema
2020-12-29 17:11:35 +08:00
天元
3a47d5de73 refactor application object to have more strict schema 2020-12-29 15:48:32 +08:00
zzxwill
eb2501f644 fix lint issue 2020-12-29 10:58:07 +08:00
zzxwill
abce944aad Add description field for Capability/Workloads list
Added `description` field for workloads.

To fix #821
2020-12-29 10:43:05 +08:00
Jianbo Sun
386d5dd0ee Merge pull request #833 from zzxwill/workload
Expend column width for "vela workloads/traits"
2020-12-28 22:00:59 +08:00
zzxwill
509895511b Expend column width for "vela workloads/traits"
Expended column width for `vela workloads/traits` and also
shortened the description for all workloads and traits.
Fixed a tiny issue in hack/reference/generate.go

To fix issue #827
2020-12-28 20:57:22 +08:00
Weiping Cai
c0ebe8dc62 support mutli storage resources,define storage interface and implemen… (#776)
* support mutli storage resources,define storage interface and implement local storage

Signed-off-by: Weiping Cai <weiping.cai@daocloud.io>

* support mutli storage resources,define storage interface and implement local storage

Signed-off-by: Weiping Cai <weiping.cai@daocloud.io>

* support mutli storage resources,define storage interface and implement local storage

Signed-off-by: Weiping Cai <weiping.cai@daocloud.io>

* support mutli storage resources,define storage interface and implement local storage

Signed-off-by: Weiping Cai <weiping.cai@daocloud.io>

* move application/Application to storage/driver pkg

Signed-off-by: Weiping Cai <weiping.cai@daocloud.io>

* update storage import format

Signed-off-by: Weiping Cai <weiping.cai@daocloud.io>
2020-12-28 18:39:58 +08:00
Jianbo Sun
ebf1b51d58 Merge pull request #831 from zzxwill/mutation-webhook-conflicts
Add "How to fix issue: MutatingWebhookConfiguration mutating-webhook-configuration exists?"
2020-12-28 18:39:17 +08:00
zzxwill
4b27f9b4e2 Add "How to fix issue: MutatingWebhookConfiguration mutating-webhook-configuration exists?"
Added another question.

To cover issue #794
2020-12-28 17:44:58 +08:00
Jianbo Sun
8f6d0fded8 Merge pull request #825 from wonderflow/fix1
run CI check for all PR including docs/ and *md
2020-12-28 13:38:41 +08:00
Jianbo Sun
e8cabdc13c Merge pull request #824 from zzxwill/issue-workloads
Add "description" field for each workload from ListWorkloads API
2020-12-28 10:02:01 +08:00
Jianbo Sun
a03d9f2626 Merge pull request #828 from zzxwill/issue-vela-workloads
Refine error message for trait without `spec.extension.template`
2020-12-27 11:06:50 +08:00
zzxwill
37cb5ccb51 Add "description" field for each workload from ListWorkloads API
Workload item doesn't have descriptin property, added it to help display
the description in capability list on Dashboard
2020-12-25 19:04:54 +08:00
zzxwill
4c34048186 Refine error message for trait without spec.extension.template
Error message of trait without `spec.extension.template`
adheres with normal message when executing "vela workloads".

To fix #826
2020-12-25 18:25:19 +08:00
天元
76e0bbcabd run CI check for all PR including docs/ and *md 2020-12-25 17:53:04 +08:00
Jianbo Sun
32bc74456a Merge pull request #810 from Cweiping/fix/fix_promethus_typo_error_2
fix typo error of promethus
2020-12-25 17:39:22 +08:00
Jianbo Sun
82df7c3a71 Merge pull request #811 from captainroy-hy/fix-integration-test
fix unstable integration test
2020-12-25 17:38:21 +08:00
majian
c06aca6f60 add dashboard lint check (#815) and remove unused ref 2020-12-25 14:24:06 +08:00
Jianbo Sun
69dcf2fc5a Merge pull request #807 from wonderflow/datainput
support strategy patch datainput merge for slice case
2020-12-25 12:42:13 +08:00
Yang Liu
04c9af5c81 Merge pull request #812 from wonderflow/revision
support custom component revision hook
2020-12-25 11:51:02 +08:00
guoxudong
1e6248d189 [Dashboard] Capabilities page (#803)
* add capabilities (workloads and traits)

* yarn prettier
2020-12-25 11:13:08 +08:00
天元
e3b4bcd2ca support custom component revision 2020-12-25 09:40:54 +08:00
roywang
9730cb438d fix unstable integration test
Signed-off-by: roywang <seiwy2010@gmail.com>
2020-12-24 18:22:27 +09:00
Jianbo Sun
a8f48eb140 Merge pull request #809 from hongchaodeng/owner
add sunny0826 (Xudong Guo) as reviewer
2020-12-24 14:20:59 +08:00
Weiping Cai
ab6a170c1d fix typo error of promethus
Signed-off-by: Weiping Cai <weiping.cai@daocloud.io>
2020-12-24 14:00:17 +08:00
Hongchao Deng
dc9b1eb6fc add sunny0826 (Xudong Guo) as reviewer 2020-12-23 21:55:04 -08:00
Hongchao Deng
629bf00b63 update owner file (#808)
Signed-off-by: Hongchao Deng <hongchaodeng1@gmail.com>
2020-12-23 21:51:31 -08:00
Jian.Li
1f2c38d3c7 supports strategy patch for definition template (#798)
* supports strategy patch for definition template

* strategy unify

* lint code

* test cases

* add docs

* add test cases

* lint code

* add test cases for walk

* fix close fun

* lint code

* const variable for patchKey

* lint code

* interceptor for ast.Node

* add test cases

* check diff

* strategyUnify

* listMergeByKey

* prompts
2020-12-24 13:35:34 +08:00
Hongchao Deng
b129637cf2 add Community doc to clarify membership ladder (#805)
* add Community doc to clarify membership ladder

* update
2020-12-23 11:07:06 -08:00
Yue Wang
630f1e48bc enable webhooks for AppConfig/Comp (#781)
rename webhooks

fix e2e tests

Signed-off-by: roywang <seiwy2010@gmail.com>
2020-12-23 11:02:06 -08:00
天元
4bed55b400 support strategy patch datainput merge for slice case 2020-12-23 21:53:05 +08:00
Jianbo Sun
54ca5c115f Merge pull request #774 from captainroy-hy/trait-conflict-validation
implement conflictsWtih feature in trait definition
2020-12-23 13:32:38 +08:00
Zheng Xi Zhou
ddba62fba0 Generate restful api based on Swagger (#765)
* Generate restful api based on Swagger

As OpenAPI has to be quickly developped to support front-end developement, so
did the restufl api docs. Based on swagger, generate the docs automatically

* fix conflicts and add application list annotation
2020-12-22 16:35:26 -08:00
guoxudong
15a24c65b9 fix toc (#802) 2020-12-22 16:32:48 -08:00
guoxudong
56285ca540 add restful api docs (#801) 2020-12-22 15:16:56 +08:00
Jianbo Sun
b1c3f593db Merge pull request #800 from sunny0826/brew-install
docs add brew
2020-12-22 14:53:45 +08:00
guoxudong
e23f6b3866 docs add brew 2020-12-22 14:47:54 +08:00
Jianbo Sun
2943bc7ce1 Merge pull request #797 from wonderflow/fixrevision
fix workload reconcile error when revision enable trait is attached
2020-12-21 22:27:47 +08:00
Jianbo Sun
da0f8916aa Merge pull request #790 from zzxwill/issue-vela-install
Refine error message for vela installation
2020-12-21 21:15:21 +08:00
天元
7609da212f fix workload can not be update when revision enable trait is attached 2020-12-21 21:12:19 +08:00
Zheng Xi Zhou
7f87a47832 Update pkg/commands/system.go
Co-authored-by: Jianbo Sun <wonderflow.sun@gmail.com>
2020-12-21 18:05:42 +08:00
Jianbo Sun
04868d217b Merge pull request #791 from zzxwill/autoscale-metrics-server
Add "Autoscale: how to enable metrics server in various Kubernetes clusters?" in FAQ
2020-12-21 14:35:42 +08:00
zzxwill
56aa3c24d7 Add "Autoscale: how to enable metrics server in various Kubernetes clusters?" in FAQ
Also linked the FAQ in set-autoscale.md
2020-12-18 21:02:11 +08:00
zzxwill
a54ba9bb54 Refine error message for vela installation
Refined error message for vela installation and increase
timeout to 5 minutes from 2 minutes. And did some code
refactoring

To fix issue #783
2020-12-18 19:41:38 +08:00
Jianbo Sun
fbe93dc847 Merge pull request #771 from wonderflow/blog
add blog about how to extend kubevela by cuelang
2020-12-18 19:33:59 +08:00
天元
dbd855cc25 address comments 2020-12-18 19:11:57 +08:00
Hongchao Deng
7f136159c0 fix inconsistency for dev proxy config (#786) 2020-12-17 20:39:27 -08:00
Hongchao Deng
af61b59c5e return go time in Format RFC3339 to match js Date (#785)
Signed-off-by: Hongchao Deng <hongchaodeng1@gmail.com>
2020-12-17 20:11:18 -08:00
majian
c09e4df452 1.add application list page (#779)
2.ignore the deleted applicationconfig resource instead return nil
3.code style fix
2020-12-17 09:22:38 -08:00
Jianbo Sun
1694980eba Update docs/blog/zh/extend-kubevela-by-cuelang-in-20-mins.md
Co-authored-by: Lei Zhang (Harry) <resouer@gmail.com>
2020-12-17 09:54:46 +08:00
Jianbo Sun
feee1306fd Update docs/blog/zh/extend-kubevela-by-cuelang-in-20-mins.md
Co-authored-by: Lei Zhang (Harry) <resouer@gmail.com>
2020-12-17 09:54:30 +08:00
Jianbo Sun
0d56da4ab8 Update docs/blog/zh/extend-kubevela-by-cuelang-in-20-mins.md
Co-authored-by: Lei Zhang (Harry) <resouer@gmail.com>
2020-12-17 09:53:28 +08:00
roywang
582c3788c4 implement TraitConflict check in webhook
add unit tests

Signed-off-by: roy wang <seiwy2010@gmail.com>
2020-12-16 18:01:44 +09:00
天元
b8fd6f9823 add blog about how to extend kubevela by cuelang 2020-12-15 20:14:50 +08:00
Jianbo Sun
0fab691ba3 Merge pull request #773 from wonderflow/fiximports
minor fix
2020-12-15 15:56:23 +08:00
天元
3cb172f7ff minor fix 2020-12-15 13:55:36 +08:00
Jian.Li
e882a650ae Extend application's capabilities by trait definition (#742)
* add dsl pkg

* realize context capabilities for application

* fix golint

* fix check-diff

* upgrade vela server sample

* comment group

* Definition Reference be Optional & fix  three-part trait crd apply without namespace

* Improve samples
2020-12-13 20:00:06 -08:00
Jianbo Sun
ef9c26ffec Merge pull request #686 from majian159/hotfix-notfound-error
application not found return error. fix #685
2020-12-14 10:41:14 +08:00
majian
cf2a57c96a Integrate swagger and add env api (#764)
* 1.swagger integrate
2.add env swagger comment

Signed-off-by: majian <majian159@live.com>

* use swagger.json

Signed-off-by: majian <majian159@live.com>
2020-12-12 08:54:33 -08:00
majian
7acc52ebdb 1.use yarn (#769)
2.reinstall package

Signed-off-by: majian <majian159@live.com>
2020-12-11 10:28:08 -08:00
Jianbo Sun
3c35d9dadc Merge pull request #684 from majian159/feature-exec-svc
add svc flag for exec command.
2020-12-11 20:53:41 +08:00
majian
07742b6349 application not found return error. fix #685 and fix unit tests
Signed-off-by: majian <majian159@live.com>
2020-12-11 19:54:18 +08:00
majian
d45d086efb add svc flag for exec command and add unit test
Signed-off-by: majian <majian159@live.com>
2020-12-11 19:32:50 +08:00
Jianbo Sun
a31a316171 Merge pull request #767 from sunny0826/brew
Adapted for brew installation
2020-12-11 13:54:50 +08:00
guoxudong
ec287a181f Adapted for brew installation 2020-12-11 10:20:53 +08:00
Zheng Xi Zhou
50f4d10b00 Add make target to start both OpenAPI server and dashboard (#766)
Start up dashboard all in one
2020-12-10 11:10:10 -08:00
majian
9f27f70da8 1.migrate-env (#757)
2.add lockfile to version control
3.update packages
2020-12-10 15:05:33 +08:00
Jianbo Sun
3df55a92f3 Merge pull request #762 from resouer/dev
Update slack channel link
2020-12-10 12:08:04 +08:00
Harry Zhang
fd65c27ecb Update slack channel link 2020-12-09 19:49:15 -08:00
Jianbo Sun
576d928a83 Merge pull request #761 from captainroy-hy/fix-golint-1
fix golint issues
2020-12-10 11:39:20 +08:00
roywang
d14558a227 fix golint issues
Signed-off-by: roywang <seiwy2010@gmail.com>
2020-12-10 12:10:52 +09:00
Jianbo Sun
f48aba6f66 Merge pull request #743 from captainroy-hy/faster-refresh
faster refresh capabilities
2020-12-10 10:16:52 +08:00
Zheng Xi Zhou
f51dccf956 Minor updates on docs (#758)
Updated reference docs for autoscale and task, updated
cli docs
2020-12-09 10:35:59 -08:00
roywang
a961b002c2 faster refresh capabilities
Signed-off-by: roywang <seiwy2010@gmail.com>
2020-12-09 23:51:04 +09:00
Jianbo Sun
bffd43fa2c Merge pull request #754 from zzxwill/disscussion
Remove "Question" issue template
2020-12-09 22:14:47 +08:00
Jianbo Sun
2a88f9221f Merge pull request #728 from captainroy-hy/fix-uitable-wrap
fix cmd uitable wrap issue
2020-12-09 22:14:05 +08:00
Jianbo Sun
efdef27d0a Merge pull request #756 from zzxwill/extending-docs
Minor docs fix
2020-12-09 22:12:10 +08:00
roy wang
58bef9791f fix cmd uitable wrap issue
Signed-off-by: roy wang <seiwy2010@gmail.com>
2020-12-09 19:48:17 +09:00
zzxwill
c1de71d122 Minor docs fix
In extending trait docs, correct heading level for "Step 3"
2020-12-09 17:06:14 +08:00
majian
f8e320b97c Feature dashboard scaffold init. (#747)
* ant design pro5 init.

* scaffold init

Signed-off-by: majian <majian159@live.com>
2020-12-09 16:48:48 +08:00
zzxwill
f69476df37 Remove "question" issue template
Removed "Question" issue as we enable Github "Discussion" #744
2020-12-09 14:50:29 +08:00
Jianbo Sun
922892a909 Merge pull request #753 from zzxwill/faq
Add `what's the difference between Kubevela and helm` in FAQ
2020-12-09 14:35:43 +08:00
zzxwill
f36f7296fd Add what's the difference between Kubevela and helm in FAQ
Added the question from #704 in FAQ
2020-12-09 14:32:30 +08:00
Jianbo Sun
eff9d5f6e9 Merge pull request #752 from ElementakGod/fix-rds
Fixed the problem that the rds crd name is incorrect
2020-12-09 13:55:13 +08:00
Jianbo Sun
a75f32857a Merge pull request #750 from sunny0826/docs
Toc adapts to narrow screens
2020-12-09 13:41:19 +08:00
guoxudong
f011fe14bc fix 2020-12-09 13:40:04 +08:00
陈浩
7889a8c467 change the name of rds crd 2020-12-09 13:37:48 +08:00
guoxudong
f37cb3a1a7 Toc adapts to narrow screens 2020-12-09 13:01:35 +08:00
590 changed files with 51649 additions and 13530 deletions

View File

@@ -1,12 +0,0 @@
---
name: Question
about: Help wanted.
title: "[Question]"
labels: help wanted
assignees: ''
---
<!--
Please write your questions.
-->

View File

@@ -5,9 +5,8 @@ on:
branches: [ master ]
pull_request:
branches: [master]
paths-ignore:
- 'docs/**'
- '**.md'
workflow_dispatch: {}
defaults:
run:
working-directory: ./dashboard
@@ -16,7 +15,7 @@ jobs:
runs-on: ubuntu-20.04
strategy:
matrix:
node-version: [10.x]
node-version: [12.x]
steps:
- uses: actions/checkout@v2
@@ -24,6 +23,7 @@ jobs:
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: npm install
- run: npm run build
- run: yarn
- run: yarn lint
- run: yarn build

View File

@@ -1,56 +0,0 @@
name: Publish to Registry
on:
push:
branches:
- master
tags:
- "v*"
jobs:
update:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: Get the version
id: get_version
run: |
VERSION=${GITHUB_REF#refs/tags/}
if [[ ${GITHUB_REF} == "refs/heads/master" ]]; then
VERSION=latest
fi
echo ::set-output name=VERSION::${VERSION}
- name: Get git revision
id: vars
shell: bash
run: |
echo "::set-output name=git_revision::$(git rev-parse --short HEAD)"
- name: Login ghcr.io
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.CR_PAT }}
- name: Login docker.io
uses: docker/login-action@v1
with:
registry: docker.io
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- uses: docker/setup-qemu-action@v1
- uses: docker/setup-buildx-action@v1
- uses: docker/build-push-action@v2
name: Build & Pushing
with:
context: .
file: Dockerfile
labels: |-
org.opencontainers.image.source=https://github.com/${{ github.repository }}
org.opencontainers.image.revision=${{ github.sha }}
platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
build-args: |
GITVERSION=git-${{ steps.vars.outputs.git_revision }}
VERSION=${{ steps.get_version.outputs.VERSION }}
tags: |-
ghcr.io/${{ github.repository }}/vela-core:${{ steps.get_version.outputs.VERSION }}
docker.io/oamdev/vela-core:${{ steps.get_version.outputs.VERSION }}

View File

@@ -8,9 +8,6 @@ on:
workflow_dispatch: {}
pull_request:
branches: [master]
paths-ignore:
- 'docs/**'
- '**.md'
env:
# Common versions
@@ -71,11 +68,16 @@ jobs:
- name: Check out code into the Go module directory
uses: actions/checkout@v2
- name: Setup Go
uses: actions/setup-go@v2
with:
go-version: ${{ env.GO_VERSION }}
- name: Get dependencies
run: |
go get -v -t -d ./...
- name: Setup Kind Cluster
- name: Setup Kind
uses: engineerd/setup-kind@v0.5.0
with:
version: ${{ env.KIND_VERSION }}
@@ -106,10 +108,30 @@ jobs:
run: |
timeout 60 bash -c 'while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:38081/api/workloads)" != "200" ]]; do sleep 5; done' || false
- name: Run api e2e tests
run: make e2e-api-test
- name: Run e2e tests
run: |
make e2e-api-test
make e2e-test
run: make e2e-test
staticcheck:
runs-on: ubuntu-20.04
steps:
- name: Checkout
uses: actions/checkout@v2
with:
submodules: true
- name: Cache Go Dependencies
uses: actions/cache@v2
with:
path: .work/pkg
key: ${{ runner.os }}-pkg-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-pkg-
- name: Static Check
run: go run honnef.co/go/tools/cmd/staticcheck -- ./...
lint:
runs-on: ubuntu-20.04
@@ -157,5 +179,8 @@ jobs:
key: ${{ runner.os }}-pkg-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-pkg-
- name: Check code formatting
run: go install golang.org/x/tools/cmd/goimports && make fmt
- name: Check Diff
run: make check-diff
run: make check-diff

103
.github/workflows/registry.yml vendored Normal file
View File

@@ -0,0 +1,103 @@
name: Registry
on:
push:
branches:
- master
tags:
- "v*"
workflow_dispatch: {}
env:
BUCKET: kubevelacharts
ENDPOINT: oss-cn-hangzhou.aliyuncs.com
ACCESS_KEY: ${{ secrets.OSS_ACCESS_KEY }}
ACCESS_KEY_SECRET: ${{ secrets.OSS_ACCESS_KEY_SECRET }}
jobs:
publish-images:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: Get the version
id: get_version
run: |
VERSION=${GITHUB_REF#refs/tags/}
if [[ ${GITHUB_REF} == "refs/heads/master" ]]; then
VERSION=latest
fi
echo ::set-output name=VERSION::${VERSION}
- name: Get git revision
id: vars
shell: bash
run: |
echo "::set-output name=git_revision::$(git rev-parse --short HEAD)"
- name: Login ghcr.io
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.CR_PAT }}
- name: Login docker.io
uses: docker/login-action@v1
with:
registry: docker.io
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- uses: docker/setup-qemu-action@v1
- uses: docker/setup-buildx-action@v1
- uses: docker/build-push-action@v2
name: Build & Pushing
with:
context: .
file: Dockerfile
labels: |-
org.opencontainers.image.source=https://github.com/${{ github.repository }}
org.opencontainers.image.revision=${{ github.sha }}
platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
build-args: |
GITVERSION=git-${{ steps.vars.outputs.git_revision }}
VERSION=${{ steps.get_version.outputs.VERSION }}
tags: |-
ghcr.io/${{ github.repository }}/vela-core:${{ steps.get_version.outputs.VERSION }}
docker.io/oamdev/vela-core:${{ steps.get_version.outputs.VERSION }}
publish-charts:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@master
- name: Get the version
id: get_version
run: |
VERSION=${GITHUB_REF#refs/tags/}
if [[ ${GITHUB_REF} == "refs/heads/master" ]]; then
VERSION=latest
fi
echo ::set-output name=VERSION::${VERSION}
- name: Get git revision
id: vars
shell: bash
run: |
echo "::set-output name=git_revision::$(git rev-parse --short HEAD)"
- name: Install Helm
uses: azure/setup-helm@v1
with:
version: v3.4.0
- name: Tag helm chart image
run: |
version=${{ steps.get_version.outputs.VERSION }}
number=${version#"v"}
sed -i "s/latest/$number/g" charts/vela-core/values.yaml
sed -i "s/0.1.0/$number/g" charts/vela-core/Chart.yaml
- name: Install ossutil
run: wget http://gosspublic.alicdn.com/ossutil/1.7.0/ossutil64 && chmod +x ossutil64 && mv ossutil64 ossutil
- name: Configure Alibaba Cloud OSSUTIL
run: ./ossutil --config-file .ossutilconfig config -i ${ACCESS_KEY} -k ${ACCESS_KEY_SECRET} -e ${ENDPOINT} -c .ossutilconfig
- name: sync cloud to local
run: ./ossutil --config-file .ossutilconfig sync oss://kubevelacharts/core .oss/
- name: Package helm charts
run: |
helm package charts/vela-core --destination .oss/
helm repo index --url https://kubevelacharts.oss-cn-hangzhou.aliyuncs.com/core .oss/
- name: sync local to cloud
run: ./ossutil --config-file .ossutilconfig sync .oss/ oss://kubevelacharts/core -f

View File

@@ -4,10 +4,10 @@ on:
push:
tags:
- "v*"
workflow_dispatch: {}
jobs:
build:
name: Build
publish-cli:
runs-on: ubuntu-latest
env:
VELA_VERSION: ${{ github.ref }}
@@ -26,11 +26,11 @@ jobs:
- name: Use Node.js 10.x
uses: actions/setup-node@v1
with:
node-version: 10.x
- name: Run npm install
run: make npm-install
- name: Run npm build
run: make npm-build
node-version: 12.x
- name: Run dashboard install
run: make dashboard-install
- name: Run dashboard build
run: make dashboard-build
- name: Tag helm chart image
run: |
sed -i 's/latest/${{ steps.get_version.outputs.VERSION }}/g' charts/vela-core/values.yaml
@@ -41,58 +41,69 @@ jobs:
run: make cross-build
- name: Run compress binary
run: make compress
- name: Create Release
id: create_release
uses: actions/create-release@v1
with:
tag_name: ${{ github.ref }}
release_name: Release ${{ github.ref }}
- name: Upload Linux tar.gz
- name: Get release
id: get_release
uses: bruceadams/get-release@v1.2.2
- name: Upload Linux amd64 tar.gz
uses: actions/upload-release-asset@v1.0.2
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
upload_url: ${{ steps.get_release.outputs.upload_url }}
asset_path: ./_bin/vela-linux-amd64.tar.gz
asset_name: vela-${{ steps.get_version.outputs.VERSION }}-linux-amd64.tar.gz
asset_content_type: binary/octet-stream
- name: Upload Linux zip
- name: Upload Linux amd64 zip
uses: actions/upload-release-asset@v1.0.2
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
upload_url: ${{ steps.get_release.outputs.upload_url }}
asset_path: ./_bin/vela-linux-amd64.zip
asset_name: vela-${{ steps.get_version.outputs.VERSION }}-linux-amd64.zip
asset_content_type: binary/octet-stream
- name: Upload Linux arm64 tar.gz
uses: actions/upload-release-asset@v1.0.2
with:
upload_url: ${{ steps.get_release.outputs.upload_url }}
asset_path: ./_bin/vela-linux-arm64.tar.gz
asset_name: vela-${{ steps.get_version.outputs.VERSION }}-linux-arm64.tar.gz
asset_content_type: binary/octet-stream
- name: Upload Linux arm64 zip
uses: actions/upload-release-asset@v1.0.2
with:
upload_url: ${{ steps.get_release.outputs.upload_url }}
asset_path: ./_bin/vela-linux-arm64.zip
asset_name: vela-${{ steps.get_version.outputs.VERSION }}-linux-arm64.zip
asset_content_type: binary/octet-stream
- name: Upload MacOS tar.gz
uses: actions/upload-release-asset@v1.0.2
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
upload_url: ${{ steps.get_release.outputs.upload_url }}
asset_path: ./_bin/vela-darwin-amd64.tar.gz
asset_name: vela-${{ steps.get_version.outputs.VERSION }}-darwin-amd64.tar.gz
asset_content_type: binary/octet-stream
- name: Upload MacOS zip
uses: actions/upload-release-asset@v1.0.2
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
upload_url: ${{ steps.get_release.outputs.upload_url }}
asset_path: ./_bin/vela-darwin-amd64.zip
asset_name: vela-${{ steps.get_version.outputs.VERSION }}-darwin-amd64.zip
asset_content_type: binary/octet-stream
- name: Upload Windows tar.gz
uses: actions/upload-release-asset@v1.0.2
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
upload_url: ${{ steps.get_release.outputs.upload_url }}
asset_path: ./_bin/vela-windows-amd64.tar.gz
asset_name: vela-${{ steps.get_version.outputs.VERSION }}-windows-amd64.tar.gz
asset_content_type: binary/octet-stream
- name: Upload Windows zip
uses: actions/upload-release-asset@v1.0.2
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
upload_url: ${{ steps.get_release.outputs.upload_url }}
asset_path: ./_bin/vela-windows-amd64.zip
asset_name: vela-${{ steps.get_version.outputs.VERSION }}-windows-amd64.zip
asset_content_type: binary/octet-stream
- name: Upload Checksums
uses: actions/upload-release-asset@v1.0.2
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
upload_url: ${{ steps.get_release.outputs.upload_url }}
asset_path: ./_bin/sha256sums.txt
asset_name: sha256sums.txt
asset_content_type: text/plain

3
.gitignore vendored
View File

@@ -51,3 +51,6 @@ dashboard/package-lock.json
dashboard/src/.umi/
package-lock.json
dashboard/src/.umi-production/
# Swagger: generate Restful API
pkg/server/docs/index.html

View File

@@ -103,6 +103,10 @@ linters-settings:
rangeValCopy:
sizeThreshold: 32
makezero:
# Allow only slices initialized with a length of zero. Default is false.
always: false
linters:
enable:
- megacheck

View File

@@ -2,7 +2,8 @@
## About KubeVela
KubeVela project is initialized and maintained by the cloud native community since day 0 with [bootstrapping contributors from 8+ different organizations](https://github.com/oam-dev/kubevela/graphs/contributors). We intend for KubeVela to have a open governance since the very beginning and donate the project to neutral foundation as soon as it's released.
KubeVela project is initialized and maintained by the cloud native community since day 0 with [bootstrapping contributors from 8+ different organizations](https://github.com/oam-dev/kubevela/graphs/contributors).
We intend for KubeVela to have an open governance since the very beginning and donate the project to neutral foundation as soon as it's released.
This doc explains how to set up a development environment, so you can get started
contributing to `kubevela` or build a PoC (Proof of Concept).
@@ -27,15 +28,22 @@ We also recommend you to learn about KubeVela's [design](docs/en/design.md) befo
git clone git@github.com:oam-dev/kubevela.git
```
KubeVela includes two parts, `vela core` and `vela cli`.
- The `vela core` is actually a K8s controller, it will watch OAM Spec CRD and deploy resources.
- The `vela cli` is a command line tool that can build, run apps(with the help of `vela core`).
For local development, we probably need to build both of them.
* Build Vela CLI
```shell script
make
```
* Configure vela to PATH
After the vela cli built successfully, `make` command will create `vela` binary to `bin/` under the project.
after build, make will create `vela` binary to `bin/`, Set this path to PATH.
* Configure `vela` binary to System PATH
```shell script
export PATH=$PATH:/your/path/to/project/kubevela/bin
@@ -51,7 +59,7 @@ make manager
* Run Vela Core
Firstly make sure your cluster has CRDs.
Firstly make sure your cluster has CRDs, below is the command that can help install all CRDs.
```shell script
make core-install
@@ -66,74 +74,19 @@ make core-run
This command will run controller locally, it will use your local KubeConfig which means you need to have a k8s cluster
locally. If you don't have a one, we suggest that you could setup up a cluster with [kind](https://kind.sigs.k8s.io/).
When you're developing `vela-core`, make sure the controller installed by `vela install` is not running.
Otherwise, it will conflict with your local running controller.
You can check and uninstall it by using helm.
```shell script
helm list -A
helm uninstall -n vela-system kubevela
```
### Use
* Create environment
```shell script
vela env init myenv --namespace myenv --email my@email.com --domain kubevela.io
```
* Create Component
For example, use the following command to create and run an application.
```shell script
$ vela svc deploy mysvc -t webservice --image crccheck/hello-world --port 8000 -a abc
App abc deployed
```
* Add Trait
```shell script
$ vela route abc
Adding route for app mysvc
⠋ Deploying ...
✅ Application Deployed Successfully!
- Name: mysvc
Type: webservice
HEALTHY Ready: 1/1
Last Deployment:
Created at: 2020-11-02 11:17:28 +0800 CST
Updated at: 2020-11-02T11:21:23+08:00
Routes:
- route: Visiting URL: http://abc.kubevela.io IP: 47.242.68.137
```
* Check Status
```
$ vela status abc
About:
Name: abc
Namespace: default
Created at: 2020-11-02 11:17:28.067738 +0800 CST
Updated at: 2020-11-02 11:28:13.490986 +0800 CST
Services:
- Name: mysvc
Type: webservice
HEALTHY Ready: 1/1
Last Deployment:
Created at: 2020-11-02 11:17:28 +0800 CST
Updated at: 2020-11-02T11:28:13+08:00
Routes:
- route: Visiting URL: http://abc.kubevela.io IP: 47.242.68.137
```
* Delete App
```shell script
$ vela ls
SERVICE APP TYPE TRAITS STATUS CREATED-TIME
mysvc abc Deployed 2020-11-02 11:17:28 +0800 CST
$ vela delete abc
Deleting Application "abc"
delete apps succeed abc from default
```
You can try use your local built binaries follow [the documentation](https://kubevela.io/#/en/quick-start).
## Testing
@@ -158,7 +111,18 @@ make e2e-test
```
## Make a pull request
Remember to write unit-test and e2e test before making a pull request.
Remember to write unit-test and e2e-test after you have finished your code.
Run following checks before making a pull request.
```shell script
make reviewable
```
The command will do some lint checks and clean code.
After that, check in all changes and send a pull request.
## Merge Regulations

View File

@@ -8,7 +8,7 @@ VELA_GITVERSION_VAR := github.com/oam-dev/kubevela/version.GitRevision
LDFLAGS ?= "-X $(VELA_VERSION_VAR)=$(VELA_VERSION) -X $(VELA_GITVERSION_VAR)=$(GIT_COMMIT)"
GOX = go run github.com/mitchellh/gox
TARGETS := darwin/amd64 linux/amd64 windows/amd64
TARGETS := darwin/amd64 linux/amd64 windows/amd64 linux/arm64
DIST_DIRS := find * -type d -exec
TIME_LONG = `date +%Y-%m-%d' '%H:%M:%S`
@@ -37,37 +37,44 @@ endif
all: build
# Run tests
test: vet lint
test: vet lint staticcheck
go test -race -coverprofile=coverage.txt -covermode=atomic ./pkg/... ./cmd/...
@$(OK) unit-tests pass
# Build manager binary
build: fmt vet lint
build: fmt vet lint staticcheck
go run hack/chart/generate.go
go build -o bin/vela -ldflags ${LDFLAGS} cmd/vela/main.go
git checkout cmd/vela/fake/chart_source.go
@$(OK) build succeed
vela-cli:
go run hack/chart/generate.go
go build -o bin/vela -ldflags ${LDFLAGS} cmd/vela/main.go
git checkout cmd/vela/fake/chart_source.go
npm-build:
cd dashboard && npm run build && cd ./..
dashboard-build:
cd dashboard && yarn build && cd ./..
npm-install:
cd dashboard && npm install && cd ./..
dashboard-install:
cd dashboard && yarn && cd ./..
doc-gen:
rm -r docs/en/cli/*
go run hack/docgen/gen.go
go run hack/references/generate.go
api-gen:
swag init -g pkg/server/route.go --output pkg/server/docs
swagger-codegen generate -l html2 -i pkg/server/docs/swagger.yaml -o pkg/server/docs
mv pkg/server/docs/index.html docs/en/developers/references/restful-api/
generate-source:
go run hack/frontend/source.go
cross-build:
go run hack/chart/generate.go
GO111MODULE=on CGO_ENABLED=0 $(GOX) -ldflags $(LDFLAGS) -parallel=3 -output="_bin/{{.OS}}-{{.Arch}}/vela" -osarch='$(TARGETS)' ./cmd/vela/
GO111MODULE=on CGO_ENABLED=0 $(GOX) -ldflags $(LDFLAGS) -parallel=2 -output="_bin/{{.OS}}-{{.Arch}}/vela" -osarch='$(TARGETS)' ./cmd/vela/
compress:
( \
@@ -95,10 +102,13 @@ fmt: goimports installcue
vet:
go vet ./...
staticcheck: staticchecktool
$(STATICCHECK) ./...
lint: golangci
$(GOLANGCILINT) run ./...
reviewable: fmt vet lint manifests
reviewable: manifests fmt vet lint staticcheck
go mod tidy
# Execute auto-gen code commands and ensure branch is clean.
@@ -115,24 +125,25 @@ docker-push:
docker push ${IMG}
e2e-setup:
bin/vela install --image-pull-policy IfNotPresent --image-repo vela-core-test --image-tag $(GIT_COMMIT)
bin/vela install --set installCertManager=true --image-pull-policy IfNotPresent --image-repo vela-core-test --image-tag $(GIT_COMMIT)
ginkgo version
ginkgo -v -r e2e/setup
kubectl wait --for=condition=Ready pod -l app.kubernetes.io/name=vela-core,app.kubernetes.io/instance=kubevela -n vela-system --timeout=600s
bin/vela dashboard &
e2e-api-test:
# Run e2e test
ginkgo -v -skipPackage capability,setup,apiserver,application -r e2e
ginkgo -v -r e2e/apiserver
ginkgo -v -r e2e/application
e2e-test:
# Run e2e test
ginkgo -v -skipPackage capability,setup,apiserver -r e2e
ginkgo -v ./test/e2e-test
# integration test will clean environment, please don't put test behind it.
CGO_ENABLED=0 go test -timeout 1h -count=1 -v -tags 'integration' ./test/integration
@$(OK) tests pass
e2e-api-test:
# Run e2e test
ginkgo -v -r e2e/apiserver
e2e-cleanup:
# Clean up
rm -rf ~/.vela
@@ -178,7 +189,7 @@ manifests:
go generate $(foreach t,pkg apis,./$(t)/...)
./hack/vela-templates/gen_definitions.sh
GOLANGCILINT_VERSION ?= v1.29.0
GOLANGCILINT_VERSION ?= v1.31.0
HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]')
HOSTARCH := $(shell uname -m)
ifeq ($(HOSTARCH),x86_64)
@@ -198,6 +209,19 @@ else
GOLANGCILINT=$(shell which golangci-lint)
endif
.PHONY: staticchecktool
staticchecktool:
ifeq (, $(shell which staticcheck))
@{ \
set -e ;\
echo 'installing honnef.co/go/tools/cmd/staticcheck ' ;\
GO111MODULE=off go get honnef.co/go/tools/cmd/staticcheck ;\
}
STATICCHECK=$(GOBIN)/staticcheck
else
STATICCHECK=$(shell which staticcheck)
endif
.PHONY: goimports
goimports:
ifeq (, $(shell which goimports))
@@ -220,4 +244,11 @@ ifeq (, $(shell which cue))
CUE=$(GOBIN)/cue
else
CUE=$(shell which cue)
endif
endif
start-dashboard:
go run pkg/server/main/startAPIServer.go &
cd dashboard && yarn && yarn start && cd ..
swagger-gen:
$(GOBIN)/swag init -g server/route.go -d pkg/ -o pkg/server/docs/

8
OWNERS
View File

@@ -1,8 +1,12 @@
approvers:
- kubevela-controller
- kubevela-devex
- kubevela-dashboard-approver
reviewers:
- kubevela-controller
- kubevela-dashboard
- oam-spec
- oam-spec
- kubevela-dashboard-reviewer
members:
- community-collaborators

View File

@@ -3,11 +3,14 @@ aliases:
- hongchaodeng
- wonderflow
kubevela-dashboard:
kubevela-dashboard-approver:
- zzxwill
- hanxie-crypto
- hongchaodeng
kubevela-dashboard-reviewer:
- sunny0826
- hanxie-crypto
kubevela-controller:
- resouer
- wonderflow
@@ -19,7 +22,6 @@ aliases:
oam-spec: # inherit from https://github.com/oam-dev/spec/blob/master/OWNERS.md
- hongchaodeng
- resouer
- vturecek
community-collaborators:
- Fei-Guo

View File

@@ -13,18 +13,28 @@
# KubeVela
For developers, KubeVela is an easy-to-use tool that enables them to describe and ship their applications to Kubernetes with minimal effort.
For developers, KubeVela is an easy-to-use yet extensible platform that enables them to design and ship applications with minimal effort.
For platform builders, KubeVela serves as a framework that empowers them to create developer facing yet highly extensible platforms at ease.
For platform builders, KubeVela is the core engine that empowers them to create above platform with ease.
- Slack: [Discuss](https://cloud-native.slack.com/archives/C01BLQ3HTJA)
- Gitter: [Community](https://gitter.im/oam-dev/community)
## Community
- Slack: [CNCF Slack](https://slack.cncf.io/) #kubevela channel
- Gitter: [Discussion](https://gitter.im/oam-dev/community)
> NOTE: KubeVela is still in early stage and iterating quickly. It's currently under preview release.
## How It Works?
![alt](docs/resources/how-it-works.png)
## Quick Start
Quick start guides are available on [this section](https://kubevela.io/#/en/quick-start).
Quick start guides for developers are available on [this section](https://kubevela.io/#/en/quick-start).
## Platform Builder Guide
Detailed guides for platform teams are available on [this section](https://kubevela.io/#/en/platform-engineers/overview).
## Documentation

View File

@@ -17,21 +17,34 @@ limitations under the License.
package v1alpha2
import (
runtimev1alpha1 "github.com/crossplane/crossplane-runtime/apis/core/v1alpha1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/oam-dev/kubevela/apis/standard.oam.dev/v1alpha1"
)
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
// ApplicationDeploymentSpec defines the desired state of ApplicationDeployment
// ApplicationDeploymentSpec defines how to describe an upgrade between different application
type ApplicationDeploymentSpec struct {
// TODO add spec here
}
// TargetApplicationName contains the name of the application that we need to upgrade to.
// We assume that an application is immutable, thus the name alone is suffice
TargetApplicationName string `json:"targetApplicationName"`
// ApplicationDeploymentStatus defines the observed state of ApplicationDeployment
type ApplicationDeploymentStatus struct {
// TODO add status field here
runtimev1alpha1.ConditionedStatus `json:",inline"`
// SourceApplicationName contains the name of the application that we need to upgrade from.
// it can be empty only when it's the first time to deploy the application
SourceApplicationName string `json:"sourceApplicationName"`
// 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, default is false
// It will remove the target application from the kubernetes
// +optional
RevertOnDelete *bool `json:"revertOnDelete,omitempty"`
}
// ApplicationDeployment is the Schema for the ApplicationDeployment API
@@ -42,8 +55,8 @@ type ApplicationDeployment struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec ApplicationDeploymentSpec `json:"spec,omitempty"`
Status ApplicationDeploymentStatus `json:"status,omitempty"`
Spec ApplicationDeploymentSpec `json:"spec,omitempty"`
Status v1alpha1.RolloutStatus `json:"status,omitempty"`
}
// ApplicationDeploymentList contains a list of ApplicationDeployment

View File

@@ -30,6 +30,8 @@ import (
type ApplicationPhase string
const (
// ApplicationRollingOut means the app is in the middle of rolling out
ApplicationRollingOut ApplicationPhase = "rollingOut"
// ApplicationRendering means the app is rendering
ApplicationRendering ApplicationPhase = "rendering"
// ApplicationRunning means the app finished rendering and applied result to the cluster
@@ -44,6 +46,39 @@ type AppStatus struct {
runtimev1alpha1.ConditionedStatus `json:",inline"`
Phase ApplicationPhase `json:"status,omitempty"`
// Components record the related Components created by Application Controller
Components []runtimev1alpha1.TypedReference `json:"components,omitempty"`
}
// ApplicationTrait defines the trait of application
type ApplicationTrait struct {
Name string `json:"name"`
// +kubebuilder:pruning:PreserveUnknownFields
Properties runtime.RawExtension `json:"properties"`
}
// ApplicationComponent describe the component of application
type ApplicationComponent struct {
Name string `json:"name"`
WorkloadType string `json:"type"`
// +kubebuilder:pruning:PreserveUnknownFields
Settings runtime.RawExtension `json:"settings"`
// Traits define the trait of one component, the type must be array to keep the order.
Traits []ApplicationTrait `json:"traits,omitempty"`
// +kubebuilder:pruning:PreserveUnknownFields
// scopes in ApplicationComponent defines the component-level scopes
// the format is <scope-type:scope-instance-name> pairs, the key represents type of `ScopeDefinition` while the value represent the name of scope instance.
Scopes map[string]string `json:"scopes,omitempty"`
}
// ApplicationSpec is the spec of Application
type ApplicationSpec struct {
Components []ApplicationComponent `json:"components"`
// TODO(wonderflow): we should have application level scopes supported here
}
// +kubebuilder:object:root=true
@@ -54,9 +89,8 @@ type Application struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
// +kubebuilder:pruning:PreserveUnknownFields
Spec runtime.RawExtension `json:"spec,omitempty"`
Status AppStatus `json:"status,omitempty"`
Spec ApplicationSpec `json:"spec,omitempty"`
Status AppStatus `json:"status,omitempty"`
}
// +kubebuilder:object:root=true
@@ -68,6 +102,12 @@ type ApplicationList struct {
Items []Application `json:"items"`
}
func init() {
SchemeBuilder.Register(&Application{}, &ApplicationList{})
// GetComponent get the component from the application based on its workload type
func (app *Application) GetComponent(workloadType string) *ApplicationComponent {
for _, c := range app.Spec.Components {
if c.WorkloadType == workloadType {
return &c
}
}
return nil
}

View File

@@ -0,0 +1,52 @@
package v1alpha2
import (
"reflect"
"testing"
)
func TestApplication_GetComponent(t *testing.T) {
ac1 := ApplicationComponent{
Name: "ac1",
WorkloadType: "type1",
}
ac2 := ApplicationComponent{
Name: "ac2",
WorkloadType: "type2",
}
tests := map[string]struct {
app *Application
componentName string
want *ApplicationComponent
}{
"test get one": {
app: &Application{
Spec: ApplicationSpec{
Components: []ApplicationComponent{
ac1, ac2,
},
},
},
componentName: ac1.WorkloadType,
want: &ac1,
},
"test get none": {
app: &Application{
Spec: ApplicationSpec{
Components: []ApplicationComponent{
ac2,
},
},
},
componentName: ac1.WorkloadType,
want: nil,
},
}
for name, tt := range tests {
t.Run(name, func(t *testing.T) {
if got := tt.app.GetComponent(tt.componentName); !reflect.DeepEqual(got, tt.want) {
t.Errorf("GetComponent() = %v, want %v", got, tt.want)
}
})
}
}

View File

@@ -97,7 +97,7 @@ type WorkloadDefinitionList struct {
// A TraitDefinitionSpec defines the desired state of a TraitDefinition.
type TraitDefinitionSpec struct {
// Reference to the CustomResourceDefinition that defines this trait kind.
Reference DefinitionReference `json:"definitionRef"`
Reference DefinitionReference `json:"definitionRef,omitempty"`
// Revision indicates whether a trait is aware of component revision
// +optional
@@ -114,6 +114,18 @@ type TraitDefinitionSpec struct {
// +optional
AppliesToWorkloads []string `json:"appliesToWorkloads,omitempty"`
// ConflictsWith specifies the list of traits(CRD name, Definition name, CRD group)
// which could not apply to the same workloads with this trait.
// Traits that omit this field can work with any other traits.
// Example rules:
// "service" # Trait definition name
// "services.k8s.io" # API resource/crd name
// "*.networking.k8s.io" # API group
// "labelSelector:foo=bar" # label selector
// labelSelector format: https://pkg.go.dev/k8s.io/apimachinery/pkg/labels#Parse
// +optional
ConflictsWith []string `json:"conflictsWith,omitempty"`
// Extension is used for extension needs by OAM platform builders
// +optional
// +kubebuilder:pruning:PreserveUnknownFields
@@ -504,6 +516,12 @@ type DataInput struct {
// ToFieldPaths specifies the field paths of an object to fill passed value.
ToFieldPaths []string `json:"toFieldPaths,omitempty"`
// StrategyMergeKeys specifies the merge key if the toFieldPaths target is an array.
// The StrategyMergeKeys is optional, by default, if the toFieldPaths target is an array, we will append.
// If StrategyMergeKeys specified, we will check the key in the target array.
// If any key exist, do update; if no key exist, append.
StrategyMergeKeys []string `json:"strategyMergeKeys,omitempty"`
}
// DataInputValueFrom specifies the value source for a data input.

View File

@@ -101,6 +101,22 @@ var (
HealthScopeGroupVersionKind = SchemeGroupVersion.WithKind(HealthScopeKind)
)
// Application type metadata.
var (
ApplicationKind = reflect.TypeOf(Application{}).Name()
ApplicationGroupKind = schema.GroupKind{Group: Group, Kind: ApplicationKind}.String()
ApplicationKindAPIVersion = ApplicationKind + "." + SchemeGroupVersion.String()
ApplicationKindVersionKind = SchemeGroupVersion.WithKind(ApplicationKind)
)
// Application type metadata.
var (
ApplicationDeploymentKind = reflect.TypeOf(ApplicationDeployment{}).Name()
ApplicationDeploymentGroupKind = schema.GroupKind{Group: Group, Kind: ApplicationDeploymentKind}.String()
ApplicationDeploymentKindAPIVersion = ApplicationKind + "." + SchemeGroupVersion.String()
ApplicationDeploymentKindVersionKind = SchemeGroupVersion.WithKind(ApplicationDeploymentKind)
)
func init() {
SchemeBuilder.Register(&WorkloadDefinition{}, &WorkloadDefinitionList{})
SchemeBuilder.Register(&TraitDefinition{}, &TraitDefinitionList{})
@@ -110,5 +126,6 @@ func init() {
SchemeBuilder.Register(&ContainerizedWorkload{}, &ContainerizedWorkloadList{})
SchemeBuilder.Register(&ManualScalerTrait{}, &ManualScalerTraitList{})
SchemeBuilder.Register(&HealthScope{}, &HealthScopeList{})
SchemeBuilder.Register(&Application{}, &ApplicationList{})
SchemeBuilder.Register(&ApplicationDeployment{}, &ApplicationDeploymentList{})
}

View File

@@ -1,7 +1,7 @@
// +build !ignore_autogenerated
/*
Copyright 2020 The KubeVela Authors.
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.
@@ -29,6 +29,11 @@ import (
func (in *AppStatus) DeepCopyInto(out *AppStatus) {
*out = *in
in.ConditionedStatus.DeepCopyInto(&out.ConditionedStatus)
if in.Components != nil {
in, out := &in.Components, &out.Components
*out = make([]v1alpha1.TypedReference, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AppStatus.
@@ -68,6 +73,36 @@ func (in *Application) DeepCopyObject() runtime.Object {
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ApplicationComponent) DeepCopyInto(out *ApplicationComponent) {
*out = *in
in.Settings.DeepCopyInto(&out.Settings)
if in.Traits != nil {
in, out := &in.Traits, &out.Traits
*out = make([]ApplicationTrait, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.Scopes != nil {
in, out := &in.Scopes, &out.Scopes
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationComponent.
func (in *ApplicationComponent) DeepCopy() *ApplicationComponent {
if in == nil {
return nil
}
out := new(ApplicationComponent)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ApplicationConfiguration) DeepCopyInto(out *ApplicationConfiguration) {
*out = *in
@@ -229,7 +264,7 @@ func (in *ApplicationDeployment) DeepCopyInto(out *ApplicationDeployment) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
out.Spec = in.Spec
in.Spec.DeepCopyInto(&out.Spec)
in.Status.DeepCopyInto(&out.Status)
}
@@ -286,6 +321,17 @@ func (in *ApplicationDeploymentList) DeepCopyObject() runtime.Object {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ApplicationDeploymentSpec) DeepCopyInto(out *ApplicationDeploymentSpec) {
*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 ApplicationDeploymentSpec.
@@ -298,22 +344,6 @@ func (in *ApplicationDeploymentSpec) DeepCopy() *ApplicationDeploymentSpec {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ApplicationDeploymentStatus) DeepCopyInto(out *ApplicationDeploymentStatus) {
*out = *in
in.ConditionedStatus.DeepCopyInto(&out.ConditionedStatus)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationDeploymentStatus.
func (in *ApplicationDeploymentStatus) DeepCopy() *ApplicationDeploymentStatus {
if in == nil {
return nil
}
out := new(ApplicationDeploymentStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ApplicationList) DeepCopyInto(out *ApplicationList) {
*out = *in
@@ -346,6 +376,44 @@ func (in *ApplicationList) DeepCopyObject() runtime.Object {
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ApplicationSpec) DeepCopyInto(out *ApplicationSpec) {
*out = *in
if in.Components != nil {
in, out := &in.Components, &out.Components
*out = make([]ApplicationComponent, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationSpec.
func (in *ApplicationSpec) DeepCopy() *ApplicationSpec {
if in == nil {
return nil
}
out := new(ApplicationSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ApplicationTrait) DeepCopyInto(out *ApplicationTrait) {
*out = *in
in.Properties.DeepCopyInto(&out.Properties)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationTrait.
func (in *ApplicationTrait) DeepCopy() *ApplicationTrait {
if in == nil {
return nil
}
out := new(ApplicationTrait)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CPUResources) DeepCopyInto(out *CPUResources) {
*out = *in
@@ -941,6 +1009,11 @@ func (in *DataInput) DeepCopyInto(out *DataInput) {
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.StrategyMergeKeys != nil {
in, out := &in.StrategyMergeKeys, &out.StrategyMergeKeys
*out = make([]string, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataInput.
@@ -1616,6 +1689,11 @@ func (in *TraitDefinitionSpec) DeepCopyInto(out *TraitDefinitionSpec) {
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.ConflictsWith != nil {
in, out := &in.ConflictsWith, &out.ConflictsWith
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.Extension != nil {
in, out := &in.Extension, &out.Extension
*out = new(runtime.RawExtension)

View File

@@ -18,7 +18,6 @@ package v1alpha1
import (
"github.com/crossplane/crossplane-runtime/apis/core/v1alpha1"
runtimev1alpha1 "github.com/crossplane/crossplane-runtime/apis/core/v1alpha1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
@@ -91,7 +90,7 @@ type AutoscalerSpec struct {
TargetWorkload TargetWorkload `json:"targetWorkload,omitempty"`
// WorkloadReference marks the owner of the workload
WorkloadReference runtimev1alpha1.TypedReference `json:"workloadRef,omitempty"`
WorkloadReference v1alpha1.TypedReference `json:"workloadRef,omitempty"`
}
// TargetWorkload holds the a reference to the scale target Object
@@ -105,7 +104,7 @@ type TargetWorkload struct {
// AutoscalerStatus defines the observed state of Autoscaler
type AutoscalerStatus struct {
runtimev1alpha1.ConditionedStatus `json:",inline"`
v1alpha1.ConditionedStatus `json:",inline"`
}
// +kubebuilder:object:root=true

View File

@@ -24,9 +24,16 @@ import (
"sigs.k8s.io/controller-runtime/pkg/scheme"
)
const (
// GroupName of the CRDs
GroupName = "standard.oam.dev"
// Version of the group of CRDs
Version = "v1alpha1"
)
var (
// SchemeGroupVersion is group version used to register these objects
SchemeGroupVersion = schema.GroupVersion{Group: "standard.oam.dev", Version: "v1alpha1"}
SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: Version}
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion}

View File

@@ -0,0 +1,233 @@
package v1alpha1
import (
runtimev1alpha1 "github.com/crossplane/crossplane-runtime/apis/core/v1alpha1"
"k8s.io/apimachinery/pkg/util/intstr"
)
// RolloutStrategyType defines strategies for pods rollout
type RolloutStrategyType string
const (
// IncreaseFirstRolloutStrategyType indicates that we increase the target resources first
IncreaseFirstRolloutStrategyType RolloutStrategyType = "IncreaseFirst"
// DecreaseFirstRolloutStrategyType indicates that we decrease the source resources first
DecreaseFirstRolloutStrategyType RolloutStrategyType = "DecreaseFirst"
)
// HookType can be pre, post or during rollout
type HookType string
const (
// InitializeRolloutHook execute webhook during the rollout initializing phase
InitializeRolloutHook HookType = "initilize-rollout"
// PreBatchRolloutHook execute webhook before each batch rollout
PreBatchRolloutHook HookType = "pre-batch-rollout"
// PostBatchRolloutHook execute webhook after each batch rollout
PostBatchRolloutHook HookType = "post-batch-rollout"
// FinalizeRolloutHook execute the webhook during the rollout finalizing phase
FinalizeRolloutHook HookType = "finalize-rollout"
)
// RollingState is the overall rollout state
type RollingState string
const (
// Verifying verify that the rollout setting is valid and the controller can locate both the
// target and the source
Verifying RollingState = "verifying"
// Initializing rollout is initializing all the new resources
Initializing RollingState = "initializing"
// Rolling rolling out
Rolling RollingState = "rolling"
// Finalising finalize the rolling, possibly clean up the old resources, adjust traffic
Finalising RollingState = "finalising"
// Succeed rollout successfully completed to match the desired target state
Succeed RollingState = "succeed"
// Failed rollout is failed, the target replica is not reached
// we can not move forward anymore
// we will let the client to decide when or whether to revert
Failed RollingState = "failed"
)
// BatchRollingState is the sub state when the rollout is on the fly
type BatchRollingState string
const (
// BatchRolling still rolling the batch, the batch rolling is not completed yet
BatchRolling BatchRollingState = "batchRolling"
// BatchStopped rollout is stopped, the batch rolling is not completed
BatchStopped BatchRollingState = "batchStopped"
// BatchReady the pods in the batch are ready. Wait for auto or manual verification.
BatchReady BatchRollingState = "batchReady"
// BatchVerifying verifying if the application is ready to roll. This happens when it's either manual or
// automatic with analysis
BatchVerifying RollingState = "batchVerifying"
// BatchAvailable one batch is ready, we could move to the batch
BatchAvailable BatchRollingState = "batchAvailable"
)
// RolloutPlan fines the details of the rollout plan
type RolloutPlan struct {
// RolloutStrategy defines strategies for the rollout plan
// +optional
RolloutStrategy *RolloutStrategyType `json:"rolloutStrategy,omitempty"`
// The size of the target resource. The default is the same
// as the size of the source resource.
// +optional
TargetSize *int32 `json:"targetSize,omitempty"`
// The number of batches, default = 1
// mutually exclusive to RolloutBatches
// +optional
NumBatches *int32 `json:"numBatches,omitempty"`
// The exact distribution among batches.
// mutually exclusive to NumBatches
// +optional
RolloutBatches []RolloutBatch `json:"rolloutBatches,omitempty"`
// 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
// +optional
BatchPartition *int32 `json:"lastBatchToRollout,omitempty"`
// Paused the rollout, default is false
// +optional
Paused bool `json:"paused,omitempty"`
// RolloutWebhooks provides a way for the rollout to interact with an external process
// +optional
RolloutWebhooks []RolloutWebhook `json:"rolloutWebhooks,omitempty"`
// CanaryMetric provides a way for the rollout process to automatically check certain metrics
// before complete the process
// +optional
CanaryMetric []CanaryMetric `json:"canaryMetric,omitempty"`
}
// RolloutBatch is used to describe how the each batch rollout should be
type RolloutBatch struct {
// 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
// +optional
// it is mutually exclusive with the PodList field
Replicas intstr.IntOrString `json:"replicas,omitempty"`
// The list of Pods to get upgraded
// +optional
// it is mutually exclusive with the Replicas field
PodList []string `json:"podList,omitempty"`
// 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
// +optional
MaxUnavailable *intstr.IntOrString `json:"maxUnavailable,omitempty"`
// The wait time, in seconds, between instances upgrades, default = 0
// +optional
InstanceInterval *int32 `json:"instanceInterval,omitempty"`
// RolloutWebhooks provides a way for the batch rollout to interact with an external process
// +optional
BatchRolloutWebhooks []RolloutWebhook `json:"batchRolloutWebhooks,omitempty"`
// CanaryMetric provides a way for the batch rollout process to automatically check certain metrics
// before moving to the next batch
// +optional
CanaryMetric []CanaryMetric `json:"canaryMetric,omitempty"`
}
// RolloutWebhook holds the reference to external checks used for canary analysis
type RolloutWebhook struct {
// Type of this webhook
Type HookType `json:"type"`
// Name of this webhook
Name string `json:"name"`
// URL address of this webhook
URL string `json:"url"`
// Request timeout for this webhook
Timeout string `json:"timeout,omitempty"`
// Metadata (key-value pairs) for this webhook
// +optional
Metadata *map[string]string `json:"metadata,omitempty"`
}
// RolloutWebhookPayload holds the info and metadata sent to webhooks
type RolloutWebhookPayload struct {
// ResourceRef refers to the resource we are operating on
ResourceRef *runtimev1alpha1.TypedReference `json:"resourceRef"`
// RolloutRef refers to the rollout that is controlling the rollout
RolloutRef *runtimev1alpha1.TypedReference `json:"rolloutRef"`
// Metadata (key-value pairs) are the extra data send to this webhook
Metadata map[string]string `json:"metadata,omitempty"`
}
// CanaryMetric holds the reference to metrics used for canary analysis
type CanaryMetric struct {
// Name of the metric
Name string `json:"name"`
// Interval represents the windows size
Interval string `json:"interval,omitempty"`
// Range value accepted for this metric
// +optional
MetricsRange *MetricsExpectedRange `json:"metricsRange,omitempty"`
// TemplateRef references a metric template object
// +optional
TemplateRef *runtimev1alpha1.TypedReference `json:"templateRef,omitempty"`
}
// MetricsExpectedRange defines the range used for metrics validation
type MetricsExpectedRange struct {
// Minimum value
// +optional
Min *intstr.IntOrString `json:"min,omitempty"`
// Maximum value
// +optional
Max *intstr.IntOrString `json:"max,omitempty"`
}
// RolloutStatus defines the observed state of Rollout
type RolloutStatus struct {
// Conditions represents the latest available observations of a CloneSet's current state.
runtimev1alpha1.ConditionedStatus `json:",inline"`
// The target resource generation
TargetGeneration string `json:"targetGeneration"`
// The source resource generation
SourceGeneration string `json:"sourceGeneration"`
// RollingState is the Rollout State
RollingState RollingState `json:"rollingState"`
// BatchRollingState only meaningful when the Status is rolling
// +optional
BatchRollingState BatchRollingState `json:"batchRollingState"`
// The current batch the rollout is working on/blocked
CurrentBatch int32 `json:"currentBatch"`
// UpgradedReplicas is the number of Pods upgraded by the rollout controller
UpgradedReplicas int32 `json:"upgradedReplicas"`
// UpgradedReplicas is the number of Pods upgraded by the rollout controller that have a Ready Condition.
UpgradedReadyReplicas int32 `json:"upgradedReadyReplicas"`
}

View File

@@ -0,0 +1,71 @@
package v1alpha1
import (
runtimev1alpha1 "github.com/crossplane/crossplane-runtime/apis/core/v1alpha1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/oam-dev/kubevela/pkg/oam"
)
// RolloutTraitSpec defines the desired state of RolloutTrait
type RolloutTraitSpec struct {
// TargetRef references a target resource that contains the newer version
// of the software. We assumed that new resource already exists.
// This is the only resource we work on if the resource is a stateful resource (cloneset/statefulset)
TargetRef runtimev1alpha1.TypedReference `json:"targetRef"`
// SourceRef references the list of resources that contains the older version
// of the software. We assume that it's the first time to deploy when we cannot find any source.
// +optional
SourceRef []runtimev1alpha1.TypedReference `json:"sourceRef,omitempty"`
// RolloutPlan is the details on how to rollout the resources
RolloutPlan RolloutPlan `json:"rolloutPlan"`
}
// RolloutTrait is the Schema for the RolloutTrait API
// +kubebuilder:object:root=true
// +genclient
// +kubebuilder:subresource:status
type RolloutTrait struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec RolloutTraitSpec `json:"spec,omitempty"`
Status RolloutStatus `json:"status,omitempty"`
}
// RolloutTraitList contains a list of RolloutTrait
// +kubebuilder:object:root=true
// +genclient
type RolloutTraitList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []RolloutTrait `json:"items"`
}
func init() {
SchemeBuilder.Register(&RolloutTrait{}, &RolloutTraitList{})
}
var _ oam.Trait = &RolloutTrait{}
// SetConditions for set CR condition
func (tr *RolloutTrait) SetConditions(c ...runtimev1alpha1.Condition) {
tr.Status.SetConditions(c...)
}
// GetCondition for get CR condition
func (tr *RolloutTrait) GetCondition(c runtimev1alpha1.ConditionType) runtimev1alpha1.Condition {
return tr.Status.GetCondition(c)
}
// GetWorkloadReference of this MetricsTrait.
func (tr *RolloutTrait) GetWorkloadReference() runtimev1alpha1.TypedReference {
return tr.Spec.TargetRef
}
// SetWorkloadReference of this MetricsTrait.
func (tr *RolloutTrait) SetWorkloadReference(r runtimev1alpha1.TypedReference) {
tr.Spec.TargetRef = r
}

View File

@@ -1,7 +1,7 @@
// +build !ignore_autogenerated
/*
Copyright 2020 The KubeVela Authors.
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.
@@ -23,6 +23,7 @@ package v1alpha1
import (
corev1alpha1 "github.com/crossplane/crossplane-runtime/apis/core/v1alpha1"
runtime "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/intstr"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
@@ -170,6 +171,56 @@ func (in *BackendServiceRef) DeepCopy() *BackendServiceRef {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CanaryMetric) DeepCopyInto(out *CanaryMetric) {
*out = *in
if in.MetricsRange != nil {
in, out := &in.MetricsRange, &out.MetricsRange
*out = new(MetricsExpectedRange)
(*in).DeepCopyInto(*out)
}
if in.TemplateRef != nil {
in, out := &in.TemplateRef, &out.TemplateRef
*out = new(corev1alpha1.TypedReference)
**out = **in
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CanaryMetric.
func (in *CanaryMetric) DeepCopy() *CanaryMetric {
if in == nil {
return nil
}
out := new(CanaryMetric)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *MetricsExpectedRange) DeepCopyInto(out *MetricsExpectedRange) {
*out = *in
if in.Min != nil {
in, out := &in.Min, &out.Min
*out = new(intstr.IntOrString)
**out = **in
}
if in.Max != nil {
in, out := &in.Max, &out.Max
*out = new(intstr.IntOrString)
**out = **in
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetricsExpectedRange.
func (in *MetricsExpectedRange) DeepCopy() *MetricsExpectedRange {
if in == nil {
return nil
}
out := new(MetricsExpectedRange)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *MetricsTrait) DeepCopyInto(out *MetricsTrait) {
*out = *in
@@ -371,6 +422,262 @@ func (in *PodSpecWorkloadStatus) DeepCopy() *PodSpecWorkloadStatus {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *RolloutBatch) DeepCopyInto(out *RolloutBatch) {
*out = *in
out.Replicas = in.Replicas
if in.PodList != nil {
in, out := &in.PodList, &out.PodList
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.MaxUnavailable != nil {
in, out := &in.MaxUnavailable, &out.MaxUnavailable
*out = new(intstr.IntOrString)
**out = **in
}
if in.InstanceInterval != nil {
in, out := &in.InstanceInterval, &out.InstanceInterval
*out = new(int32)
**out = **in
}
if in.BatchRolloutWebhooks != nil {
in, out := &in.BatchRolloutWebhooks, &out.BatchRolloutWebhooks
*out = make([]RolloutWebhook, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.CanaryMetric != nil {
in, out := &in.CanaryMetric, &out.CanaryMetric
*out = make([]CanaryMetric, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RolloutBatch.
func (in *RolloutBatch) DeepCopy() *RolloutBatch {
if in == nil {
return nil
}
out := new(RolloutBatch)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *RolloutPlan) DeepCopyInto(out *RolloutPlan) {
*out = *in
if in.RolloutStrategy != nil {
in, out := &in.RolloutStrategy, &out.RolloutStrategy
*out = new(RolloutStrategyType)
**out = **in
}
if in.TargetSize != nil {
in, out := &in.TargetSize, &out.TargetSize
*out = new(int32)
**out = **in
}
if in.NumBatches != nil {
in, out := &in.NumBatches, &out.NumBatches
*out = new(int32)
**out = **in
}
if in.RolloutBatches != nil {
in, out := &in.RolloutBatches, &out.RolloutBatches
*out = make([]RolloutBatch, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.BatchPartition != nil {
in, out := &in.BatchPartition, &out.BatchPartition
*out = new(int32)
**out = **in
}
if in.RolloutWebhooks != nil {
in, out := &in.RolloutWebhooks, &out.RolloutWebhooks
*out = make([]RolloutWebhook, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.CanaryMetric != nil {
in, out := &in.CanaryMetric, &out.CanaryMetric
*out = make([]CanaryMetric, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RolloutPlan.
func (in *RolloutPlan) DeepCopy() *RolloutPlan {
if in == nil {
return nil
}
out := new(RolloutPlan)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *RolloutStatus) DeepCopyInto(out *RolloutStatus) {
*out = *in
in.ConditionedStatus.DeepCopyInto(&out.ConditionedStatus)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RolloutStatus.
func (in *RolloutStatus) DeepCopy() *RolloutStatus {
if in == nil {
return nil
}
out := new(RolloutStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *RolloutTrait) DeepCopyInto(out *RolloutTrait) {
*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 RolloutTrait.
func (in *RolloutTrait) DeepCopy() *RolloutTrait {
if in == nil {
return nil
}
out := new(RolloutTrait)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *RolloutTrait) 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 *RolloutTraitList) DeepCopyInto(out *RolloutTraitList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]RolloutTrait, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RolloutTraitList.
func (in *RolloutTraitList) DeepCopy() *RolloutTraitList {
if in == nil {
return nil
}
out := new(RolloutTraitList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *RolloutTraitList) 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 *RolloutTraitSpec) DeepCopyInto(out *RolloutTraitSpec) {
*out = *in
out.TargetRef = in.TargetRef
if in.SourceRef != nil {
in, out := &in.SourceRef, &out.SourceRef
*out = make([]corev1alpha1.TypedReference, len(*in))
copy(*out, *in)
}
in.RolloutPlan.DeepCopyInto(&out.RolloutPlan)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RolloutTraitSpec.
func (in *RolloutTraitSpec) DeepCopy() *RolloutTraitSpec {
if in == nil {
return nil
}
out := new(RolloutTraitSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *RolloutWebhook) DeepCopyInto(out *RolloutWebhook) {
*out = *in
if in.Metadata != nil {
in, out := &in.Metadata, &out.Metadata
*out = new(map[string]string)
if **in != nil {
in, out := *in, *out
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RolloutWebhook.
func (in *RolloutWebhook) DeepCopy() *RolloutWebhook {
if in == nil {
return nil
}
out := new(RolloutWebhook)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *RolloutWebhookPayload) DeepCopyInto(out *RolloutWebhookPayload) {
*out = *in
if in.ResourceRef != nil {
in, out := &in.ResourceRef, &out.ResourceRef
*out = new(corev1alpha1.TypedReference)
**out = **in
}
if in.RolloutRef != nil {
in, out := &in.RolloutRef, &out.RolloutRef
*out = new(corev1alpha1.TypedReference)
**out = **in
}
if in.Metadata != nil {
in, out := &in.Metadata, &out.Metadata
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RolloutWebhookPayload.
func (in *RolloutWebhookPayload) DeepCopy() *RolloutWebhookPayload {
if in == nil {
return nil
}
out := new(RolloutWebhookPayload)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Route) DeepCopyInto(out *Route) {
*out = *in

View File

@@ -88,6 +88,14 @@ const (
TypeScope CapType = "scope"
)
// CapabilityCategory defines the category of a capability
type CapabilityCategory string
const (
// TerraformCategory means the capability is in Terraform format
TerraformCategory CapabilityCategory = "terraform"
)
// Parameter defines a parameter for cli from capability template
type Parameter struct {
Name string `json:"name"`

View File

@@ -50,6 +50,11 @@ spec:
items:
description: DataInput specifies a data input sink to an object. If input is array, it will be appended to the target field paths.
properties:
strategyMergeKeys:
description: StrategyMergeKeys specifies the merge key if the toFieldPaths target is an array. The StrategyMergeKeys is optional, by default, if the toFieldPaths target is an array, we will append. If StrategyMergeKeys specified, we will check the key in the target array. If any key exist, do update; if no key exist, append.
items:
type: string
type: array
toFieldPaths:
description: ToFieldPaths specifies the field paths of an object to fill passed value.
items:
@@ -166,6 +171,11 @@ spec:
items:
description: DataInput specifies a data input sink to an object. If input is array, it will be appended to the target field paths.
properties:
strategyMergeKeys:
description: StrategyMergeKeys specifies the merge key if the toFieldPaths target is an array. The StrategyMergeKeys is optional, by default, if the toFieldPaths target is an array, we will append. If StrategyMergeKeys specified, we will check the key in the target array. If any key exist, do update; if no key exist, append.
items:
type: string
type: array
toFieldPaths:
description: ToFieldPaths specifies the field paths of an object to fill passed value.
items:

View File

@@ -32,11 +32,241 @@ spec:
metadata:
type: object
spec:
description: ApplicationDeploymentSpec defines the desired state of ApplicationDeployment
description: ApplicationDeploymentSpec defines how to describe an upgrade between different application
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, default is false It will remove the target application from the kubernetes
type: boolean
rolloutPlan:
description: RolloutPlan is the details on how to rollout the resources
properties:
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: APIVersion of the referenced object.
type: string
kind:
description: Kind of the referenced object.
type: string
name:
description: Name of the referenced object.
type: string
uid:
description: UID of the referenced object.
type: string
required:
- apiVersion
- kind
- name
type: object
required:
- name
type: object
type: array
lastBatchToRollout:
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
numBatches:
description: The number of batches, default = 1 mutually exclusive to RolloutBatches
format: int32
type: integer
paused:
description: Paused the rollout, default is false
type: boolean
rolloutBatches:
description: The exact distribution among batches. mutually exclusive to NumBatches
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:
metadata:
additionalProperties:
type: string
description: Metadata (key-value pairs) for this webhook
type: object
name:
description: Name of this webhook
type: string
timeout:
description: Request timeout for 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: APIVersion of the referenced object.
type: string
kind:
description: Kind of the referenced object.
type: string
name:
description: Name of the referenced object.
type: string
uid:
description: UID of the referenced object.
type: string
required:
- apiVersion
- kind
- name
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 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
type: string
rolloutWebhooks:
description: RolloutWebhooks provides 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:
metadata:
additionalProperties:
type: string
description: Metadata (key-value pairs) for this webhook
type: object
name:
description: Name of this webhook
type: string
timeout:
description: Request timeout for 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
sourceApplicationName:
description: SourceApplicationName contains the name of the application that we need to upgrade from. it can be empty only when it's the first time to deploy the application
type: string
targetApplicationName:
description: TargetApplicationName contains the name of the application that we need to upgrade to. We assume that an application is immutable, thus the name alone is suffice
type: string
required:
- rolloutPlan
- sourceApplicationName
- targetApplicationName
type: object
status:
description: ApplicationDeploymentStatus defines the observed state of ApplicationDeployment
description: RolloutStatus defines the observed state of Rollout
properties:
batchRollingState:
description: BatchRollingState only meaningful when the Status is rolling
type: string
conditions:
description: Conditions of the resource.
items:
@@ -65,6 +295,34 @@ spec:
- type
type: object
type: array
currentBatch:
description: The current batch the rollout is working on/blocked
format: int32
type: integer
rollingState:
description: RollingState is the Rollout State
type: string
sourceGeneration:
description: The source resource generation
type: string
targetGeneration:
description: The target resource generation
type: string
upgradedReadyReplicas:
description: UpgradedReplicas 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
- rollingState
- sourceGeneration
- targetGeneration
- upgradedReadyReplicas
- upgradedReplicas
type: object
type: object
served: true

View File

@@ -30,11 +30,75 @@ spec:
metadata:
type: object
spec:
description: ApplicationSpec is the spec of Application
properties:
components:
items:
description: ApplicationComponent describe the component of application
properties:
name:
type: string
scopes:
additionalProperties:
type: string
description: scopes in ApplicationComponent defines the component-level scopes the format is <scope-type:scope-instance-name> pairs, the key represents type of `ScopeDefinition` while the value represent the name of scope instance.
type: object
x-kubernetes-preserve-unknown-fields: true
settings:
type: object
x-kubernetes-preserve-unknown-fields: true
traits:
description: Traits define the trait of one component, the type must be array to keep the order.
items:
description: ApplicationTrait defines the trait of application
properties:
name:
type: string
properties:
type: object
x-kubernetes-preserve-unknown-fields: true
required:
- name
- properties
type: object
type: array
type:
type: string
required:
- name
- settings
- type
type: object
type: array
required:
- components
type: object
x-kubernetes-preserve-unknown-fields: true
status:
description: AppStatus defines the observed state of Application
properties:
components:
description: Components record the related Components created by Application Controller
items:
description: A TypedReference refers to an object by Name, Kind, and APIVersion. It is commonly used to reference cluster-scoped objects or objects where the namespace is already known.
properties:
apiVersion:
description: APIVersion of the referenced object.
type: string
kind:
description: Kind of the referenced object.
type: string
name:
description: Name of the referenced object.
type: string
uid:
description: UID of the referenced object.
type: string
required:
- apiVersion
- kind
- name
type: object
type: array
conditions:
description: Conditions of the resource.
items:

View File

@@ -44,6 +44,11 @@ spec:
items:
type: string
type: array
conflictsWith:
description: 'ConflictsWith specifies the list of traits(CRD name, Definition name, CRD group) which could not apply to the same workloads with this trait. Traits that omit this field can work with any other traits. Example rules: "service" # Trait definition name "services.k8s.io" # API resource/crd name "*.networking.k8s.io" # API group "labelSelector:foo=bar" # label selector labelSelector format: https://pkg.go.dev/k8s.io/apimachinery/pkg/labels#Parse'
items:
type: string
type: array
definitionRef:
description: Reference to the CustomResourceDefinition that defines this trait kind.
properties:
@@ -66,8 +71,6 @@ spec:
workloadRefPath:
description: WorkloadRefPath indicates where/if a trait accepts a workloadRef object
type: string
required:
- definitionRef
type: object
type: object
served: true

View File

@@ -0,0 +1,349 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.2.4
creationTimestamp: null
name: rollouts.standard.oam.dev
spec:
group: standard.oam.dev
names:
kind: Rollout
listKind: RolloutList
plural: rollouts
singular: rollout
scope: Namespaced
versions:
- name: v1alpha1
schema:
openAPIV3Schema:
description: Rollout is the Schema for the rollouts 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: RolloutSpec defines the desired state of Rollout
properties:
rolloutPlan:
description: RolloutPlan is the details on how to rollout the resources
properties:
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: APIVersion of the referenced object.
type: string
kind:
description: Kind of the referenced object.
type: string
name:
description: Name of the referenced object.
type: string
uid:
description: UID of the referenced object.
type: string
required:
- apiVersion
- kind
- name
type: object
required:
- name
type: object
type: array
lastBatchToRollout:
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
numBatches:
description: The number of batches, default = 1 mutually exclusive to RolloutBatches
format: int32
type: integer
rolloutBatches:
description: The exact distribution among batches. mutually exclusive to NumBatches
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:
metadata:
additionalProperties:
type: string
description: Metadata (key-value pairs) for this webhook
type: object
name:
description: Name of this webhook
type: string
timeout:
description: Request timeout for 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: APIVersion of the referenced object.
type: string
kind:
description: Kind of the referenced object.
type: string
name:
description: Name of the referenced object.
type: string
uid:
description: UID of the referenced object.
type: string
required:
- apiVersion
- kind
- name
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 Replica field
items:
type: string
type: array
replica:
anyOf:
- type: integer
- type: string
description: 'Replica is the number of pods to upgrade in this batch it can be an absolute number (ex: 5) or a percentage of total pods it is mutually exclusive with the PodList field'
x-kubernetes-int-or-string: true
type: object
type: array
rolloutWebhooks:
description: RolloutWebhooks provides 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:
metadata:
additionalProperties:
type: string
description: Metadata (key-value pairs) for this webhook
type: object
name:
description: Name of this webhook
type: string
timeout:
description: Request timeout for 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
stopped:
description: Stopped the rollout, default is false
type: boolean
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
sourceRef:
description: SourceRef references the source resource that contains the older version of the software. We assume that it's the first time to deploy when we cannot find the source.
properties:
apiVersion:
description: APIVersion of the referenced object.
type: string
kind:
description: Kind of the referenced object.
type: string
name:
description: Name of the referenced object.
type: string
uid:
description: UID of the referenced object.
type: string
required:
- apiVersion
- kind
- name
type: object
targetRef:
description: TargetRef references a target resource that contains the newer version of the software. We assumed that new resource already exists. This is the only resource we work on if the resource is a stateful resource (cloneset/statefulset)
properties:
apiVersion:
description: APIVersion of the referenced object.
type: string
kind:
description: Kind of the referenced object.
type: string
name:
description: Name of the referenced object.
type: string
uid:
description: UID of the referenced object.
type: string
required:
- apiVersion
- kind
- name
type: object
required:
- rolloutPlan
- targetRef
type: object
status:
description: RolloutStatus defines the observed state of Rollout
properties:
batchRollingState:
description: BatchRollingState only meaningful when the Status is rolling
type: string
conditions:
description: Conditions represents the latest available observations of a CloneSet's current state.
items:
description: RolloutCondition is the condition of the rollout
properties:
batchRollingState:
description: BatchRollingState only meaningful when the Status is rolling
type: string
lastTransitionTime:
description: Last time the condition transitioned to this state
format: date-time
type: string
message:
description: A human readable message indicating details about the transition.
type: string
reason:
description: The reason for the condition's last transition.
type: string
rollingState:
description: RollingState is the Rollout Status
type: string
required:
- rollingState
type: object
type: array
currentBatch:
description: The current batch the rollout is working on/blocked
format: int32
type: integer
rollingState:
description: RollingState is the Rollout State
type: string
sourceGeneration:
description: The source resource generation
type: string
targetGeneration:
description: The target resource generation
type: string
upgradedReplicas:
description: UpgradedReplicas is the number of Pods upgraded by the rollout controller that have a Ready Condition.
format: int32
type: integer
required:
- currentBatch
- rollingState
- sourceGeneration
- targetGeneration
- upgradedReplicas
type: object
type: object
served: true
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

View File

@@ -0,0 +1,363 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.2.4
creationTimestamp: null
name: rollouttraits.standard.oam.dev
spec:
group: standard.oam.dev
names:
kind: RolloutTrait
listKind: RolloutTraitList
plural: rollouttraits
singular: rollouttrait
scope: Namespaced
versions:
- name: v1alpha1
schema:
openAPIV3Schema:
description: RolloutTrait is the Schema for the RolloutTrait 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: RolloutTraitSpec defines the desired state of RolloutTrait
properties:
rolloutPlan:
description: RolloutPlan is the details on how to rollout the resources
properties:
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: APIVersion of the referenced object.
type: string
kind:
description: Kind of the referenced object.
type: string
name:
description: Name of the referenced object.
type: string
uid:
description: UID of the referenced object.
type: string
required:
- apiVersion
- kind
- name
type: object
required:
- name
type: object
type: array
lastBatchToRollout:
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
numBatches:
description: The number of batches, default = 1 mutually exclusive to RolloutBatches
format: int32
type: integer
paused:
description: Paused the rollout, default is false
type: boolean
rolloutBatches:
description: The exact distribution among batches. mutually exclusive to NumBatches
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:
metadata:
additionalProperties:
type: string
description: Metadata (key-value pairs) for this webhook
type: object
name:
description: Name of this webhook
type: string
timeout:
description: Request timeout for 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: APIVersion of the referenced object.
type: string
kind:
description: Kind of the referenced object.
type: string
name:
description: Name of the referenced object.
type: string
uid:
description: UID of the referenced object.
type: string
required:
- apiVersion
- kind
- name
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 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
type: string
rolloutWebhooks:
description: RolloutWebhooks provides 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:
metadata:
additionalProperties:
type: string
description: Metadata (key-value pairs) for this webhook
type: object
name:
description: Name of this webhook
type: string
timeout:
description: Request timeout for 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
sourceRef:
description: SourceRef references the list of resources that contains the older version of the software. We assume that it's the first time to deploy when we cannot find any source.
items:
description: A TypedReference refers to an object by Name, Kind, and APIVersion. It is commonly used to reference cluster-scoped objects or objects where the namespace is already known.
properties:
apiVersion:
description: APIVersion of the referenced object.
type: string
kind:
description: Kind of the referenced object.
type: string
name:
description: Name of the referenced object.
type: string
uid:
description: UID of the referenced object.
type: string
required:
- apiVersion
- kind
- name
type: object
type: array
targetRef:
description: TargetRef references a target resource that contains the newer version of the software. We assumed that new resource already exists. This is the only resource we work on if the resource is a stateful resource (cloneset/statefulset)
properties:
apiVersion:
description: APIVersion of the referenced object.
type: string
kind:
description: Kind of the referenced object.
type: string
name:
description: Name of the referenced object.
type: string
uid:
description: UID of the referenced object.
type: string
required:
- apiVersion
- kind
- name
type: object
required:
- rolloutPlan
- targetRef
type: object
status:
description: RolloutStatus defines the observed state of Rollout
properties:
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
format: int32
type: integer
rollingState:
description: RollingState is the Rollout State
type: string
sourceGeneration:
description: The source resource generation
type: string
targetGeneration:
description: The target resource generation
type: string
upgradedReadyReplicas:
description: UpgradedReplicas 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
- rollingState
- sourceGeneration
- targetGeneration
- upgradedReadyReplicas
- upgradedReplicas
type: object
type: object
served: true
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

View File

@@ -11,7 +11,9 @@
# 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.
{{- if .Values.installCertManager -}}
{{- if .Values.useWebhook -}}
---
apiVersion: v1
kind: Namespace
metadata:
@@ -1080,4 +1082,6 @@ webhooks:
resources:
- '*/*'
sideEffects: None
---
{{- end -}}
{{- end -}}

View File

@@ -0,0 +1,12 @@
apiVersion: core.oam.dev/v1alpha2
kind: WorkloadDefinition
metadata:
name: containerizedworkloads.core.oam.dev
spec:
definitionRef:
name: containerizedworkloads.core.oam.dev
childResourceKinds:
- apiVersion: apps/v1
kind: Deployment
- apiVersion: v1
kind: Service

View File

@@ -7,4 +7,4 @@ spec:
workloadRefsPath: spec.workloadRefs
allowComponentOverlap: true
definitionRef:
name: healthscope.core.oam.dev
name: healthscopes.core.oam.dev

View File

@@ -0,0 +1,60 @@
# Code generated by KubeVela templates. DO NOT EDIT.
apiVersion: core.oam.dev/v1alpha2
kind: TraitDefinition
metadata:
annotations:
definition.oam.dev/description: "Configures K8s ingress and service to enable web traffic for your service.
Please use route trait in cap center for advanced usage."
name: ingress
spec:
appliesToWorkloads:
- webservice
- worker
extension:
template: |
parameter: {
domain: string
http: [string]: int
}
// trait template can have multiple outputs in one trait
outputs: service: {
apiVersion: "v1"
kind: "Service"
metadata:
name: context.name
spec: {
selector:
"app.oam.dev/component": context.name
ports: [
for k, v in parameter.http {
port: v
targetPort: v
},
]
}
}
outputs: ingress: {
apiVersion: "networking.k8s.io/v1beta1"
kind: "Ingress"
metadata:
name: context.name
spec: {
rules: [{
host: parameter.domain
http: {
paths: [
for k, v in parameter.http {
path: k
backend: {
serviceName: context.name
servicePort: v
}
},
]
}
}]
}
}

View File

@@ -3,7 +3,7 @@ apiVersion: core.oam.dev/v1alpha2
kind: TraitDefinition
metadata:
annotations:
definition.oam.dev/description: "`Scaler` is used to configure replicas for your service."
definition.oam.dev/description: "Configures replicas for your service."
name: scaler
spec:
appliesToWorkloads:

View File

@@ -4,7 +4,7 @@ kind: WorkloadDefinition
metadata:
name: task
annotations:
definition.oam.dev/description: "`Task` is a workload type to describe jobs that run code or a script to completion."
definition.oam.dev/description: "Describes jobs that run code or a script to completion."
spec:
definitionRef:
name: jobs.batch

View File

@@ -4,8 +4,8 @@ kind: WorkloadDefinition
metadata:
name: webservice
annotations:
definition.oam.dev/description: "`Webservice` is a workload type to describe long-running, scalable, containerized services that have a stable network endpoint to receive external network traffic from customers.
If workload type is skipped for any service defined in Appfile, it will be defaulted to `Web Service` type."
definition.oam.dev/description: "Describes long-running, scalable, containerized services that have a stable network endpoint to receive external network traffic from customers.
If workload type is skipped for any service defined in Appfile, it will be defaulted to `webservice` type."
spec:
definitionRef:
name: deployments.apps

View File

@@ -4,7 +4,7 @@ kind: WorkloadDefinition
metadata:
name: worker
annotations:
definition.oam.dev/description: "`Worker` is a workload type to describe long-running, scalable, containerized services that running at backend. They do NOT have network endpoint to receive external network traffic."
definition.oam.dev/description: "Describes long-running, scalable, containerized services that running at backend. They do NOT have network endpoint to receive external network traffic."
spec:
definitionRef:
name: deployments.apps
@@ -34,10 +34,6 @@ spec:
}]
}
}
selector:
matchLabels:
"app.oam.dev/component": context.name
}
}

View File

@@ -145,11 +145,13 @@ spec:
name: tls-cert-vol
readOnly: true
{{ end }}
{{ if .Values.useWebhook }}
volumes:
- name: tls-cert-vol
secret:
defaultMode: 420
secretName: {{ .Values.certificate.secretName | quote }}
{{ end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}

View File

@@ -1,31 +0,0 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: vela-config
# TODO: Currently namespace MUST be vela-system
namespace: vela-system
data:
servicemonitors.monitoring.coreos.com: |
{
"repo": "prometheus-community",
"urL": "https://prometheus-community.github.io/helm-charts",
"name": "kube-prometheus-stack",
"namespace": "monitoring",
"version": "9.4.4"
}
flagger.app: |
{
"repo": "oam-flagger",
"urL": "https://oam.dev/flagger/archives/",
"name": "flagger",
"namespace": "vela-system",
"version": "1.1.0"
}
keda: |
{
"repo": "kedacore",
"urL": "https://kedacore.github.io/charts",
"name": "keda",
"namespace": "keda",
"version": "2.0.0-rc3"
}

View File

@@ -3,11 +3,55 @@
apiVersion: admissionregistration.k8s.io/v1beta1
kind: MutatingWebhookConfiguration
metadata:
name: mutating-webhook-configuration
name: kubevela-mutating-webhook-configuration
namespace: {{ .Release.Namespace }}
annotations:
cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ .Values.certificate.certificateName }}
webhooks:
- clientConfig:
caBundle: Cg==
service:
name: {{ template "kubevela.name" . }}-webhook
namespace: {{ .Release.Namespace }}
path: /mutating-core-oam-dev-v1alpha2-applicationconfigurations
failurePolicy: Fail
name: mutating.core.oam.dev.v1alpha2.applicationconfigurations
rules:
- apiGroups:
- core.oam.dev
apiVersions:
- v1alpha2
operations:
- CREATE
- UPDATE
resources:
- applicationconfigurations
scope: Namespaced
admissionReviewVersions:
- v1beta1
timeoutSeconds: 5
- clientConfig:
caBundle: Cg==
service:
name: {{ template "kubevela.name" . }}-webhook
namespace: {{ .Release.Namespace }}
path: /mutating-core-oam-dev-v1alpha2-components
failurePolicy: Fail
name: mutating.core.oam-dev.v1alpha2.components
rules:
- apiGroups:
- core.oam.dev
apiVersions:
- v1alpha2
operations:
- CREATE
- UPDATE
resources:
- components
scope: Namespaced
admissionReviewVersions:
- v1beta1
timeoutSeconds: 5
- clientConfig:
caBundle: Cg==
service:
@@ -49,11 +93,55 @@ webhooks:
apiVersion: admissionregistration.k8s.io/v1beta1
kind: ValidatingWebhookConfiguration
metadata:
name: validating-webhook-configuration
name: kubevela-validating-webhook-configuration
namespace: {{ .Release.Namespace }}
annotations:
cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ .Values.certificate.certificateName }}
webhooks:
- clientConfig:
caBundle: Cg==
service:
name: {{ template "kubevela.name" . }}-webhook
namespace: {{ .Release.Namespace }}
path: /validating-core-oam-dev-v1alpha2-applicationconfigurations
failurePolicy: Fail
name: validating.core.oam.dev.v1alpha2.applicationconfigurations
rules:
- apiGroups:
- core.oam.dev
apiVersions:
- v1alpha2
operations:
- CREATE
- UPDATE
resources:
- applicationconfigurations
scope: Namespaced
admissionReviewVersions:
- v1beta1
timeoutSeconds: 5
- clientConfig:
caBundle: Cg==
service:
name: {{ template "kubevela.name" . }}-webhook
namespace: {{ .Release.Namespace }}
path: /validating-core-oam-dev-v1alpha2-components
failurePolicy: Fail
name: validating.core.oam.dev.v1alpha2.components
rules:
- apiGroups:
- core.oam.dev
apiVersions:
- v1alpha2
operations:
- CREATE
- UPDATE
resources:
- components
scope: Namespaced
admissionReviewVersions:
- v1beta1
timeoutSeconds: 5
- clientConfig:
caBundle: Cg==
service:
@@ -120,6 +208,8 @@ metadata:
spec:
selfSigned: {}
# The following Certificate will generate a secret for vela-core
# This rely on the system has a installed cert-manager in it.
---
apiVersion: cert-manager.io/v1
kind: Certificate

View File

@@ -3,6 +3,7 @@
# Declare variables to be passed into your templates.
replicaCount: 1
installCertManager: false
useWebhook: true
# By default, don't disable any builtin capabilities
disableCaps: ""

View File

@@ -12,11 +12,8 @@ import (
"syscall"
"time"
"github.com/oam-dev/kubevela/version"
monitoring "github.com/coreos/prometheus-operator/pkg/apis/monitoring/v1"
"github.com/crossplane/crossplane-runtime/pkg/logging"
"github.com/go-logr/logr"
injectorv1alpha1 "github.com/oam-dev/trait-injector/api/v1alpha1"
injectorcontroller "github.com/oam-dev/trait-injector/controllers"
"github.com/oam-dev/trait-injector/pkg/injector"
@@ -29,19 +26,20 @@ import (
"k8s.io/apimachinery/pkg/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/healthz"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
oamcore "github.com/oam-dev/kubevela/apis/core.oam.dev"
velacore "github.com/oam-dev/kubevela/apis/standard.oam.dev/v1alpha1"
"github.com/oam-dev/kubevela/pkg/appfile/driver"
velacontroller "github.com/oam-dev/kubevela/pkg/controller"
oamcontroller "github.com/oam-dev/kubevela/pkg/controller/core.oam.dev"
oamv1alpha2 "github.com/oam-dev/kubevela/pkg/controller/core.oam.dev/v1alpha2"
"github.com/oam-dev/kubevela/pkg/controller/dependency"
"github.com/oam-dev/kubevela/pkg/controller/utils"
velawebhook "github.com/oam-dev/kubevela/pkg/webhook"
oamwebhook "github.com/oam-dev/kubevela/pkg/webhook/core.oam.dev/v1alpha2"
"github.com/oam-dev/kubevela/pkg/utils/system"
oamwebhook "github.com/oam-dev/kubevela/pkg/webhook/core.oam.dev"
velawebhook "github.com/oam-dev/kubevela/pkg/webhook/standard.oam.dev"
"github.com/oam-dev/kubevela/version"
)
const (
@@ -77,6 +75,8 @@ func main() {
var controllerArgs oamcontroller.Args
var healthAddr string
var disableCaps string
var storageDriver string
var syncPeriod time.Duration
flag.BoolVar(&useWebhook, "use-webhook", false, "Enable Admission Webhook")
flag.BoolVar(&useTraitInjector, "use-trait-injector", false, "Enable TraitInjector")
@@ -95,7 +95,12 @@ func main() {
flag.StringVar(&healthAddr, "health-addr", ":9440", "The address the health endpoint binds to.")
flag.BoolVar(&controllerArgs.ApplyOnceOnly, "apply-once-only", false,
"For the purpose of some production environment that workload or trait should not be affected if no spec change")
flag.StringVar(&controllerArgs.CustomRevisionHookURL, "custom-revision-hook-url", "",
"custom-revision-hook-url is a webhook url which will let KubeVela core to call with applicationConfiguration and component info and return a customized component revision")
flag.StringVar(&disableCaps, "disable-caps", "", "To be disabled builtin capability list.")
flag.StringVar(&storageDriver, "storage-driver", driver.LocalDriverName, "Application file save to the storage driver")
flag.DurationVar(&syncPeriod, "informer-re-sync-interval", 5*time.Minute,
"controller shared informer lister full re-sync period")
flag.Parse()
// setup logging
@@ -118,14 +123,6 @@ func main() {
setupLog.Info(fmt.Sprintf("KubeVela Version: %s, GIT Revision: %s.", version.VelaVersion, version.GitRevision))
setupLog.Info(fmt.Sprintf("Disable Capabilities: %s.", disableCaps))
// install dependency charts first
k8sClient, err := client.New(ctrl.GetConfigOrDie(), client.Options{Scheme: scheme})
if err != nil {
setupLog.Error(err, "unable to create a kubernetes client")
os.Exit(1)
}
go dependency.Install(k8sClient)
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
Scheme: scheme,
MetricsBindAddress: metricsAddr,
@@ -135,6 +132,7 @@ func main() {
Port: webhookPort,
CertDir: certDir,
HealthProbeBindAddress: healthAddr,
SyncPeriod: &syncPeriod,
})
if err != nil {
setupLog.Error(err, "unable to create a controller manager")
@@ -153,7 +151,7 @@ func main() {
if useWebhook {
setupLog.Info("vela webhook enabled, will serving at :" + strconv.Itoa(webhookPort))
if err = oamwebhook.Add(mgr); err != nil {
if err = oamwebhook.Register(mgr); err != nil {
setupLog.Error(err, "unable to setup oam runtime webhook")
os.Exit(1)
}
@@ -173,6 +171,15 @@ func main() {
setupLog.Error(err, "unable to setup the vela core controller")
os.Exit(1)
}
if driver := os.Getenv(system.StorageDriverEnv); len(driver) == 0 {
// first use system environment,
err := os.Setenv(system.StorageDriverEnv, storageDriver)
if err != nil {
setupLog.Error(err, "unable to setup the vela core controller")
os.Exit(1)
}
}
setupLog.Info("use storage driver", "storageDriver", os.Getenv(system.StorageDriverEnv))
if useTraitInjector {
// register all service injectors
@@ -197,7 +204,7 @@ func main() {
if controllerArgs.ApplyOnceOnly {
setupLog.Info("applyOnceOnly is enabled that means workload or trait only apply once if no spec change even they are changed by others")
}
if err := mgr.Start(makeSignalHandler(setupLog, k8sClient)); err != nil {
if err := mgr.Start(makeSignalHandler()); err != nil {
setupLog.Error(err, "problem running manager")
os.Exit(1)
}
@@ -261,8 +268,7 @@ func waitWebhookSecretVolume(certDir string, timeout, interval time.Duration) er
}
}
//nolint:unparam
func makeSignalHandler(log logr.Logger, kubecli client.Client) (stopCh <-chan struct{}) {
func makeSignalHandler() (stopCh <-chan struct{}) {
stop := make(chan struct{})
c := make(chan os.Signal, 2)
@@ -270,10 +276,6 @@ func makeSignalHandler(log logr.Logger, kubecli client.Client) (stopCh <-chan st
go func() {
<-c
// Do not uninstall when vela-core terminating.
// When running on K8s, old pod will terminate after new pod running, it will cause charts uninstalled.
// https://github.com/oam-dev/kubevela/issues/499
// dependency.Uninstall(kubecli)
close(stop)
// second signal. Exit directly.

15
community.md Normal file
View File

@@ -0,0 +1,15 @@
# Community
All contributors should be welcomed to the community by existing members, helped with PR workflow, and directed to relevant documentation and communication channels.
This doc outlines the various responsibilities of contributor roles in
KubeVela.
| Role | Responsibilities | Requirements | Defined by |
| -----| ---------------- | ------------ | -------|
| approver | Approve and merge PRs | Highly experienced and active member to a subcomponent. Sponsored by majority of approvers. | [OWNERS] file approver entry|
| reviewer | Review contributions | Active contributor and/or code reviewer. Contributed and own major features. Sponsored by 2 approvers. | [OWNERS] file reviewer entry. |
| member | Active contributor in the community. | Active contributor and/or code reviewer. Submitted 5 coding PRs or 10 doc PRs. Sponsored by 2 reviewers/approvers. | OAM GitHub org member. |
Established community members are expected to continuously demonstrate their commitment and contribution to the KubeVela projects.

View File

@@ -1,5 +1,4 @@
# Vela Server
## example
# Application Example
In this Demo, Application application-sample will be converted to appconfig and component
@@ -28,15 +27,26 @@ metadata:
name: application-sample
namespace: oam-test
spec:
services:
myweb:
cmd:
- sleep
- "1000"
image: busybox
scaler:
replicas: 10
components:
- name: myweb
type: worker
settings:
image: "busybox"
cmd:
- sleep
- "1000"
traits:
- name: scaler
properties:
replicas: 10
- name: sidercar
properties:
name: "sidecar-test"
image: "nginx"
- name: kservice
properties:
http:
server: 80
status:
conditions:
- lastTransitionTime: "2020-12-02T12:12:52Z"
@@ -74,34 +84,21 @@ metadata:
kind: Application
name: application-sample
uid: dca7acc3-664c-422b-aa52-4fe012e37974
spec:
spec:
components:
- componentName: myweb
traits:
- trait:
apiVersion: core.oam.dev/v1alpha2
kind: ManualScalerTrait
apiVersion: v1
kind: Service
metadata:
name: myweb
spec:
replicaCount: 10
status:
conditions:
- lastTransitionTime: "2020-12-02T12:12:52Z"
reason: Successfully reconciled resource
status: "True"
type: Synced
dependency: {}
workloads:
- componentName: myweb
componentRevisionName: myweb-v1
traits:
- traitRef:
apiVersion: core.oam.dev/v1alpha2
kind: ManualScalerTrait
name: myweb-trait-78fdd467d6
workloadRef:
apiVersion: apps/v1
kind: Deployment
name: myweb
ports:
- port: 80
targetPort: 80
selector:
app: myweb
kubectl get component/myweb -oyaml
@@ -124,12 +121,14 @@ spec:
apiVersion: apps/v1
kind: Deployment
spec:
replicas: 10
selector:
matchLabels:
app.oam.dev/component: myweb
template:
metadata:
labels:
app: myweb
app.oam.dev/component: myweb
spec:
containers:
@@ -138,9 +137,10 @@ spec:
- "1000"
image: busybox
name: myweb
status:
latestRevision:
name: myweb-v1
revision: 1
- command:
- sleep
- "1000"
image: busybox
name: test-sidecar
```

View File

@@ -0,0 +1,388 @@
# Definition Docs
## Reserved word
### Patch
Perform the CUE AND operation with the content declared by 'patch' and workload cr,
you can define the strategy of list merge through comments, example as follows
base model
```
containers: [{
name: "x1"
}, {
name: "x2"
image: string
envs: [{
name: "OPS"
value: string
}, ...]
}, ...]
```
define patch model
```
// +patchKey=name
containers: [{
name: "x2"
image: "test-image"
envs: [{
name: "OPS1"
value: "V-OPS1"
},{
name: "OPS"
value: "V-OPS"
}, ...]
}, ...]
```
and the result model after patch is follow
```
containers: [{
name: "x1"
},{
name: "x2"
image: "test-image"
envs: [{
name: "OPS1"
value: "V-OPS1"
},{
name: "OPS"
value: "V-OPS"
}, ...]
}, ...]
```
### output
Generate a new cr, which is generally associated with workload cr
## Workload Definition
The following workload definition is to generate a deployment
```
apiVersion: core.oam.dev/v1alpha2
kind: WorkloadDefinition
metadata:
name: worker
annotations:
definition.oam.dev/description: "Long-running scalable backend worker without network endpoint"
spec:
definitionRef:
name: deployments.apps
extension:
template: |
output: {
apiVersion: "apps/v1"
kind: "Deployment"
spec: {
selector: matchLabels: {
"app.oam.dev/component": context.name
}
template: {
metadata: labels: {
"app.oam.dev/component": context.name
}
spec: {
containers: [{
name: context.name
image: parameter.image
if parameter["cmd"] != _|_ {
command: parameter.cmd
}
}]
}
}
}
}
parameter: {
// +usage=Which image would you like to use for your service
// +short=i
image: string
cmd?: [...string]
}
```
If defined an application as follows
```
apiVersion: core.oam.dev/v1alpha2
kind: Application
metadata:
name: application-sample
spec:
components:
- name: myweb
type: worker
settings:
image: "busybox"
cmd:
- sleep
- "1000"
```
we will get a deployment
```
apiVersion: apps/v1
kind: Deployment
spec:
selector:
matchLabels:
app.oam.dev/component: myweb
template:
metadata:
labels:
app.oam.dev/component: myweb
spec:
containers:
- command:
- sleep
- "1000"
image: busybox
name: myweb
```
## Service Trait Definition
Define a trait Definition that appends service to workload(worker) , as shown below
```
apiVersion: core.oam.dev/v1alpha2
kind: TraitDefinition
metadata:
annotations:
definition.oam.dev/description: "service the app"
name: kservice
spec:
appliesToWorkloads:
- webservice
- worker
definitionRef:
name: service.v1
extension:
template: |-
patch: {spec: template: metadata: labels: app: context.name}
output: {
apiVersion: "v1"
kind: "Service"
metadata: name: context.name
spec: {
selector: app: context.name
ports: [
for k, v in parameter.http {
port: v
targetPort: v
}
]
}
}
parameter: {
http: [string]: int
}
```
If add service capability to the application, as follows
```
apiVersion: core.oam.dev/v1alpha2
kind: Application
metadata:
name: application-sample
spec:
components:
- name: myweb
type: worker
settings:
image: "busybox"
cmd:
- sleep
- "1000"
traits:
- name: kservice
properties:
http:
server: 80
```
we will get a new deployment and service
```
// origin deployment template add labels
apiVersion: apps/v1
kind: Deployment
spec:
selector:
matchLabels:
app.oam.dev/component: myweb
template:
metadata:
labels:
// add label app
app: myweb
app.oam.dev/component: myweb
spec:
containers:
- command:
- sleep
- "1000"
image: busybox
name: myweb
---
apiVersion: v1
kind: Service
metadata:
name: myweb
spec:
ports:
- port: 80
targetPort: 80
selector:
app: myweb
```
## Scaler Trait Definition
Define a trait Definition that scale workload(worker) replicas
```
apiVersion: core.oam.dev/v1alpha2
kind: TraitDefinition
metadata:
annotations:
definition.oam.dev/description: "Manually scale the app"
name: scaler
spec:
appliesToWorkloads:
- webservice
- worke
extension:
template: |-
patch: {
spec: replicas: parameter.replicas
}
parameter: {
//+short=r
replicas: *1 | int
}
```
If add scaler capability to the application, as follows
```
components:
- name: myweb
type: worker
settings:
image: "busybox"
cmd:
- sleep
- "1000"
traits:
- name: kservice
properties:
http:
server: 80
- name: scaler
properties:
replicas: 10
```
The deployment replicas will be scale to 10
```
apiVersion: apps/v1
kind: Deployment
spec:
selector:
matchLabels:
app.oam.dev/component: myweb
// scale to 10
replicas: 10
template:
metadata:
labels:
// add label app
app: myweb
app.oam.dev/component: myweb
spec:
containers:
- command:
- sleep
- "1000"
image: busybox
name: myweb
```
## Sidecar Trait Definition
Define a trait Definition that append containers to workload(worker)
```
apiVersion: core.oam.dev/v1alpha2
kind: TraitDefinition
metadata:
annotations:
definition.oam.dev/description: "add sidecar to the app"
name: sidecar
spec:
appliesToWorkloads:
- webservice
- worke
extension:
template: |-
patch: {
// +patchKey=name
spec: template: spec: containers: [parameter]
}
parameter: {
name: string
image: string
command?: [...string]
}
```
If add sidercar capability to the application, as follows
```
apiVersion: core.oam.dev/v1alpha2
kind: Application
metadata:
name: application-sample
spec:
components:
- name: myweb
type: worker
settings:
image: "busybox"
cmd:
- sleep
- "1000"
traits:
- name: scaler
properties:
replicas: 10
- name: sidercar
properties:
name: "sidecar-test"
image: "nginx"
- name: kservice
properties:
http:
server: 80
```
The deployment updated as follows
```
apiVersion: apps/v1
kind: Deployment
spec:
selector:
matchLabels:
app.oam.dev/component: myweb
// scale to 10
replicas: 10
template:
metadata:
labels:
// add label app
app: myweb
app.oam.dev/component: myweb
spec:
containers:
- command:
- sleep
- "1000"
image: busybox
name: myweb
- name: sidecar-test
image: nginx
```

View File

@@ -0,0 +1,25 @@
apiVersion: core.oam.dev/v1alpha2
kind: Application
metadata:
name: application-sample
spec:
components:
- name: myweb
type: worker
settings:
image: "busybox"
cmd:
- sleep
- "1000"
traits:
- name: scaler
properties:
replicas: 10
- name: sidecar
properties:
name: "sidecar-test"
image: "nginx"
- name: kservice
properties:
http:
server: 80

View File

@@ -58,19 +58,76 @@ spec:
appliesToWorkloads:
- webservice
- worker
definitionRef:
name: manualscalertraits.core.oam.dev
workloadRefPath: spec.workloadRef
extension:
template: |-
output: {
apiVersion: "core.oam.dev/v1alpha2"
kind: "ManualScalerTrait"
spec: {
replicaCount: parameter.replicas
}
patch: {
spec: replicas: parameter.replicas
}
parameter: {
//+short=r
replicas: *1 | int
}
---
apiVersion: core.oam.dev/v1alpha2
kind: TraitDefinition
metadata:
annotations:
definition.oam.dev/description: "add sidecar to the app"
name: sidecar
spec:
appliesToWorkloads:
- webservice
- worker
extension:
template: |-
patch: {
// +patchKey=name
spec: template: spec: containers: [parameter]
}
parameter: {
name: string
image: string
command?: [...string]
}
---
apiVersion: core.oam.dev/v1alpha2
kind: TraitDefinition
metadata:
annotations:
definition.oam.dev/description: "service the app"
name: kservice
spec:
appliesToWorkloads:
- webservice
- worker
definitionRef:
name: services
extension:
template: |-
patch: {spec: template: metadata: labels: app: context.name}
output: {
apiVersion: "v1"
kind: "Service"
metadata: name: context.name
spec: {
selector: app: context.name
ports: [
for k, v in parameter.http {
port: v
targetPort: v
}
]
}
}
parameter: {
http: [string]: int
}
---
apiVersion: core.oam.dev/v1alpha2
kind: TraitDefinition
metadata:
name: services
namespace: default
spec:
definitionRef:
name: services

View File

@@ -1,14 +0,0 @@
apiVersion: core.oam.dev/v1alpha2
kind: Application
metadata:
name: application-sample
spec:
services:
myweb:
type: worker
image: "busybox"
cmd:
- sleep
- "1000"
scaler:
replicas: 10

View File

@@ -1,4 +1,8 @@
/lambda/
/scripts
/config
.history
.history
public
dist
.umi
mock

View File

@@ -5,4 +5,8 @@ module.exports = {
page: true,
REACT_APP_ENV: true,
},
rules: {
'react/jsx-uses-react': 'off',
'react/react-in-jsx-scope': 'off',
},
};

37
dashboard/.gitignore vendored Normal file
View File

@@ -0,0 +1,37 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
**/node_modules
# roadhog-api-doc ignore
/src/utils/request-temp.js
_roadhog-api-doc
# production
/dist
# misc
.DS_Store
npm-debug.log*
yarn-error.log
/coverage
.idea
*bak
.vscode
# visual studio code
.history
*.log
functions/*
.temp/**
# umi
.umi
.umi-production
# screenshot
screenshot
.firebase
.eslintcache
build

View File

@@ -20,3 +20,4 @@ yarn-error.log
.history
CNAME
/build
/public

View File

@@ -1,50 +1,81 @@
# Vela Dashboard
# KubeVela Dashboard
## Quick start
In the root folder of this project, run `make start-dashboard` to start backend OpenAPI server and Dashboard at the same time.
```shell
➜ xxx/src/github.com/oam-dev/kubevela $ make start-dashboard
go run pkg/server/main/startAPIServer.go &
cd dashboard && yarn && yarn start && cd ..
yarn install v1.22.4
warning package-lock.json found. Your project contains lock files generated by tools other than Yarn. It is advised not to mix package managers in order to avoid resolution inconsistencies caused by unsynchronized lock files. To clear this warning, remove package-lock.json.
[1/5] 🔍 Validating package.json...
[2/5] 🔍 Resolving packages...
success Already up-to-date.
$ umi g tmp
✨ Done in 5.89s.
yarn run v1.22.4
$ umi dev
Starting the development server...
I1230 10:37:54.157092 14236 request.go:621] Throttling request took 1.04915427s, request: GET:https://47.242.145.141:6443/apis/split.smi-spec.io/v1alpha2?timeout=32s
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
[GIN-debug] POST /api/envs/ --> github.com/oam-dev/kubevela/pkg/server.(*APIServer).CreateEnv-fm (6 handlers)
[GIN-debug] PUT /api/envs/:envName --> github.com/oam-dev/kubevela/pkg/server.(*APIServer).UpdateEnv-fm (6 handlers)
...
[GIN-debug] GET /api/version --> github.com/oam-dev/kubevela/pkg/server.(*APIServer).GetVersion-fm (6 handlers)
[GIN-debug] GET /swagger/*any --> github.com/swaggo/gin-swagger.CustomWrapHandler.func1 (7 handlers)
✔ Webpack
Compiled successfully in 26.86s
DONE Compiled successfully in 26865ms 10:38:22 AM
## Environment Prepare
Install `node_modules`:
```bash
npm install
App running at:
- Local: http://localhost:8000 (copied to clipboard)
- Network: http://192.168.31.114:8000
```
or
## Development
### Install dependencies
```bash
yarn
```
## Provided Scripts
Scripts provided in `package.json`. It's safe to modify or add additional script:
### Start project
### Build
```bash
npm start
yarn build
```
### Build project
### Start up
```bash
npm run build
yarn start
```
### Check code style
### Lint and Test
- Check code style
```bash
npm run lint
yarn lint
```
You can also use script to auto fix some lint error:
```bash
npm run lint:fix
yarn prettier
```
### Test code
- Test code
```bash
npm test
```
yarn test
```

View File

@@ -1,153 +0,0 @@
// https://umijs.org/config/
import { defineConfig } from 'umi';
import defaultSettings from './defaultSettings';
import proxy from './proxy';
const { REACT_APP_ENV } = process.env;
export default defineConfig({
history: { type: 'hash' },
hash: false,
antd: {},
dva: {
hmr: true,
},
locale: {
default: 'en-US',
antd: false,
baseNavigator: false,
},
dynamicImport: {
loading: '@/components/PageLoading/index',
},
targets: {
ie: 11,
},
// umi routes: https://umijs.org/docs/routing
routes: [
{
path: '/',
component: '../layouts/SecurityLayout',
routes: [
{
path: '/',
component: '../layouts/BasicLayout',
routes: [
{
path: '/',
redirect: `/ApplicationList`,
},
{
name: 'ApplicationList',
icon: 'table',
path: `/ApplicationList`,
component: './ApplicationList',
},
{
name: 'ApplicationList.WorkloadDetail',
icon: 'smile',
path: '/ApplicationList/WorkloadDetail',
component: './Workload/Detail',
hideInMenu: true,
},
{
name: 'ApplicationList.TraitDetail',
icon: 'smile',
path: '/ApplicationList/TraitDetail',
component: './Traits/Detail',
hideInMenu: true,
},
{
name: 'ApplicationList.Components',
hideInMenu: true,
path: '/ApplicationList/:appName/Components',
component: './ApplicationList/Components',
},
{
name: 'ApplicationList.Components.createComponent',
hideInMenu: true,
path: '/ApplicationList/:appName/createComponent',
component: './ApplicationList/CreateComponent',
},
{
name: 'Workload',
icon: 'table',
path: '/Workload',
routes: [
{
name: 'WorkloadItem',
icon: 'smile',
path: '/Workload/:WorkloadType',
component: './Workload/index.jsx',
},
],
},
{
path: '/Traits',
name: 'Traits',
icon: 'table',
routes: [
{
name: 'TraitItem',
icon: 'smile',
path: '/Traits/:traitType',
component: './Traits/index.jsx',
},
],
},
{
name: 'Capability',
icon: 'table',
path: '/Capability',
component: './Capability',
},
{
path: '/System',
name: 'System',
icon: 'table',
routes: [
{
name: 'Env',
icon: 'table',
path: '/System/Env',
component: './System/Env',
},
],
},
{
name: 'Capability.Detail',
hideInMenu: true,
path: '/Capability/Detail',
component: './Capability/Detail',
},
{
component: './404',
},
],
},
{
component: './404',
},
],
},
{
component: './404',
},
],
// Theme for antd: https://ant.design/docs/react/customize-theme-cn
theme: {
// 主题配置
'primary-color': defaultSettings.primaryColor,
'link-color': defaultSettings.linkColor,
'link-hover-color': defaultSettings.linkHoverColor,
'disabled-bg': defaultSettings.disabledBg,
'disabled-color': defaultSettings.disabledColor,
'btn-disable-color': defaultSettings.btnDisableColor,
},
// @ts-ignore
title: false,
ignoreMomentLocale: true,
proxy: proxy[REACT_APP_ENV || 'dev'],
manifest: {
basePath: '/',
},
});

View File

@@ -0,0 +1,68 @@
// https://umijs.org/config/
import { defineConfig } from 'umi';
import defaultSettings from './defaultSettings';
import proxy from './proxy';
import routes from './routes';
import themeSettings from './themeSettings';
const { REACT_APP_ENV } = process.env;
export default defineConfig({
hash: true,
antd: {},
dva: {
hmr: true,
},
layout: {
name: 'KubeVela',
locale: true,
siderWidth: 208,
...defaultSettings,
},
locale: {
// default en-US
default: 'en-US',
antd: true,
// default true, when it is true, will use `navigator.language` overwrite default
baseNavigator: true,
},
dynamicImport: {
loading: '@ant-design/pro-layout/es/PageLoading',
},
nodeModulesTransform: {
type: 'none',
},
targets: {
ie: 11,
},
// umi routes: https://umijs.org/docs/routing
routes,
// Theme for antd: https://ant.design/docs/react/customize-theme-cn
theme: {
'primary-color': defaultSettings.primaryColor,
'link-color': themeSettings.linkColor,
'link-hover-color': themeSettings.linkHoverColor,
'disabled-bg': themeSettings.disabledBg,
'disabled-color': themeSettings.disabledColor,
'btn-disable-color': themeSettings.btnDisableColor,
},
esbuild: {},
title: false,
ignoreMomentLocale: true,
proxy: proxy[REACT_APP_ENV || 'dev'],
manifest: {
basePath: '/',
},
// https://github.com/zthxxx/react-dev-inspector
plugins: ['react-dev-inspector/plugins/umi/react-inspector'],
inspectorConfig: {
// loader options type and docs see below
exclude: [],
babelPlugins: [],
babelOptions: {},
},
resolve: {
includes: ['src/components'],
},
});

View File

@@ -1,22 +0,0 @@
const proSettings = {
navTheme: 'dark',
// 主题颜色配置
primaryColor: '#1B58F4', // 全局主色
linkColor: '#1B58F4', // 链接色
linkHoverColor: '#1B58F4',
disabledBg: '#EBEBEB', // 失效背景色,
disabledColor: '#BEBEBE', // 失效文本色,
btnDisableColor: '#A4A4A4', // 禁用btn文字颜色
layout: 'side',
contentWidth: 'Fluid',
fixedHeader: false,
fixSiderbar: true,
colorWeak: false,
menu: {
locale: false,
},
title: 'Micro App Engine',
pwa: false,
iconfontUrl: '',
};
export default proSettings;

View File

@@ -0,0 +1,22 @@
import { Settings as LayoutSettings } from '@ant-design/pro-layout';
import themeSettings from './themeSettings';
const Settings: LayoutSettings & {
pwa?: boolean;
logo?: string;
} = {
navTheme: 'dark',
primaryColor: themeSettings.primaryColor, // 全局主色
layout: 'mix',
contentWidth: 'Fluid',
fixedHeader: false,
fixSiderbar: true,
colorWeak: false,
title: 'KubeVela',
pwa: false,
logo: 'https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg',
iconfontUrl: '',
};
export default Settings;

View File

@@ -1,33 +0,0 @@
/**
* 在生产环境 代理是无法生效的,所以这里没有生产环境的配置
* The agent cannot take effect in the production environment
* so there is no configuration of the production environment
* For details, please see
* https://pro.ant.design/docs/deploy
*/
export default {
dev: {
'/api': {
target: 'http://127.0.0.1:38081/',
changeOrigin: true,
},
},
test: {
'/api/': {
target: 'https://preview.pro.ant.design',
changeOrigin: true,
pathRewrite: {
'^': '',
},
},
},
pre: {
'/api/': {
target: 'your pre url',
changeOrigin: true,
pathRewrite: {
'^': '',
},
},
},
};

20
dashboard/config/proxy.ts Normal file
View File

@@ -0,0 +1,20 @@
export default {
dev: {
'/api/': {
target: 'http://localhost:38081/',
changeOrigin: true,
},
},
test: {
'/api/': {
target: 'http://localhost:38081/',
changeOrigin: true,
},
},
pre: {
'/api/': {
target: 'http://localhost:38081/',
changeOrigin: true,
},
},
};

View File

@@ -0,0 +1,52 @@
export default [
{
path: '/',
redirect: `/System`,
},
{
name: 'applications',
icon: 'appstore',
path: `/applications`,
component: './Application',
},
{
name: 'capability',
icon: 'AppstoreAddOutlined',
path: '/capabilities',
routes: [
{
path: '/capabilities',
redirect: `/Capability/Workloads`,
},
{
name: 'workloads',
path: '/capabilities/workloads',
component: './Capability/Workloads'
},
{
name: 'traits',
path: '/capabilities/traits',
component: './Capability/Traits',
},
],
},
{
name: 'system',
icon: 'setting',
path: '/System',
routes: [
{
path: '/System',
redirect: `/System/Environment`,
},
{
name: 'environment',
path: '/System/Environment',
component: './System/Environment',
},
],
},
{
component: './404',
},
];

View File

@@ -0,0 +1,9 @@
const themeSettings = {
primaryColor: '#1b58f4', // 全局主色
linkColor: '#1b58f4', // 链接色
linkHoverColor: '#1b58f4',
disabledBg: '#ebebeb', // 失效背景色,
disabledColor: '#bebebe', // 失效文本色,
btnDisableColor: '#a4a4a4', // 禁用btn文字颜色
};
export default themeSettings;

View File

@@ -2,6 +2,7 @@ module.exports = {
testURL: 'http://localhost:8000',
testEnvironment: './tests/PuppeteerEnvironment',
verbose: false,
extraSetupFiles: ['./tests/setupTests.js'],
globals: {
ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION: false,
localStorage: null,

View File

@@ -1,6 +1,6 @@
{
"name": "micro-app-engine",
"version": "4.2.0",
"name": "kubevela",
"version": "0.0.1",
"private": true,
"description": "An out-of-box UI solution for enterprise applications",
"scripts": {
@@ -8,19 +8,19 @@
"build": "umi build",
"deploy": "npm run site && npm run gh-pages",
"dev": "npm run start:dev",
"fetch:blocks": "pro fetch-blocks && npm run prettier",
"gh-pages": "gh-pages -d dist",
"i18n-remove": "pro i18n-remove --locale=zh-CN --write",
"postinstall": "umi g tmp",
"lint": "umi g tmp && npm run lint:js && npm run lint:style && npm run lint:prettier",
"lint-staged": "lint-staged",
"lint-staged:js": "eslint --ext .js,.jsx,.ts,.tsx ",
"lint:fix": "eslint --fix --cache --ext .js,.jsx,.ts,.tsx --format=pretty ./src && npm run lint:style",
"lint:js": "eslint --cache --ext .js,.jsx,.ts,.tsx --format=pretty ./src",
"lint:prettier": "prettier --check \"**/*\" --end-of-line auto",
"lint:prettier": "prettier --check \"src/**/*\" --end-of-line auto",
"lint:style": "stylelint --fix \"src/**/*.less\" --syntax less",
"precommit": "lint-staged",
"prettier": "prettier -c --write \"**/*\"",
"start": "cross-env UMI_UI=none umi dev",
"prettier": "prettier -c --write \"src/**/*\"",
"start": "umi dev",
"start:dev": "cross-env REACT_APP_ENV=dev MOCK=none umi dev",
"start:no-mock": "cross-env MOCK=none umi dev",
"start:no-ui": "cross-env UMI_UI=none umi dev",
@@ -30,7 +30,7 @@
"test": "umi test",
"test:all": "node ./tests/run-tests.js",
"test:component": "umi test ./src/components",
"tsc": "tsc"
"tsc": "tsc --noEmit"
},
"lint-staged": {
"**/*.less": "stylelint --syntax less",
@@ -45,44 +45,47 @@
"not ie <= 10"
],
"dependencies": {
"@ant-design/icons": "^4.0.0",
"@ant-design/pro-layout": "^6.2.5",
"@ant-design/pro-table": "^2.4.0",
"@antv/g6": "^3.6.2",
"antd": "^4.4.0",
"@ant-design/icons": "^4.3.0",
"@ant-design/pro-descriptions": "^1.0.19",
"@ant-design/pro-form": "^1.9.0",
"@ant-design/pro-layout": "^6.6.1",
"@ant-design/pro-list": "^1.1.12",
"@ant-design/pro-table": "^2.15.1",
"@umijs/route-utils": "^1.0.33",
"antd": "^4.9.4",
"classnames": "^2.2.6",
"dva": "^2.4.1",
"dayjs": "^1.9.7",
"lodash": "^4.17.11",
"moment": "^2.25.3",
"omit.js": "^2.0.2",
"path-to-regexp": "2.4.0",
"qs": "^6.9.0",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react": "^17.0.0",
"react-dev-inspector": "^1.1.1",
"react-dom": "^17.0.0",
"react-helmet-async": "^1.0.4",
"umi": "^3.2.13",
"umi": "^3.2.14",
"umi-request": "^1.0.8",
"use-merge-value": "^1.0.1"
},
"devDependencies": {
"@ant-design/pro-cli": "^1.0.18",
"@ant-design/pro-cli": "^2.0.2",
"@types/classnames": "^2.2.7",
"@types/express": "^4.17.0",
"@types/history": "^4.7.2",
"@types/jest": "^26.0.0",
"@types/lodash": "^4.14.144",
"@types/qs": "^6.5.3",
"@types/react": "^16.9.17",
"@types/react-dom": "^16.8.4",
"@types/react-helmet": "^5.0.13",
"@umijs/fabric": "^2.2.0",
"@types/react": "^17.0.0",
"@types/react-dom": "^17.0.0",
"@types/react-helmet": "^6.1.0",
"@umijs/fabric": "^2.3.0",
"@umijs/plugin-blocks": "^2.0.5",
"@umijs/plugin-esbuild": "^1.0.1",
"@umijs/preset-ant-design-pro": "^1.2.0",
"@umijs/preset-react": "^1.4.8",
"@umijs/preset-ui": "^2.0.9",
"@umijs/preset-dumi": "^1.1.0-rc.6",
"@umijs/preset-react": "^1.7.8",
"@umijs/yorkie": "^2.0.3",
"carlo": "^0.9.46",
"chalk": "^4.0.0",
"cross-env": "^7.0.0",
"cross-port-killer": "^1.1.1",
"detect-installer": "^1.0.1",
@@ -96,16 +99,10 @@
"prettier": "^2.0.1",
"pro-download": "1.0.1",
"puppeteer-core": "^5.0.0",
"stylelint": "^13.0.0"
"stylelint": "^13.0.0",
"typescript": "^4.1.2"
},
"engines": {
"node": ">=10.0.0"
},
"checkFiles": [
"src/**/*.js*",
"src/**/*.ts*",
"src/**/*.less",
"config/**/*.js*",
"scripts/**/*.js"
]
}
}

View File

@@ -1 +0,0 @@
preview.pro.ant.design

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200" version="1.1" viewBox="0 0 200 200"><title>Group 28 Copy 5</title><desc>Created with Sketch.</desc><defs><linearGradient id="linearGradient-1" x1="62.102%" x2="108.197%" y1="0%" y2="37.864%"><stop offset="0%" stop-color="#4285EB"/><stop offset="100%" stop-color="#2EC7FF"/></linearGradient><linearGradient id="linearGradient-2" x1="69.644%" x2="54.043%" y1="0%" y2="108.457%"><stop offset="0%" stop-color="#29CDFF"/><stop offset="37.86%" stop-color="#148EFF"/><stop offset="100%" stop-color="#0A60FF"/></linearGradient><linearGradient id="linearGradient-3" x1="69.691%" x2="16.723%" y1="-12.974%" y2="117.391%"><stop offset="0%" stop-color="#FA816E"/><stop offset="41.473%" stop-color="#F74A5C"/><stop offset="100%" stop-color="#F51D2C"/></linearGradient><linearGradient id="linearGradient-4" x1="68.128%" x2="30.44%" y1="-35.691%" y2="114.943%"><stop offset="0%" stop-color="#FA8E7D"/><stop offset="51.264%" stop-color="#F74A5C"/><stop offset="100%" stop-color="#F51D2C"/></linearGradient></defs><g id="Page-1" fill="none" fill-rule="evenodd" stroke="none" stroke-width="1"><g id="logo" transform="translate(-20.000000, -20.000000)"><g id="Group-28-Copy-5" transform="translate(20.000000, 20.000000)"><g id="Group-27-Copy-3"><g id="Group-25" fill-rule="nonzero"><g id="2"><path id="Shape" fill="url(#linearGradient-1)" d="M91.5880863,4.17652823 L4.17996544,91.5127728 C-0.519240605,96.2081146 -0.519240605,103.791885 4.17996544,108.487227 L91.5880863,195.823472 C96.2872923,200.518814 103.877304,200.518814 108.57651,195.823472 L145.225487,159.204632 C149.433969,154.999611 149.433969,148.181924 145.225487,143.976903 C141.017005,139.771881 134.193707,139.771881 129.985225,143.976903 L102.20193,171.737352 C101.032305,172.906015 99.2571609,172.906015 98.0875359,171.737352 L28.285908,101.993122 C27.1162831,100.824459 27.1162831,99.050775 28.285908,97.8821118 L98.0875359,28.1378823 C99.2571609,26.9692191 101.032305,26.9692191 102.20193,28.1378823 L129.985225,55.8983314 C134.193707,60.1033528 141.017005,60.1033528 145.225487,55.8983314 C149.433969,51.69331 149.433969,44.8756232 145.225487,40.6706018 L108.58055,4.05574592 C103.862049,-0.537986846 96.2692618,-0.500797906 91.5880863,4.17652823 Z"/><path id="Shape" fill="url(#linearGradient-2)" d="M91.5880863,4.17652823 L4.17996544,91.5127728 C-0.519240605,96.2081146 -0.519240605,103.791885 4.17996544,108.487227 L91.5880863,195.823472 C96.2872923,200.518814 103.877304,200.518814 108.57651,195.823472 L145.225487,159.204632 C149.433969,154.999611 149.433969,148.181924 145.225487,143.976903 C141.017005,139.771881 134.193707,139.771881 129.985225,143.976903 L102.20193,171.737352 C101.032305,172.906015 99.2571609,172.906015 98.0875359,171.737352 L28.285908,101.993122 C27.1162831,100.824459 27.1162831,99.050775 28.285908,97.8821118 L98.0875359,28.1378823 C100.999864,25.6271836 105.751642,20.541824 112.729652,19.3524487 C117.915585,18.4685261 123.585219,20.4140239 129.738554,25.1889424 C125.624663,21.0784292 118.571995,14.0340304 108.58055,4.05574592 C103.862049,-0.537986846 96.2692618,-0.500797906 91.5880863,4.17652823 Z"/></g><path id="Shape" fill="url(#linearGradient-3)" d="M153.685633,135.854579 C157.894115,140.0596 164.717412,140.0596 168.925894,135.854579 L195.959977,108.842726 C200.659183,104.147384 200.659183,96.5636133 195.960527,91.8688194 L168.690777,64.7181159 C164.472332,60.5180858 157.646868,60.5241425 153.435895,64.7316526 C149.227413,68.936674 149.227413,75.7543607 153.435895,79.9593821 L171.854035,98.3623765 C173.02366,99.5310396 173.02366,101.304724 171.854035,102.473387 L153.685633,120.626849 C149.47715,124.83187 149.47715,131.649557 153.685633,135.854579 Z"/></g><ellipse id="Combined-Shape" cx="100.519" cy="100.437" fill="url(#linearGradient-4)" rx="23.6" ry="23.581"/></g></g></g></g></svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@@ -0,0 +1,5 @@
<svg width="42" height="42" xmlns="http://www.w3.org/2000/svg">
<g>
<path fill="#070707" d="m6.717392,13.773912l5.6,0c2.8,0 4.7,1.9 4.7,4.7c0,2.8 -2,4.7 -4.9,4.7l-2.5,0l0,4.3l-2.9,0l0,-13.7zm2.9,2.2l0,4.9l1.9,0c1.6,0 2.6,-0.9 2.6,-2.4c0,-1.6 -0.9,-2.4 -2.6,-2.4l-1.9,0l0,-0.1zm8.9,11.5l2.7,0l0,-5.7c0,-1.4 0.8,-2.3 2.2,-2.3c0.4,0 0.8,0.1 1,0.2l0,-2.4c-0.2,-0.1 -0.5,-0.1 -0.8,-0.1c-1.2,0 -2.1,0.7 -2.4,2l-0.1,0l0,-1.9l-2.7,0l0,10.2l0.1,0zm11.7,0.1c-3.1,0 -5,-2 -5,-5.3c0,-3.3 2,-5.3 5,-5.3s5,2 5,5.3c0,3.4 -1.9,5.3 -5,5.3zm0,-2.1c1.4,0 2.2,-1.1 2.2,-3.2c0,-2 -0.8,-3.2 -2.2,-3.2c-1.4,0 -2.2,1.2 -2.2,3.2c0,2.1 0.8,3.2 2.2,3.2z" class="st0" id="Ant-Design-Pro"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 677 B

4
dashboard/src/access.ts Normal file
View File

@@ -0,0 +1,4 @@
// src/access.ts
export default function access() {
return {};
}

79
dashboard/src/app.tsx Normal file
View File

@@ -0,0 +1,79 @@
import React from 'react';
import { notification } from 'antd';
import { RequestConfig, RunTimeLayoutConfig } from 'umi';
import { ResponseError } from 'umi-request';
import Footer from '@/components/Footer';
import RightContent from '@/components/RightContent';
import { PageLoading, Settings as LayoutSettings } from '@ant-design/pro-layout';
import defaultSettings from '../config/defaultSettings';
export const initialStateConfig = {
loading: <PageLoading />,
};
export async function getInitialState(): Promise<{
settings?: LayoutSettings;
}> {
return {
settings: defaultSettings,
};
}
export const layout: RunTimeLayoutConfig = ({ initialState }) => {
return {
rightContentRender: () => <RightContent />,
disableContentMargin: false,
footerRender: () => <Footer />,
menuHeaderRender: undefined,
// custom 403 page
// unAccessible: <div>unAccessible</div>,
...initialState?.settings,
};
};
const codeMessage = {
200: 'The server successfully returned the requested data. ',
201: 'Create or modify data successfully. ',
202: 'A request has entered the background queue (asynchronous task). ',
204: 'Delete data successfully. ',
400: 'There was an error in the request sent, and the server did not create or modify data. ',
401: 'The user does not have permission (the token, username, password are wrong). ',
403: 'The user is authorized, but access is forbidden. ',
404: 'The request sent is for a record that does not exist, and the server is not operating. ',
405: 'The requested method is not allowed. ',
406: 'The requested format is not available. ',
410: 'The requested resource has been permanently deleted and will no longer be available. ',
422: 'When creating an object, a validation error occurred. ',
500: 'An error occurred in the server, please check the server. ',
502: 'Gateway error. ',
503: 'The service is unavailable, the server is temporarily overloaded or maintained. ',
504: 'The gateway has timed out. ',
};
const errorHandler = (error: ResponseError) => {
const { response, data } = error;
if (response && response.status) {
const errorText = data?.data || codeMessage[response.status] || response.statusText;
const { status, url } = response;
notification.error({
message: `Request error ${status}: ${url}`,
description: errorText,
});
}
if (!response) {
notification.error({
description: 'Your network is abnormal and cannot connect to the server',
message: 'Network failure',
});
}
throw error;
};
export const request: RequestConfig = {
errorHandler,
};

View File

@@ -1,148 +0,0 @@
import { Form, Input, Select } from 'antd';
import { connect } from 'dva';
import React from 'react';
import _ from 'lodash';
const { Option } = Select;
const layout = {
labelCol: {
span: 8,
},
wrapperCol: {
span: 16,
},
};
@connect(() => ({}))
export default class CreateTraitItem extends React.PureComponent {
formRefStep2 = React.createRef();
constructor(props) {
super(props);
this.state = {
parameters: [],
};
}
componentDidMount() {
this.props.onRef(this);
if (this.props.initialValues && this.props.initialValues.name) {
this.traitSelectChange(this.props.initialValues.name, 2);
}
}
getSelectValue = () => {
return this.formRefStep2.current.getFieldsValue();
};
resetFields = () => {
return this.formRefStep2.current.resetFields();
};
validateFields = () => {
return this.formRefStep2.current.validateFields();
};
setDefaultValue = (traitType) => {
this.formRefStep2.current.setFieldsValue({ name: traitType });
this.traitSelectChange(traitType);
};
traitSelectChange = async (value, isType = 1) => {
if (value) {
const res = await this.props.dispatch({
type: 'trait/getTraitByName',
payload: {
traitName: value,
},
});
this.setState({
parameters: res.parameters,
});
if (isType === 2) {
this.formRefStep2.current.setFieldsValue(this.props.initialValues);
} else if (isType) {
// 进行默认值填写
const parameters = _.get(res, 'parameters', []);
if (parameters.length) {
const initialObj = {};
parameters.forEach((item) => {
if (item.default) {
initialObj[item.name] = item.default;
}
});
this.formRefStep2.current.setFieldsValue(initialObj);
}
}
}
};
render() {
const { availableTraitList } = this.props;
return (
<Form
labelAlign="left"
{...layout}
ref={this.formRefStep2}
name="control-ref"
className="traitItem"
>
<Form.Item
name="name"
label="Trait"
rules={[{ required: true, message: 'Please Select a Trait!' }]}
>
<Select placeholder="Select a Trait" onChange={this.traitSelectChange}>
{availableTraitList.map((item) => {
return (
<Option value={item.name} key={item.name}>
{item.name}
</Option>
);
})}
</Select>
</Form.Item>
<Form.Item label="Properties" />
<div className="relativeBox">
{this.state.parameters ? (
this.state.parameters.map((item) => {
return item.type === 4 ? (
<Form.Item
name={item.name}
label={item.name}
key={item.name}
rules={[
{
required: item.required || false,
message: `Please input ${item.name} !`,
},
{ pattern: /^[0-9]*$/, message: `${item.name} only use digits(0-9).` },
]}
>
<Input />
</Form.Item>
) : (
<Form.Item
name={item.name}
label={item.name}
key={item.name}
rules={[
{
required: item.required || false,
message: `Please input ${item.name} !`,
},
{ pattern: /^[^\s]*$/, message: 'Spaces are not allowed!' },
]}
>
<Input />
</Form.Item>
);
})
) : (
<></>
)}
</div>
</Form>
);
}
}

View File

@@ -0,0 +1,5 @@
import React from 'react';
import { DefaultFooter } from '@ant-design/pro-layout';
export default () => <DefaultFooter copyright="2020 All Rights Reserved by KubeVela" links={[]} />;

View File

@@ -1,36 +0,0 @@
import { Tag } from 'antd';
import React from 'react';
import { connect } from 'umi';
import WorkSpaceDropDown from './WorkSpaceDropDown';
import styles from './index.less';
const ENVTagColor = {
dev: 'orange',
test: 'green',
pre: '#87d068',
};
const GlobalHeaderRight = (props) => {
const { theme, layout } = props;
let className = styles.right;
if (theme === 'dark' && layout === 'top') {
className = `${styles.right} ${styles.dark}`;
}
return (
<div className={className}>
{REACT_APP_ENV && (
<span>
<Tag color={ENVTagColor[REACT_APP_ENV]}>{REACT_APP_ENV}</Tag>
</span>
)}
<WorkSpaceDropDown />
</div>
);
};
export default connect(({ settings }) => ({
theme: settings.navTheme,
layout: settings.layout,
}))(GlobalHeaderRight);

View File

@@ -1,96 +0,0 @@
.ant-pro-global-header-layout-side {
padding-right: 0;
}
.ant-dropdown-menu-item,
.ant-dropdown-menu-submenu-title {
clear: both;
margin: 0;
padding: 5px 20px;
color: deepskyblue;
font-weight: normal;
font-size: 14px;
line-height: 22px;
white-space: nowrap;
cursor: pointer;
transition: all 0.3s;
border-top: 1px solid #dee4e6;
}
.ant-dropdown-menu-item:nth-child(1) {
border-top: 1px solid #fff;
}
.ant-dropdown-menu-item-active {
background: rgb(0, 21, 41) !important;
}
.ant-dropdown-menu-item-active .box1 {
color: white;
}
.ant-dropdown-menu-item-active .box2 {
color: white;
}
.box {
display: flex;
width: 100%;
flex-direction: column;
}
.box1 {
font-size: 16px;
color: #5095d4;
}
.box2 {
font-size: 12px;
color: #8d959b;
}
.ant-dropdown-trigger {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
height: 100%;
}
.drop-box {
display: flex;
flex-direction: row;
align-items: center;
justify-content: left;
height: 100%;
background: rgb(0, 21, 41);
padding: 0 20px;
}
.btn-box {
display: flex;
flex-direction: column;
align-items: space-between;
overflow: hidden;
margin-right: 20px;
min-width: 120px;
}
.btn-top {
display: flex;
height: 20px;
line-height: 20px;
font-size: 20px;
color: white;
}
.btn-bottom {
display: flex;
height: 20px;
line-height: 20px;
font-size: 12px;
color: #8d959b;
}
.btn-outlined {
fontsize: 15px;
color: #fff;
}

View File

@@ -1,98 +0,0 @@
import { Menu, Dropdown, message } from 'antd';
import { DownOutlined } from '@ant-design/icons';
import React from 'react';
import { connect } from 'dva';
import './WorkSpaceDropDown.css';
@connect((env) => ({ envs: env.envs }))
export default class WorkSpaceDropDown extends React.Component {
constructor(props) {
super(props);
this.state = {
workSpaceName: '',
namespace: '',
};
}
async componentDidMount() {
const envs = await this.props.dispatch({
type: 'envs/getEnvs',
});
if (envs) {
const { envName, namespace } = envs.find((env) => {
return env.current === '*';
});
this.setState({
workSpaceName: envName,
namespace,
});
this.props.dispatch({
type: 'globalData/currentEnv',
payload: {
currentEnv: envName,
},
});
}
}
handleMenuClick = async (e) => {
// 发送切换envs的接口
const switchResult = await this.props.dispatch({
type: 'envs/switchEnv',
payload: {
currentEnv: e.key,
},
});
if (switchResult) {
message.success(switchResult);
}
this.setState(
{
workSpaceName: e.key,
namespace: e.item.props.title,
},
() => {
// 值切换存储
this.props.dispatch({
type: 'globalData/currentEnv',
payload: {
currentEnv: e.key,
},
});
},
);
await this.props.dispatch({
type: 'envs/getEnvs', // applist对应models层的命名空间namespace
});
};
render() {
const { envs } = this.props;
const menu = (
<Menu onClick={this.handleMenuClick}>
{envs.envs &&
envs.envs.map((item) => {
return (
<Menu.Item key={item.envName} title={item.namespace}>
<div className="box">
<div className="box1">{item.envName}</div>
<div className="box2">{item.namespace}</div>
</div>
</Menu.Item>
);
})}
</Menu>
);
return (
<Dropdown overlay={menu}>
<div className="drop-box">
<div className="btn-box">
<div className="btn-top">{this.state.workSpaceName}</div>
<div className="btn-bottom">{this.state.namespace}</div>
</div>
<DownOutlined style={{ fontSize: '15px', color: '#ffffff' }} />
</div>
</Dropdown>
);
}
}

View File

@@ -0,0 +1,16 @@
@import '~antd/es/style/themes/default.less';
.container > * {
background-color: @popover-bg;
border-radius: 4px;
box-shadow: @shadow-1-down;
}
@media screen and (max-width: @screen-xs) {
.container {
width: 100% !important;
}
.container > * {
border-radius: 0 !important;
}
}

View File

@@ -0,0 +1,21 @@
import React from 'react';
import { Dropdown } from 'antd';
import { DropDownProps } from 'antd/es/dropdown';
import classNames from 'classnames';
import styles from './index.less';
declare type OverlayFunc = () => React.ReactNode;
export interface HeaderDropdownProps extends Omit<DropDownProps, 'overlay'> {
overlayClassName?: string;
overlay: React.ReactNode | OverlayFunc | any;
placement?: 'bottomLeft' | 'bottomRight' | 'topLeft' | 'topCenter' | 'topRight' | 'bottomCenter';
}
const HeaderDropdown: React.FC<HeaderDropdownProps> = ({ overlayClassName: cls, ...restProps }) => (
<Dropdown overlayClassName={classNames(styles.container, cls)} {...restProps} />
);
export default HeaderDropdown;

View File

@@ -1,4 +0,0 @@
import { PageLoading } from '@ant-design/pro-layout'; // loading components from code split
// https://umijs.org/plugin/umi-plugin-react.html#dynamicimport
export default PageLoading;

View File

@@ -0,0 +1,66 @@
import React from 'react';
import { Menu, message, Spin, Typography } from 'antd';
import { useModel } from 'umi';
import { DownOutlined } from '@ant-design/icons';
import HeaderDropdown from '../HeaderDropdown';
import styles from './index.less';
export default () => {
const {
environments,
currentEnvironment,
switchCurrentEnvironment: switchEnvironment,
} = useModel('useEnvironmentModel');
const menu = (
<Menu
className={styles.menu}
selectedKeys={currentEnvironment == null ? undefined : [currentEnvironment.envName]}
onClick={(e) => {
switchEnvironment(e.key.toString()).then((env) => {
if (env == null) {
return;
}
message.success({
content: `Set environment succeed, current environment is ${env.envName}, namespace is ${env.namespace}`,
key: 'switchEnvironment',
});
});
}}
>
{environments &&
environments.map((item) => {
return (
<Menu.Item key={item.envName} title={item.namespace}>
<div>
<Typography.Text>{item.envName}</Typography.Text>
</div>
<div>
<Typography.Text type="secondary">
<small>{item.namespace}</small>
</Typography.Text>
</div>
</Menu.Item>
);
})}
</Menu>
);
return (
<HeaderDropdown overlay={menu}>
<div className={`${styles.action}`}>
{environments == null || currentEnvironment == null ? (
<Spin size="small" />
) : (
<>
<span className={`${styles.name} anticon`}>{currentEnvironment?.envName}</span>
<DownOutlined style={{ marginLeft: '5px' }} />
</>
)}
</div>
</HeaderDropdown>
);
};

View File

@@ -20,7 +20,7 @@
.action {
display: flex;
align-items: center;
height: 100%;
height: 48px;
padding: 0 12px;
cursor: pointer;
transition: all 0.3s;
@@ -42,7 +42,6 @@
}
.account {
.avatar {
margin: ~'calc((@{layout-header-height} - 24px) / 2)' 0;
margin-right: 8px;
color: @primary-color;
vertical-align: top;
@@ -53,52 +52,11 @@
.dark {
.action {
color: rgba(255, 255, 255, 0.85);
> span {
color: rgba(255, 255, 255, 0.85);
&:hover {
background: #252a3d;
}
&:hover,
&:global(.opened) {
background: @primary-color;
}
}
}
:global(.ant-pro-global-header) {
.dark {
.action {
color: @text-color;
> span {
color: @text-color;
}
&:hover {
color: rgba(255, 255, 255, 0.85);
> span {
color: rgba(255, 255, 255, 0.85);
}
}
}
}
}
@media only screen and (max-width: @screen-md) {
:global(.ant-divider-vertical) {
vertical-align: unset;
}
.name {
display: none;
}
.right {
position: absolute;
top: 0;
right: 12px;
.account {
.avatar {
margin-right: 0;
}
}
.search {
display: none;
background: #252a3d;
}
}
}

View File

@@ -0,0 +1,42 @@
import React from 'react';
import { Space, Tag } from 'antd';
import { SelectLang, useModel } from 'umi';
import styles from './index.less';
import WorkSpaceDropDown from './WorkSpaceDropDown';
export type SiderTheme = 'light' | 'dark';
const ENVTagColor = {
dev: 'orange',
test: 'green',
pre: '#87d068',
};
const GlobalHeaderRight: React.FC<{}> = () => {
const { initialState } = useModel('@@initialState');
if (!initialState || !initialState.settings) {
return null;
}
const { navTheme, layout } = initialState.settings;
let className = styles.right;
if ((navTheme === 'dark' && layout === 'top') || layout === 'mix') {
className = `${styles.right} ${styles.dark}`;
}
return (
<Space className={className}>
{REACT_APP_ENV && (
<span>
<Tag color={ENVTagColor[REACT_APP_ENV]}>{REACT_APP_ENV}</Tag>
</span>
)}
<WorkSpaceDropDown />
<SelectLang className={styles.action} />
</Space>
);
};
export default GlobalHeaderRight;

View File

@@ -1,362 +0,0 @@
import React, { Fragment } from 'react';
import { PageContainer } from '@ant-design/pro-layout';
import { Button, Row, Col, Modal, Select, message, Breadcrumb, Form, Input } from 'antd';
import './index.less';
import { connect } from 'dva';
import { Link } from 'umi';
import _ from 'lodash';
const { Option } = Select;
const layout = {
labelCol: {
span: 8,
},
wrapperCol: {
span: 16,
},
};
@connect(({ loading, applist, globalData }) => ({
loadingAll: loading.models.applist,
currentEnv: globalData.currentEnv,
returnObj: applist.returnObj,
}))
class Trait extends React.Component {
formRefStep2 = React.createRef();
constructor(props) {
super(props);
this.state = {
visible: false,
selectValue: null,
compList: [],
};
}
componentDidMount() {
this.getInitialData();
}
shouldComponentUpdate(nextProps) {
if (nextProps.currentEnv === this.props.currentEnv) {
return true;
}
this.props.dispatch({
type: 'applist/getList',
payload: {
url: `/api/envs/${nextProps.currentEnv}/apps/`,
},
});
return true;
}
getInitialData = async () => {
if (this.props.currentEnv) {
await this.props.dispatch({
type: 'applist/getList',
payload: {
url: `/api/envs/${this.props.currentEnv}/apps/`,
},
});
}
};
showModal = () => {
this.setState(
{
visible: true,
},
() => {
if (this.formRefStep2.current) {
this.formRefStep2.current.resetFields();
}
},
);
};
handleOk = async () => {
await this.formRefStep2.current.validateFields();
const { title } = this.props.propsObj;
if (title) {
const submitObj = {
name: title,
flags: [],
};
const submitData = this.formRefStep2.current.getFieldValue();
Object.keys(submitData).forEach((currentKey) => {
if (
currentKey !== 'name' &&
currentKey !== 'appName' &&
currentKey !== 'compName' &&
submitData[currentKey]
) {
submitObj.flags.push({
name: currentKey,
value: submitData[currentKey].toString(),
});
}
});
const { currentEnv: envName } = this.props;
const { appName, compName } = submitData;
if (envName && appName && compName) {
const res = await this.props.dispatch({
type: 'trait/attachOneTraits',
payload: {
envName,
appName,
compName,
params: submitObj,
},
});
if (res) {
this.setState({
visible: false,
});
message.success(res);
const { history } = this.props.propsObj;
history.push({
pathname: `/ApplicationList/${appName}/Components`,
state: { appName, envName },
});
}
}
}
};
handleCancel = () => {
this.setState({
visible: false,
});
};
onChange = async (value) => {
this.setState({
selectValue: value,
compList: [],
});
const res = await this.props.dispatch({
type: 'applist/getAppDetail',
payload: {
envName: this.props.currentEnv,
appName: value,
},
});
if (res) {
const compData = _.get(res, 'components', []);
const compList = [];
compData.forEach((item) => {
compList.push({
compName: item.name,
});
});
this.setState({
compList,
});
}
};
onSearch = () => {};
render() {
const { btnValue, title, settings = [], btnIsShow, crdInfo, appliesTo } = this.props.propsObj;
const initialObj = {};
if (settings.length) {
settings.forEach((item) => {
if (item.default) {
initialObj[item.name] = item.default;
}
});
}
let appList = _.get(this.props, 'returnObj', []);
if (!appList) {
appList = [];
}
const { compList = [] } = this.state;
return (
<div>
<div className="breadCrumb">
<Breadcrumb>
<Breadcrumb.Item>
<Link to="/ApplicationList">Home</Link>
</Breadcrumb.Item>
<Breadcrumb.Item>Traits</Breadcrumb.Item>
<Breadcrumb.Item>{title}</Breadcrumb.Item>
</Breadcrumb>
</div>
<PageContainer>
<Row>
<Col span="11">
<div className="deployment">
<Row>
<Col span="22">
<p className="title">{title}</p>
{crdInfo ? (
<p>
{crdInfo.apiVersion}
<span>,kind=</span>
{crdInfo.kind}
</p>
) : (
<p />
)}
</Col>
</Row>
<Row>
<Col span="22">
<p className="title">Applies To:</p>
<p>{Array.isArray(appliesTo) ? appliesTo.join(', ') : appliesTo}</p>
</Col>
</Row>
<p className="title">Configurable Properties:</p>
{settings.map((item, index) => {
return (
<Row key={index.toString()}>
<Col span="8">
<p>{item.name}</p>
</Col>
<Col span="16">
<p>{item.default || item.usage}</p>
</Col>
</Row>
);
})}
</div>
<Button
type="primary"
className="create-button"
onClick={this.showModal}
style={{ display: btnIsShow ? 'block' : 'none' }}
>
{btnValue}
</Button>
<Modal
title="Attach Trait"
visible={this.state.visible}
onOk={this.handleOk}
onCancel={this.handleCancel}
footer={[
<Button key="back" onClick={this.handleCancel}>
Cancel
</Button>,
<Button key="submit" type="primary" onClick={this.handleOk}>
Submit
</Button>,
]}
>
<Form
labelAlign="left"
{...layout}
ref={this.formRefStep2}
name="control-ref"
className="traitItem"
initialValues={initialObj}
>
<Form.Item
label="App"
name="appName"
rules={[{ required: true, message: 'Please Select a Application!' }]}
>
<Select
showSearch
value={this.state.selectValue}
style={{ width: '100%' }}
placeholder="Select a Application"
optionFilterProp="children"
onChange={this.onChange}
onSearch={this.onSearch}
filterOption={(input, option) =>
option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
>
{appList.length ? (
appList.map((item, index) => {
return (
<Option key={index.toString()} value={item.name}>
{item.name}
</Option>
);
})
) : (
<Fragment />
)}
</Select>
</Form.Item>
<Form.Item
label="Component"
name="compName"
rules={[{ required: true, message: 'Please Select a Component!' }]}
>
<Select
allowClear
// value={this.state.selectValue}
style={{ width: '100%' }}
placeholder="Select a Component"
>
{compList.length ? (
compList.map((item) => {
return (
<Option key={item.compName} value={item.compName}>
{item.compName}
</Option>
);
})
) : (
<Fragment />
)}
</Select>
</Form.Item>
<div className="relativeBox">
<Form.Item label="Properties" />
{settings ? (
settings.map((item) => {
return item.type === 4 ? (
<Form.Item
name={item.name}
label={item.name}
key={item.name}
rules={[
{
required: item.required || false,
message: `Please input ${item.name} !`,
},
{
pattern: /^[0-9]*$/,
message: `${item.name} only use digits(0-9).`,
},
]}
>
<Input />
</Form.Item>
) : (
<Form.Item
name={item.name}
label={item.name}
key={item.name}
rules={[
{
required: item.required || false,
message: `Please input ${item.name} !`,
},
{ pattern: /^[^\s]*$/, message: 'Spaces are not allowed!' },
]}
>
<Input />
</Form.Item>
);
})
) : (
<></>
)}
</div>
</Form>
</Modal>
</Col>
</Row>
</PageContainer>
</div>
);
}
}
export default Trait;

View File

@@ -1,27 +0,0 @@
.deployment {
position: relative;
padding: 10px;
padding-left: 16px;
background-color: #fff;
border: 1px solid #eee;
a {
position: absolute;
top: 10px;
right: 16px;
font-size: 20px;
}
.title {
margin: 0;
font-size: 18px;
line-height: 36px;
}
p {
font-size: 12px;
line-height: 20px;
}
}
.create-button {
float: right;
margin-top: 16px;
text-align: right;
}

View File

@@ -1,226 +0,0 @@
import React, { Fragment } from 'react';
import { PageContainer } from '@ant-design/pro-layout';
import { Button, Row, Col, Modal, Select, Breadcrumb, Form } from 'antd';
import { connect } from 'dva';
import { Link } from 'umi';
import _ from 'lodash';
import './index.less';
const { Option } = Select;
const layout = {
labelCol: {
span: 8,
},
wrapperCol: {
span: 16,
},
};
@connect(({ loading, applist, globalData }) => ({
loadingAll: loading.models.applist,
currentEnv: globalData.currentEnv,
returnObj: applist.returnObj,
}))
export default class Workload extends React.Component {
formRefStep2 = React.createRef();
constructor(props) {
super(props);
this.state = {
visible: false,
};
}
componentDidMount() {
this.getInitialData();
}
shouldComponentUpdate(nextProps) {
if (nextProps.currentEnv === this.props.currentEnv) {
return true;
}
this.props.dispatch({
type: 'applist/getList',
payload: {
url: `/api/envs/${nextProps.currentEnv}/apps/`,
},
});
return true;
}
getInitialData = async () => {
if (this.props.currentEnv) {
await this.props.dispatch({
type: 'applist/getList',
payload: {
url: `/api/envs/${this.props.currentEnv}/apps/`,
},
});
}
};
showModal = () => {
this.setState(
{
visible: true,
},
() => {
if (this.formRefStep2.current) {
this.formRefStep2.current.resetFields();
}
},
);
};
handleOk = async () => {
const submitData = await this.formRefStep2.current.validateFields();
const { history } = this.props.propsObj;
history.push({
pathname: `/ApplicationList/${submitData.appName}/createComponent`,
state: {
...submitData,
isCreate: false,
envName: this.props.currentEnv,
WorkloadType: this.props.propsObj.title,
},
});
};
handleCancel = () => {
this.setState({
visible: false,
});
};
onChange = () => {};
onSearch = () => {};
render() {
const { btnValue, title, crdInfo, settings, btnIsShow } = this.props.propsObj;
let appList = _.get(this.props, 'returnObj', []);
if (!appList) {
appList = [];
}
return (
<div>
<div className="breadCrumb">
<Breadcrumb>
<Breadcrumb.Item>
<Link to="/ApplicationList">Home</Link>
</Breadcrumb.Item>
<Breadcrumb.Item>Workloads</Breadcrumb.Item>
<Breadcrumb.Item>{title}</Breadcrumb.Item>
</Breadcrumb>
</div>
<PageContainer>
<Row>
<Col span="11">
<div className="deployment">
<Row>
<Col span="22">
<p className="title">{title}</p>
{crdInfo ? (
<p>
{crdInfo.apiVersion}
<span>,kind=</span>
{crdInfo.kind}
</p>
) : (
<p />
)}
</Col>
</Row>
<p className="title">Configurable Settings:</p>
{settings.map((item, index) => {
if (item.name === 'name') {
return <Fragment key={index.toString()} />;
}
return (
<Row key={index.toString()}>
<Col span="8">
<p>{item.name}</p>
</Col>
<Col span="16">
{
// eslint-disable-next-line consistent-return
}
<p>{item.default || item.usage}</p>
</Col>
</Row>
);
})}
</div>
{/* <Link to={{ pathname, state }} style={{ display: btnIsShow ? 'block' : 'none' }}>
<Button type="primary" className="create-button">
{btnValue}
</Button>
</Link> */}
<Button
type="primary"
className="create-button"
onClick={() => this.showModal()}
style={{ display: btnIsShow ? 'block' : 'none' }}
>
{btnValue}
</Button>
</Col>
</Row>
<Modal
title="Add Component"
visible={this.state.visible}
onOk={this.handleOk}
onCancel={this.handleCancel}
footer={[
<Button key="back" onClick={this.handleCancel}>
Cancel
</Button>,
<Button key="submit" type="primary" onClick={this.handleOk}>
Next
</Button>,
]}
>
<Form
labelAlign="left"
{...layout}
ref={this.formRefStep2}
name="control-ref"
className="traitItem"
>
<Form.Item
label="App"
name="appName"
rules={[{ required: true, message: 'Please Select a Application!' }]}
>
<Select
showSearch
style={{ width: '100%' }}
placeholder="Select a Application"
optionFilterProp="children"
onChange={this.onChange}
onSearch={this.onSearch}
filterOption={(input, option) =>
option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
>
{appList.length ? (
appList.map((item, index) => {
return (
<Option key={index.toString()} value={item.name}>
{item.name}
</Option>
);
})
) : (
<Fragment />
)}
</Select>
</Form.Item>
</Form>
</Modal>
</PageContainer>
</div>
);
}
}

View File

@@ -1,27 +0,0 @@
.deployment {
position: relative;
padding: 10px;
padding-left: 16px;
background-color: #fff;
border: 1px solid #eee;
a {
position: absolute;
top: 10px;
right: 16px;
font-size: 20px;
}
.title {
margin: 0;
font-size: 18px;
line-height: 36px;
}
p {
font-size: 12px;
line-height: 20px;
}
}
.create-button {
float: right;
margin-top: 16px;
text-align: right;
}

View File

@@ -1 +0,0 @@
export default undefined;

View File

@@ -29,6 +29,13 @@ beforeEach(async () => {
describe('Ant Design Pro E2E test', () => {
const testPage = (path) => async () => {
await page.goto(`${BASE_URL}${path}`);
await page.waitForSelector('footer', {
timeout: 2000,
});
const haveFooter = await page.evaluate(
() => document.getElementsByTagName('footer').length > 0,
);
expect(haveFooter).toBeTruthy();
};
const routers = formatter(RouterConfig);
@@ -39,5 +46,12 @@ describe('Ant Design Pro E2E test', () => {
it('topmenu should have footer', async () => {
const params = '?navTheme=light&layout=topmenu';
await page.goto(`${BASE_URL}${params}`);
await page.waitForSelector('footer', {
timeout: 2000,
});
const haveFooter = await page.evaluate(
() => document.getElementsByTagName('footer').length > 0,
);
expect(haveFooter).toBeTruthy();
});
});

View File

@@ -13,9 +13,6 @@ body,
.ant-layout {
min-height: 100vh;
}
.ant-card {
margin-bottom: 30px !important;
}
canvas {
display: block;
@@ -55,49 +52,3 @@ ol {
min-height: 100vh;
}
}
// 首页导航标题样式
#logo {
padding: 16px 8px;
img {
display: none;
}
}
// 面包屑样式调整
.ant-page-header {
padding: 12px 24px !important;
}
.ant-page-header-heading {
display: none !important;
}
.ant-pro-page-container-warp {
display: none;
}
.ant-pro-basicLayout-content {
margin: 0 !important;
}
.ant-pro-basicLayout-content .ant-pro-page-container {
margin: 0 !important;
}
.breadCrumb {
padding: 12px 24px;
background: #fff;
}
.ant-breadcrumb a:hover {
color: #1b58f4 !important;
}
// 对齐
.ant-form-item-label > label::before {
display: inline-block;
width: 7.09px;
height: 14px;
margin-right: 4px;
color: rgb(255, 77, 79);
font-size: 14px;
font-family: SimSun, sans-serif;
line-height: 1;
content: '';
}
.ant-spin-nested-loading {
height: calc(100% - 46px) !important;
}

View File

@@ -1,35 +1,32 @@
import { Button, message, notification } from 'antd';
import React from 'react';
import { useIntl } from 'umi';
import defaultSettings from '../config/defaultSettings';
const { pwa } = defaultSettings; // if pwa is true
const { pwa } = defaultSettings;
const isHttps = document.location.protocol === 'https:';
// if pwa is true
if (pwa) {
// Notify user if offline now
window.addEventListener('sw.offline', () => {
message.warning(
useIntl().formatMessage({
id: 'app.pwa.offline',
}),
);
}); // Pop up a prompt on the page asking the user if they want to use the latest version
window.addEventListener('sw.updated', (event) => {
const e = event;
message.warning(useIntl().formatMessage({ id: 'app.pwa.offline' }));
});
// Pop up a prompt on the page asking the user if they want to use the latest version
window.addEventListener('sw.updated', (event: Event) => {
const e = event as CustomEvent;
const reloadSW = async () => {
// Check if there is sw whose state is waiting in ServiceWorkerRegistration
// https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration
const worker = e.detail && e.detail.waiting;
if (!worker) {
return true;
} // Send skip-waiting event to waiting SW with MessageChannel
}
// Send skip-waiting event to waiting SW with MessageChannel
await new Promise((resolve, reject) => {
const channel = new MessageChannel();
channel.port1.onmessage = (msgEvent) => {
if (msgEvent.data.error) {
reject(msgEvent.data.error);
@@ -37,19 +34,12 @@ if (pwa) {
resolve(msgEvent.data);
}
};
worker.postMessage(
{
type: 'skip-waiting',
},
[channel.port2],
);
}); // Refresh current page to use the updated HTML and other assets after SW has skiped waiting
worker.postMessage({ type: 'skip-waiting' }, [channel.port2]);
});
// Refresh current page to use the updated HTML and other assets after SW has skiped waiting
window.location.reload(true);
return true;
};
const key = `open${Date.now()}`;
const btn = (
<Button
@@ -59,27 +49,20 @@ if (pwa) {
reloadSW();
}}
>
{useIntl().formatMessage({
id: 'app.pwa.serviceworker.updated.ok',
})}
{useIntl().formatMessage({ id: 'app.pwa.serviceworker.updated.ok' })}
</Button>
);
notification.open({
message: useIntl().formatMessage({
id: 'app.pwa.serviceworker.updated',
}),
description: useIntl().formatMessage({
id: 'app.pwa.serviceworker.updated.hint',
}),
message: useIntl().formatMessage({ id: 'app.pwa.serviceworker.updated' }),
description: useIntl().formatMessage({ id: 'app.pwa.serviceworker.updated.hint' }),
btn,
key,
onClose: async () => {},
});
});
} else if ('serviceWorker' in navigator) {
} else if ('serviceWorker' in navigator && isHttps) {
// unregister service worker
const { serviceWorker } = navigator;
if (serviceWorker.getRegistrations) {
serviceWorker.getRegistrations().then((sws) => {
sws.forEach((sw) => {
@@ -87,11 +70,11 @@ if (pwa) {
});
});
}
serviceWorker.getRegistration().then((sw) => {
if (sw) sw.unregister();
}); // remove all caches
});
// remove all caches
if (window.caches && window.caches.keys) {
caches.keys().then((keys) => {
keys.forEach((key) => {

View File

@@ -1,137 +0,0 @@
/**
* Ant Design Pro v4 use `@ant-design/pro-layout` to handle Layout.
* You can view component api by:
* https://github.com/ant-design/ant-design-pro-layout
*/
import ProLayout from '@ant-design/pro-layout';
import React, { useEffect, useState, useRef } from 'react';
import { Link, useIntl, connect, history } from 'umi';
import RightContent from '@/components/GlobalHeader/RightContent';
import {
MenuOutlined,
BranchesOutlined,
ApartmentOutlined,
DeploymentUnitOutlined,
SettingOutlined,
} from '@ant-design/icons';
import _ from 'lodash';
const AddIcon = (menuData) => {
return menuData.map((item) => {
const name = _.get(item, 'name', '');
if (name) {
if (name === 'Workload') {
// eslint-disable-next-line no-param-reassign
item.icon = <ApartmentOutlined />;
} else if (name === 'Traits') {
// eslint-disable-next-line no-param-reassign
item.icon = <BranchesOutlined />;
} else if (name === 'Capability') {
// eslint-disable-next-line no-param-reassign
item.icon = <DeploymentUnitOutlined />;
} else if (name === 'System') {
// eslint-disable-next-line no-param-reassign
item.icon = <SettingOutlined />;
} else {
// eslint-disable-next-line no-param-reassign
item.icon = <MenuOutlined />;
}
}
return item;
});
};
const BasicLayout = (props) => {
const { settings, dispatch, menus } = props;
const [currentSelectKeys, setCurrentSelectedKeys] = useState('');
const timerRef = useRef();
const getCurrentSelectKeys = () => {
const pathnameCur = props.history.location.pathname;
if (pathnameCur) {
if (pathnameCur.includes('Application')) {
setCurrentSelectedKeys(['applist']);
} else if (pathnameCur.includes('Capability')) {
setCurrentSelectedKeys(['Capability']);
} else if (pathnameCur.includes('System/Env')) {
setCurrentSelectedKeys(['Env']);
} else if (pathnameCur.includes('Workload')) {
const arr = pathnameCur.split('/');
const key = arr[arr.length - 1];
setCurrentSelectedKeys([key]);
} else if (pathnameCur.includes('Traits')) {
const arr = pathnameCur.split('/');
const key = arr[arr.length - 1];
setCurrentSelectedKeys([key]);
}
}
};
useEffect(() => {
if (dispatch) {
dispatch({
type: 'menus/getMenuData',
});
}
timerRef.current = props.history.listen((route) => {
getCurrentSelectKeys(route.pathname);
});
return () => {
if (timerRef.current) {
timerRef.current = null;
}
};
// setCurrentSelectedKeys('applist')
}, []);
const { formatMessage } = useIntl();
return (
<ProLayout
formatMessage={formatMessage}
onMenuHeaderClick={() => history.push('/')}
menuItemRender={(menuItemProps, defaultDom) => {
if (menuItemProps.isUrl || !menuItemProps.path) {
return defaultDom;
}
// return <Link to={menuItemProps.path}>{defaultDom}</Link>;
return (
<div
onClick={() => {
setCurrentSelectedKeys([menuItemProps.key]);
history.push(menuItemProps.path);
}}
>
{defaultDom}
</div>
);
}}
selectedKeys={currentSelectKeys}
breadcrumbRender={(routers = []) => [
{
path: '/',
breadcrumbName: formatMessage({
id: 'menu.home',
}),
},
...routers,
]}
itemRender={(route, params, routes, paths) => {
const first = routes.indexOf(route) === 0;
return first ? (
<Link to={paths.join('/')}>{route.breadcrumbName}</Link>
) : (
<span>{route.breadcrumbName}</span>
);
}}
// menuDataRender={menuDataRender}
menuDataRender={() => AddIcon(menus.menuData)}
rightContentRender={() => <RightContent />}
{...props}
{...settings}
/>
);
};
export default connect(({ global, settings, menus }) => ({
global,
settings,
menus,
}))(BasicLayout);

View File

@@ -1,13 +0,0 @@
import React from 'react';
import { connect } from 'umi';
class SecurityLayout extends React.Component {
render() {
const { children } = this.props;
return children;
}
}
export default connect(({ loading }) => ({
loading: loading.models.user,
}))(SecurityLayout);

View File

@@ -1,22 +0,0 @@
import component from './en-US/component';
import globalHeader from './en-US/globalHeader';
import menu from './en-US/menu';
import pwa from './en-US/pwa';
import settingDrawer from './en-US/settingDrawer';
import settings from './en-US/settings';
export default {
'navBar.lang': 'Languages',
'layout.user.link.help': 'Help',
'layout.user.link.privacy': 'Privacy',
'layout.user.link.terms': 'Terms',
'app.preview.down.block': 'Download this page to your local project',
'app.welcome.link.fetch-blocks': 'Get all block',
'app.welcome.link.block-list': 'Quickly build standard, pages based on `block` development',
...globalHeader,
...menu,
...settingDrawer,
...settings,
...pwa,
...component,
};

View File

@@ -0,0 +1,11 @@
import component from './en-US/component';
import menu from './en-US/menu';
import pages from './en-US/pages';
import pwa from './en-US/pwa';
export default {
...menu,
...pwa,
...component,
...pages,
};

View File

@@ -1,17 +0,0 @@
export default {
'component.globalHeader.search': 'Search',
'component.globalHeader.search.example1': 'Search example 1',
'component.globalHeader.search.example2': 'Search example 2',
'component.globalHeader.search.example3': 'Search example 3',
'component.globalHeader.help': 'Help',
'component.globalHeader.notification': 'Notification',
'component.globalHeader.notification.empty': 'You have viewed all notifications.',
'component.globalHeader.message': 'Message',
'component.globalHeader.message.empty': 'You have viewed all messsages.',
'component.globalHeader.event': 'Event',
'component.globalHeader.event.empty': 'You have viewed all events.',
'component.noticeIcon.clear': 'Clear',
'component.noticeIcon.cleared': 'Cleared',
'component.noticeIcon.empty': 'No notifications',
'component.noticeIcon.view-more': 'View more',
};

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