mirror of
https://github.com/kubevela/kubevela.git
synced 2026-08-27 16:17:34 +00:00
Merge branch 'master' into vela-up
This commit is contained in:
+35
-71
@@ -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
|
||||
|
||||
|
||||
@@ -94,6 +94,8 @@ 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.Parse()
|
||||
|
||||
|
||||
+55
-18
@@ -1,31 +1,68 @@
|
||||
# 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
|
||||
App running at:
|
||||
- Local: http://localhost:8000 (copied to clipboard)
|
||||
- Network: http://192.168.31.114:8000
|
||||
```
|
||||
|
||||
Install `node_modules`:
|
||||
## Development
|
||||
|
||||
### Install dependencies
|
||||
|
||||
```bash
|
||||
yarn
|
||||
```
|
||||
|
||||
## Provided Scripts
|
||||
|
||||
Scripts provided in `package.json`. It's safe to modify or add additional script:
|
||||
|
||||
### Start project
|
||||
|
||||
```bash
|
||||
yarn start
|
||||
```
|
||||
|
||||
### Build project
|
||||
### Build
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
```
|
||||
|
||||
### Check code style
|
||||
### Start up
|
||||
|
||||
```bash
|
||||
yarn start
|
||||
```
|
||||
|
||||
### Lint and Test
|
||||
|
||||
- Check code style
|
||||
|
||||
```bash
|
||||
yarn lint
|
||||
@@ -34,11 +71,11 @@ yarn lint
|
||||
You can also use script to auto fix some lint error:
|
||||
|
||||
```bash
|
||||
yarn lint:fix
|
||||
yarn prettier
|
||||
```
|
||||
|
||||
### Test code
|
||||
- Test code
|
||||
|
||||
```bash
|
||||
yarn test
|
||||
```
|
||||
```
|
||||
|
||||
@@ -31,14 +31,14 @@ export default ({ name, parameters }: ShowParameters) => {
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
width: 200,
|
||||
render: (text, row) => [
|
||||
render: (text, row) => (
|
||||
<Paragraph copyable={{ text: row.name }}>
|
||||
<Space size="small" align="center">
|
||||
{row.name}
|
||||
{!row.required ? undefined : <Tag color="geekblue">request</Tag>}
|
||||
</Space>
|
||||
</Paragraph>,
|
||||
],
|
||||
</Paragraph>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Short',
|
||||
@@ -46,11 +46,11 @@ export default ({ name, parameters }: ShowParameters) => {
|
||||
key: 'short',
|
||||
width: 100,
|
||||
responsive: ['md'],
|
||||
render: (text, row) => [
|
||||
render: (text, row) => (
|
||||
<Space size="small" align="center">
|
||||
{!row.short ? undefined : <Tag color="magenta">{text}</Tag>}
|
||||
</Space>,
|
||||
],
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Usage',
|
||||
@@ -71,11 +71,11 @@ export default ({ name, parameters }: ShowParameters) => {
|
||||
key: 'default',
|
||||
width: 200,
|
||||
responsive: ['md'],
|
||||
render: (text, row) => [
|
||||
render: (text, row) => (
|
||||
<Space size="small" align="center">
|
||||
{!row.default ? undefined : <Text code>{text}</Text>}
|
||||
</Space>,
|
||||
],
|
||||
{!row.default ? undefined : <Text code>{text.toString()}</Text>}
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
]}
|
||||
dataSource={parameters}
|
||||
|
||||
@@ -27,13 +27,13 @@ export default (): React.ReactNode => {
|
||||
<ShowComponent name={showTraits.name} parameters={showTraits.parameters} />
|
||||
<Card>
|
||||
<ProList<any>
|
||||
rowKey={(record) => record.name}
|
||||
rowKey="name"
|
||||
headerTitle="Type"
|
||||
pagination={{
|
||||
defaultPageSize: 5,
|
||||
showSizeChanger: false,
|
||||
}}
|
||||
loading={loading ? { delay: 300 } : undefined}
|
||||
loading={loading ? { delay: 60 } : undefined}
|
||||
dataSource={traitsList ?? []}
|
||||
split
|
||||
metas={{
|
||||
@@ -49,22 +49,15 @@ export default (): React.ReactNode => {
|
||||
);
|
||||
},
|
||||
},
|
||||
subTitle: {
|
||||
render: (text, row) => {
|
||||
return (
|
||||
<Space size={0}>
|
||||
<Tag color="green">{row.crdName}</Tag>
|
||||
</Space>
|
||||
);
|
||||
},
|
||||
},
|
||||
content: {
|
||||
render: (text, row) => {
|
||||
return (
|
||||
<Space size={0}>
|
||||
<Text strong>applies to: </Text>
|
||||
{row.appliesTo.map((item: string) => (
|
||||
<Tag color="processing">{item}</Tag>
|
||||
<Tag key={item} color="processing">
|
||||
{item}
|
||||
</Tag>
|
||||
))}
|
||||
</Space>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import { Button, Card, Space, Tag, Typography } from 'antd';
|
||||
import { Button, Card, Typography } from 'antd';
|
||||
import { useModel } from 'umi';
|
||||
import { PageContainer } from '@ant-design/pro-layout';
|
||||
import { FileWordTwoTone, SnippetsTwoTone } from '@ant-design/icons';
|
||||
@@ -50,15 +50,6 @@ export default (): React.ReactNode => {
|
||||
);
|
||||
},
|
||||
},
|
||||
subTitle: {
|
||||
render: (text, row) => {
|
||||
return (
|
||||
<Space size={0}>
|
||||
{!row.required ? undefined : <Tag color="#5BD8A6">Required</Tag>}
|
||||
</Space>
|
||||
);
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
render: (text, row) => [
|
||||
<Button
|
||||
|
||||
@@ -34,6 +34,15 @@
|
||||
insert-css "^2.0.0"
|
||||
rc-util "^5.0.1"
|
||||
|
||||
"@ant-design/pro-card@^1.8.3":
|
||||
version "1.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@ant-design/pro-card/-/pro-card-1.8.3.tgz#735796b47f7986e31242a7463506396234373472"
|
||||
integrity sha512-bUEDPGBVNlczllOHGQU3a6s6QiF3Lw9yI6FYOzTAuPKl5tlN1FSICX9GmM+gqibGYYgr0xLXJHh05nA9BA0bPg==
|
||||
dependencies:
|
||||
"@ant-design/icons" "^4.2.1"
|
||||
"@ant-design/pro-utils" "1.6.2"
|
||||
classnames "^2.2.6"
|
||||
|
||||
"@ant-design/pro-cli@^2.0.2":
|
||||
version "2.0.3"
|
||||
resolved "https://registry.npmjs.org/@ant-design/pro-cli/-/pro-cli-2.0.3.tgz"
|
||||
@@ -193,6 +202,13 @@
|
||||
dependencies:
|
||||
rc-util "^5.0.1"
|
||||
|
||||
"@ant-design/pro-provider@1.2.7":
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/@ant-design/pro-provider/-/pro-provider-1.2.7.tgz#aed6f0a52fb5f8d948c7087ed964febc97fcee91"
|
||||
integrity sha512-SBV4zihM5Yg6COgP7tjRhozJbOHZSVippUjCF1Ouuy4JcabF5Maunx1mAOkMGZGMJ3Cwoz6EoX5dSyUrajU0Sw==
|
||||
dependencies:
|
||||
rc-util "^5.0.1"
|
||||
|
||||
"@ant-design/pro-skeleton@1.0.0-beta.10":
|
||||
version "1.0.0-beta.10"
|
||||
resolved "https://registry.npmjs.org/@ant-design/pro-skeleton/-/pro-skeleton-1.0.0-beta.10.tgz"
|
||||
@@ -265,6 +281,18 @@
|
||||
moment "^2.27.0"
|
||||
rc-util "^5.0.6"
|
||||
|
||||
"@ant-design/pro-utils@1.6.2":
|
||||
version "1.6.2"
|
||||
resolved "https://registry.yarnpkg.com/@ant-design/pro-utils/-/pro-utils-1.6.2.tgz#57d587eb5b74fd9d1ea3fd29af05cff08a596c91"
|
||||
integrity sha512-lVDJBIFSqmZ9RKOKGz4V7HlXkbxk1bB2xVDjYuBhNLuIS65S0IqmdaOcDjyttjBR6mbvA4Z4t1ccxzutzsOlWg==
|
||||
dependencies:
|
||||
"@ant-design/icons" "^4.3.0"
|
||||
"@ant-design/pro-provider" "1.2.7"
|
||||
classnames "^2.2.6"
|
||||
fast-deep-equal "^3.1.3"
|
||||
moment "^2.27.0"
|
||||
rc-util "^5.0.6"
|
||||
|
||||
"@ant-design/react-slick@~0.27.0":
|
||||
version "0.27.14"
|
||||
resolved "https://registry.npmjs.org/@ant-design/react-slick/-/react-slick-0.27.14.tgz"
|
||||
|
||||
@@ -25,4 +25,8 @@ type Args struct {
|
||||
// ApplyOnceOnly indicates whether workloads and traits should be
|
||||
// affected if no spec change is made in the ApplicationConfiguration.
|
||||
ApplyOnceOnly bool
|
||||
|
||||
// CustomRevisionHookURL is a webhook which will let oam-runtime to call with AC+Component info
|
||||
// The webhook server will return a customized component revision for oam-runtime
|
||||
CustomRevisionHookURL string
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ func (r *Reconciler) Reconcile(req ctrl.Request) (result ctrl.Result, gerr error
|
||||
|
||||
applog.Info("parse template")
|
||||
// parse template
|
||||
appParser := parser.NewParser(template.GetHanler(fclient.NewDefinitionClient(r.Client)))
|
||||
appParser := parser.NewParser(template.GetHandler(fclient.NewDefinitionClient(r.Client)))
|
||||
|
||||
appfile, err := appParser.Parse(app.Name, app)
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
|
||||
"github.com/oam-dev/kubevela/apis/types"
|
||||
"github.com/oam-dev/kubevela/pkg/controller/core.oam.dev/v1alpha2/application/template"
|
||||
"github.com/oam-dev/kubevela/pkg/dsl/definition"
|
||||
"github.com/oam-dev/kubevela/pkg/dsl/process"
|
||||
@@ -183,13 +184,10 @@ func (pser *Parser) parseWorkload(comp v1alpha2.ApplicationComponent) (*Workload
|
||||
workload.traits = []*Trait{}
|
||||
workload.name = comp.Name
|
||||
workload.typ = comp.WorkloadType
|
||||
templ, kind, err := pser.templ(workload.typ)
|
||||
templ, err := pser.templ(workload.typ, types.TypeWorkload)
|
||||
if err != nil && !kerrors.IsNotFound(err) {
|
||||
return nil, errors.WithMessagef(err, "fetch type of %s", comp.Name)
|
||||
}
|
||||
if kind != template.WorkloadKind {
|
||||
return nil, errors.Errorf("%s type (%s) invalid", comp.Name, workload.typ)
|
||||
}
|
||||
workload.template = templ
|
||||
settings, err := DecodeJSONMarshaler(comp.Settings)
|
||||
if err != nil {
|
||||
@@ -214,14 +212,14 @@ func (pser *Parser) parseWorkload(comp v1alpha2.ApplicationComponent) (*Workload
|
||||
}
|
||||
|
||||
func (pser *Parser) parseTrait(name string, properties map[string]interface{}) (*Trait, error) {
|
||||
|
||||
templ, kind, err := pser.templ(name)
|
||||
if err != nil && !kerrors.IsNotFound(err) {
|
||||
templ, err := pser.templ(name, types.TypeTrait)
|
||||
if kerrors.IsNotFound(err) {
|
||||
return nil, errors.Errorf("trait definition of %s not found", name)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if kind != template.TraitKind {
|
||||
return nil, errors.Errorf("kind of %s is not trait", name)
|
||||
}
|
||||
|
||||
trait := new(Trait)
|
||||
trait.template = templ
|
||||
trait.name = name
|
||||
|
||||
@@ -116,7 +116,7 @@ spec:
|
||||
o := v1alpha2.Application{}
|
||||
yaml.Unmarshal([]byte(appfileYaml), &o)
|
||||
|
||||
appfile, err := NewParser(template.GetHanler(mock)).Parse("test", &o)
|
||||
appfile, err := NewParser(template.GetHandler(mock)).Parse("test", &o)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
|
||||
@@ -4,6 +4,8 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/types"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
kerrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
|
||||
@@ -14,8 +16,8 @@ type manager struct {
|
||||
defclient.DefinitionClient
|
||||
}
|
||||
|
||||
// GetHanler get template handler
|
||||
func GetHanler(cli defclient.DefinitionClient) Handler {
|
||||
// GetHandler get template handler
|
||||
func GetHandler(cli defclient.DefinitionClient) Handler {
|
||||
m := &manager{
|
||||
DefinitionClient: cli,
|
||||
}
|
||||
@@ -23,51 +25,46 @@ func GetHanler(cli defclient.DefinitionClient) Handler {
|
||||
}
|
||||
|
||||
// Handler is template handler type
|
||||
type Handler func(key string) (string, Kind, error)
|
||||
type Handler func(key string, kind types.CapType) (string, error)
|
||||
|
||||
// Kind is template kind
|
||||
type Kind uint16
|
||||
|
||||
const (
|
||||
// WorkloadKind ...
|
||||
WorkloadKind Kind = (1 << iota)
|
||||
// TraitKind ...
|
||||
TraitKind
|
||||
// Unkownkind ...
|
||||
Unkownkind
|
||||
)
|
||||
type Kind = types.CapType
|
||||
|
||||
// LoadTemplate Get template according to key
|
||||
func (m *manager) LoadTemplate(key string) (string, Kind, error) {
|
||||
wd, err := m.GetWorkloadDefinition(key)
|
||||
if err != nil && !kerrors.IsNotFound(err) {
|
||||
return "", Unkownkind, errors.WithMessagef(err, "LoadTemplate [%s] ", key)
|
||||
}
|
||||
if wd != nil {
|
||||
func (m *manager) LoadTemplate(key string, kd types.CapType) (string, error) {
|
||||
switch kd {
|
||||
case types.TypeWorkload:
|
||||
wd, err := m.GetWorkloadDefinition(key)
|
||||
if err != nil {
|
||||
return "", errors.WithMessagef(err, "LoadTemplate [%s] ", key)
|
||||
}
|
||||
jsonRaw, err := getTemplate(wd.Spec.Extension.Raw)
|
||||
if err != nil {
|
||||
return "", Unkownkind, errors.WithMessagef(err, "LoadTemplate [%s] ", key)
|
||||
return "", errors.WithMessagef(err, "LoadTemplate [%s] ", key)
|
||||
}
|
||||
if jsonRaw != "" {
|
||||
return jsonRaw, WorkloadKind, nil
|
||||
if jsonRaw == "" {
|
||||
return "", errors.New("no template found in definition")
|
||||
}
|
||||
return jsonRaw, nil
|
||||
|
||||
case types.TypeTrait:
|
||||
td, err := m.GetTraitDefition(key)
|
||||
if err != nil && !kerrors.IsNotFound(err) {
|
||||
return "", errors.WithMessagef(err, "LoadTemplate [%s] ", key)
|
||||
}
|
||||
}
|
||||
td, err := m.GetTraitDefition(key)
|
||||
if err != nil && !kerrors.IsNotFound(err) {
|
||||
return "", Unkownkind, errors.WithMessagef(err, "LoadTemplate [%s] ", key)
|
||||
}
|
||||
if td != nil {
|
||||
jsonRaw, err := getTemplate(td.Spec.Extension.Raw)
|
||||
if err != nil {
|
||||
return "", Unkownkind, errors.WithMessagef(err, "LoadTemplate [%s] ", key)
|
||||
return "", errors.WithMessagef(err, "LoadTemplate [%s] ", key)
|
||||
}
|
||||
|
||||
if jsonRaw != "" {
|
||||
return jsonRaw, TraitKind, nil
|
||||
if jsonRaw == "" {
|
||||
return "", errors.New("no template found in definition")
|
||||
}
|
||||
|
||||
return jsonRaw, nil
|
||||
case types.TypeScope:
|
||||
// TODO: add scope template support
|
||||
}
|
||||
return "", Unkownkind, nil
|
||||
|
||||
return "", fmt.Errorf("kind(%s) of %s not supported", kd, key)
|
||||
}
|
||||
|
||||
func getTemplate(raw []byte) (string, error) {
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
"cuelang.org/go/cue"
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/types"
|
||||
"github.com/oam-dev/kubevela/pkg/controller/core.oam.dev/v1alpha2/application/defclient"
|
||||
)
|
||||
|
||||
@@ -78,16 +79,11 @@ spec:
|
||||
m := manager{
|
||||
mock,
|
||||
}
|
||||
temp, kind, err := m.LoadTemplate("worker")
|
||||
temp, err := m.LoadTemplate("worker", types.TypeWorkload)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
if kind != WorkloadKind {
|
||||
t.Errorf("template.LoadTemplate kind invalid")
|
||||
return
|
||||
}
|
||||
|
||||
var r cue.Runtime
|
||||
inst, err := r.Compile("-", temp)
|
||||
if err != nil {
|
||||
|
||||
+4
-3
@@ -94,9 +94,10 @@ func Setup(mgr ctrl.Manager, args core.Args, l logging.Logger) error {
|
||||
Named(name).
|
||||
For(&v1alpha2.ApplicationConfiguration{}).
|
||||
Watches(&source.Kind{Type: &v1alpha2.Component{}}, &ComponentHandler{
|
||||
Client: mgr.GetClient(),
|
||||
Logger: l,
|
||||
RevisionLimit: args.RevisionLimit,
|
||||
Client: mgr.GetClient(),
|
||||
Logger: l,
|
||||
RevisionLimit: args.RevisionLimit,
|
||||
CustomRevisionHookURL: args.CustomRevisionHookURL,
|
||||
}).
|
||||
Complete(NewReconciler(mgr, dm,
|
||||
WithLogger(l.WithValues("controller", name)),
|
||||
|
||||
+232
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
Copyright 2020 The KubeVela Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package applicationconfiguration
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/crossplane/crossplane-runtime/apis/core/v1alpha1"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
|
||||
"github.com/oam-dev/kubevela/pkg/oam/util"
|
||||
)
|
||||
|
||||
var _ = Describe("Test Deploying ApplicationConfiguration without TraitDefinition", func() {
|
||||
const (
|
||||
namespace = "definition-test"
|
||||
appName = "hello"
|
||||
componentName = "backend"
|
||||
)
|
||||
var (
|
||||
ctx = context.Background()
|
||||
workload v1alpha2.ContainerizedWorkload
|
||||
component v1alpha2.Component
|
||||
workloadKey = client.ObjectKey{
|
||||
Name: componentName,
|
||||
Namespace: namespace,
|
||||
}
|
||||
appConfig v1alpha2.ApplicationConfiguration
|
||||
appConfigKey = client.ObjectKey{
|
||||
Name: appName,
|
||||
Namespace: namespace,
|
||||
}
|
||||
req = reconcile.Request{NamespacedName: appConfigKey}
|
||||
ns = corev1.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: namespace,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
BeforeEach(func() {})
|
||||
|
||||
It("ManualScalerTrait should work successfully even though its TraitDefinition doesn't exist", func() {
|
||||
var componentStr = `
|
||||
apiVersion: core.oam.dev/v1alpha2
|
||||
kind: Component
|
||||
metadata:
|
||||
name: backend
|
||||
namespace: definition-test
|
||||
spec:
|
||||
workload:
|
||||
apiVersion: core.oam.dev/v1alpha2
|
||||
kind: ContainerizedWorkload
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.9.4
|
||||
ports:
|
||||
- containerPort: 80
|
||||
name: nginx
|
||||
env:
|
||||
- name: TEST_ENV
|
||||
value: test
|
||||
command: [ "/bin/bash", "-c", "--" ]
|
||||
args: [ "while true; do sleep 30; done;" ]
|
||||
`
|
||||
|
||||
var appConfigStr = `
|
||||
apiVersion: core.oam.dev/v1alpha2
|
||||
kind: ApplicationConfiguration
|
||||
metadata:
|
||||
name: hello
|
||||
namespace: definition-test
|
||||
spec:
|
||||
components:
|
||||
- componentName: backend
|
||||
traits:
|
||||
- trait:
|
||||
apiVersion: core.oam.dev/v1alpha2
|
||||
kind: ManualScalerTrait
|
||||
spec:
|
||||
replicaCount: 2
|
||||
workloadRef:
|
||||
apiVersion: core.oam.dev/v1alpha2
|
||||
kind: ContainerizedWorkload
|
||||
name: backend
|
||||
`
|
||||
|
||||
By("Create namespace")
|
||||
Eventually(
|
||||
func() error {
|
||||
return k8sClient.Create(ctx, &ns)
|
||||
},
|
||||
time.Second*3, time.Millisecond*300).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{}))
|
||||
|
||||
By("Create Component")
|
||||
Expect(yaml.Unmarshal([]byte(componentStr), &component)).Should(BeNil())
|
||||
Expect(k8sClient.Create(ctx, &component)).Should(Succeed())
|
||||
cmpV1 := &v1alpha2.Component{}
|
||||
Expect(k8sClient.Get(ctx, client.ObjectKey{Namespace: namespace, Name: componentName}, cmpV1)).Should(Succeed())
|
||||
|
||||
By("Create ApplicationConfiguration")
|
||||
Expect(yaml.Unmarshal([]byte(appConfigStr), &appConfig)).Should(BeNil())
|
||||
Expect(k8sClient.Create(ctx, &appConfig)).Should(Succeed())
|
||||
|
||||
By("Reconcile")
|
||||
reconcileRetry(reconciler, req)
|
||||
time.Sleep(5)
|
||||
|
||||
By("Check workload created successfully")
|
||||
Eventually(func() error {
|
||||
return k8sClient.Get(ctx, workloadKey, &workload)
|
||||
}, time.Second, 300*time.Millisecond).Should(BeNil())
|
||||
|
||||
By("Check reconcile again and no error will happen")
|
||||
reconcileRetry(reconciler, req)
|
||||
|
||||
By("Check appConfig condition should not have error")
|
||||
Eventually(func() string {
|
||||
By("Reconcile again and should not have error")
|
||||
reconcileRetry(reconciler, req)
|
||||
err := k8sClient.Get(ctx, appConfigKey, &appConfig)
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
if len(appConfig.Status.Conditions) != 1 {
|
||||
return "condition len should be 1 but now is " + strconv.Itoa(len(appConfig.Status.Conditions))
|
||||
}
|
||||
return string(appConfig.Status.Conditions[0].Reason)
|
||||
}, 3*time.Second, 300*time.Millisecond).Should(BeEquivalentTo("ReconcileSuccess"))
|
||||
|
||||
By("Check trait CR is created")
|
||||
var scaleName string
|
||||
scaleList := v1alpha2.ManualScalerTraitList{}
|
||||
labels := &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"app.oam.dev/component": componentName,
|
||||
},
|
||||
}
|
||||
selector, _ := metav1.LabelSelectorAsSelector(labels)
|
||||
err := k8sClient.List(ctx, &scaleList, &client.ListOptions{
|
||||
Namespace: namespace,
|
||||
LabelSelector: selector,
|
||||
})
|
||||
Expect(err).Should(BeNil())
|
||||
traitNamePrefix := fmt.Sprintf("%s-dummy-", componentName)
|
||||
var traitExistFlag bool
|
||||
for _, t := range scaleList.Items {
|
||||
if strings.HasPrefix(t.Name, traitNamePrefix) {
|
||||
traitExistFlag = true
|
||||
scaleName = t.Name
|
||||
}
|
||||
}
|
||||
Expect(traitExistFlag).Should(BeTrue())
|
||||
|
||||
By("Update ApplicationConfiguration by changing spec of trait")
|
||||
newTrait := &v1alpha2.ManualScalerTrait{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: "core.oam.dev/v1alpha2",
|
||||
Kind: "ManualScalerTrait",
|
||||
},
|
||||
Spec: v1alpha2.ManualScalerTraitSpec{
|
||||
ReplicaCount: 3,
|
||||
WorkloadReference: v1alpha1.TypedReference{
|
||||
APIVersion: "core.oam.dev/v1alpha2",
|
||||
Kind: "ContainerizedWorkload",
|
||||
Name: componentName,
|
||||
},
|
||||
},
|
||||
}
|
||||
appConfig.Spec.Components[0].Traits = []v1alpha2.ComponentTrait{{Trait: runtime.RawExtension{Object: newTrait.DeepCopyObject()}}}
|
||||
Expect(k8sClient.Update(ctx, &appConfig)).Should(BeNil())
|
||||
|
||||
By("Reconcile")
|
||||
reconcileRetry(reconciler, req)
|
||||
|
||||
By("Check again that appConfig condition should not have error")
|
||||
Eventually(func() string {
|
||||
By("Reconcile again and should not have error")
|
||||
reconcileRetry(reconciler, req)
|
||||
err := k8sClient.Get(ctx, appConfigKey, &appConfig)
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
if len(appConfig.Status.Conditions) != 1 {
|
||||
return "condition len should be 1 but now is " + strconv.Itoa(len(appConfig.Status.Conditions))
|
||||
}
|
||||
return string(appConfig.Status.Conditions[0].Reason)
|
||||
}, 3*time.Second, 300*time.Millisecond).Should(BeEquivalentTo("ReconcileSuccess"))
|
||||
|
||||
By("Check new trait CR is applied")
|
||||
scale := v1alpha2.ManualScalerTrait{}
|
||||
scaleKey := client.ObjectKey{Name: scaleName, Namespace: namespace}
|
||||
err = k8sClient.Get(ctx, scaleKey, &scale)
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(scale.Spec.ReplicaCount).Should(Equal(int32(3)))
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
// delete the namespace with all its resources
|
||||
Expect(k8sClient.Delete(ctx, &ns, client.PropagationPolicy(metav1.DeletePropagationForeground))).
|
||||
Should(SatisfyAny(BeNil(), &util.NotFoundMatcher{}))
|
||||
})
|
||||
})
|
||||
@@ -77,7 +77,7 @@ func (fn WorkloadApplyFns) Finalize(ctx context.Context, ac *v1alpha2.Applicatio
|
||||
type workloads struct {
|
||||
// use patching-apply for creating/updating Workload
|
||||
patchingClient resource.Applicator
|
||||
// use updateing-apply for creating/updating Trait
|
||||
// use updating-apply for creating/updating Trait
|
||||
updatingClient resource.Applicator
|
||||
rawClient client.Client
|
||||
dm discoverymapper.DiscoveryMapper
|
||||
@@ -91,7 +91,7 @@ func (a *workloads) Apply(ctx context.Context, status []v1alpha2.WorkloadStatus,
|
||||
if !wl.HasDep {
|
||||
err := a.patchingClient.Apply(ctx, wl.Workload, ao...)
|
||||
if err != nil {
|
||||
// TODO(roywang) use errors.As() insteand of type assertion on error
|
||||
// TODO(roywang) use errors.As() instead of type assertion on error
|
||||
if _, ok := err.(*GenerationUnchanged); !ok {
|
||||
// GenerationUnchanged only aborts applying current workload
|
||||
// but not blocks the whole reconciliation through returning an error
|
||||
@@ -105,7 +105,7 @@ func (a *workloads) Apply(ctx context.Context, status []v1alpha2.WorkloadStatus,
|
||||
}
|
||||
t := trait.Object
|
||||
if err := a.updatingClient.Apply(ctx, &trait.Object, ao...); err != nil {
|
||||
// TODO(roywang) use errors.As() insteand of type assertion on error
|
||||
// TODO(roywang) use errors.As() instead of type assertion on error
|
||||
if _, ok := err.(*GenerationUnchanged); !ok {
|
||||
// GenerationUnchanged only aborts applying current trait
|
||||
// but not blocks the whole reconciliation through returning an error
|
||||
|
||||
@@ -29,10 +29,10 @@ const ControllerRevisionComponentLabel = "controller.oam.dev/component"
|
||||
|
||||
// ComponentHandler will watch component change and generate Revision automatically.
|
||||
type ComponentHandler struct {
|
||||
Client client.Client
|
||||
Logger logging.Logger
|
||||
RevisionLimit int
|
||||
CustomWebHookURL string
|
||||
Client client.Client
|
||||
Logger logging.Logger
|
||||
RevisionLimit int
|
||||
CustomRevisionHookURL string
|
||||
}
|
||||
|
||||
// Create implements EventHandler
|
||||
@@ -148,7 +148,7 @@ func (c *ComponentHandler) createControllerRevision(mt metav1.Object, obj runtim
|
||||
reqs := c.getRelatedAppConfig(mt)
|
||||
// Hook to custom revision service if exist
|
||||
if err := c.customComponentRevisionHook(reqs, comp); err != nil {
|
||||
c.Logger.Info(fmt.Sprintf("fail to hook from custom revision service(%s) %v", c.CustomWebHookURL, err), "componentName", mt.GetName())
|
||||
c.Logger.Info(fmt.Sprintf("fail to hook from custom revision service(%s) %v", c.CustomRevisionHookURL, err), "componentName", mt.GetName())
|
||||
return nil, false
|
||||
}
|
||||
|
||||
|
||||
+6
-2
@@ -20,6 +20,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
||||
@@ -36,7 +37,7 @@ type RevisionHookRequest struct {
|
||||
}
|
||||
|
||||
func (c *ComponentHandler) customComponentRevisionHook(relatedApps []reconcile.Request, comp *v1alpha2.Component) error {
|
||||
if c.CustomWebHookURL == "" {
|
||||
if c.CustomRevisionHookURL == "" {
|
||||
return nil
|
||||
}
|
||||
req := RevisionHookRequest{
|
||||
@@ -47,7 +48,7 @@ func (c *ComponentHandler) customComponentRevisionHook(relatedApps []reconcile.R
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
httpRequest, err := http.NewRequestWithContext(context.Background(), http.MethodPost, c.CustomWebHookURL, bytes.NewBuffer(data))
|
||||
httpRequest, err := http.NewRequestWithContext(context.Background(), http.MethodPost, c.CustomRevisionHookURL, bytes.NewBuffer(data))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -62,5 +63,8 @@ func (c *ComponentHandler) customComponentRevisionHook(relatedApps []reconcile.R
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if resp.StatusCode != 200 {
|
||||
return fmt.Errorf("httpcode(%d) err: %s", resp.StatusCode, string(respData))
|
||||
}
|
||||
return json.Unmarshal(respData, comp)
|
||||
}
|
||||
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
Copyright 2020 The KubeVela Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package applicationconfiguration
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
|
||||
)
|
||||
|
||||
func TestCustomRevisionHook(t *testing.T) {
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
var req RevisionHookRequest
|
||||
data, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
w.WriteHeader(400)
|
||||
return
|
||||
}
|
||||
err = json.Unmarshal(data, &req)
|
||||
if err != nil {
|
||||
w.WriteHeader(401)
|
||||
return
|
||||
}
|
||||
if len(req.RelatedApps) != 1 {
|
||||
w.WriteHeader(400)
|
||||
w.Write([]byte("we should have only one relatedApps"))
|
||||
return
|
||||
}
|
||||
if req.Comp.Annotations == nil {
|
||||
req.Comp.Annotations = make(map[string]string)
|
||||
}
|
||||
req.Comp.Annotations["app-name"] = req.RelatedApps[0].Name
|
||||
req.Comp.Annotations["app-namespace"] = req.RelatedApps[0].Namespace
|
||||
|
||||
newdata, err := json.Marshal(req.Comp)
|
||||
if err != nil {
|
||||
w.WriteHeader(500)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(200)
|
||||
w.Write(newdata)
|
||||
}))
|
||||
defer srv.Close()
|
||||
compHandler := ComponentHandler{
|
||||
CustomRevisionHookURL: srv.URL,
|
||||
}
|
||||
comp := &v1alpha2.Component{}
|
||||
err := compHandler.customComponentRevisionHook([]reconcile.Request{{NamespacedName: types.NamespacedName{Name: "app1", Namespace: "default1"}}}, comp)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "app1", comp.Annotations["app-name"])
|
||||
assert.Equal(t, "default1", comp.Annotations["app-namespace"])
|
||||
|
||||
err = compHandler.customComponentRevisionHook([]reconcile.Request{{NamespacedName: types.NamespacedName{Name: "app1", Namespace: "default1"}}, {NamespacedName: types.NamespacedName{Name: "app2", Namespace: "default2"}}}, comp)
|
||||
assert.Equal(t, err.Error(), "httpcode(400) err: we should have only one relatedApps")
|
||||
}
|
||||
@@ -226,11 +226,10 @@ func (r *components) renderTrait(ctx context.Context, ct v1alpha2.ComponentTrait
|
||||
}
|
||||
traitDef, err := util.FetchTraitDefinition(ctx, r.client, r.dm, t)
|
||||
if err != nil {
|
||||
if apierrors.IsNotFound(err) {
|
||||
t.SetNamespace(ac.GetNamespace())
|
||||
return t, util.GetDummyTraitDefinition(t), nil
|
||||
if !apierrors.IsNotFound(err) {
|
||||
return nil, nil, errors.Wrapf(err, errFmtGetTraitDefinition, t.GetAPIVersion(), t.GetKind(), t.GetName())
|
||||
}
|
||||
return nil, nil, errors.Wrapf(err, errFmtGetTraitDefinition, t.GetAPIVersion(), t.GetKind(), t.GetName())
|
||||
traitDef = util.GetDummyTraitDefinition(t)
|
||||
}
|
||||
traitName := getTraitName(ac, componentName, &ct, t, traitDef)
|
||||
|
||||
|
||||
+1
-1
@@ -54,7 +54,7 @@ const (
|
||||
)
|
||||
|
||||
// Setup adds a controller that reconciles HealthScope.
|
||||
func Setup(mgr ctrl.Manager, args controller.Args, l logging.Logger) error {
|
||||
func Setup(mgr ctrl.Manager, _ controller.Args, l logging.Logger) error {
|
||||
name := "oam/" + strings.ToLower(v1alpha2.HealthScopeGroupKind)
|
||||
|
||||
return ctrl.NewControllerManagedBy(mgr).
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ const (
|
||||
)
|
||||
|
||||
// Setup adds a controller that reconciles ContainerizedWorkload.
|
||||
func Setup(mgr ctrl.Manager, args controller.Args, log logging.Logger) error {
|
||||
func Setup(mgr ctrl.Manager, _ controller.Args, _ logging.Logger) error {
|
||||
dm, err := discoverymapper.New(mgr.GetConfig())
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
+1
-1
@@ -49,7 +49,7 @@ const (
|
||||
)
|
||||
|
||||
// Setup adds a controller that reconciles ContainerizedWorkload.
|
||||
func Setup(mgr ctrl.Manager, args controller.Args, log logging.Logger) error {
|
||||
func Setup(mgr ctrl.Manager, _ controller.Args, _ logging.Logger) error {
|
||||
reconciler := Reconciler{
|
||||
Client: mgr.GetClient(),
|
||||
log: ctrl.Log.WithName("ContainerizedWorkload"),
|
||||
|
||||
@@ -30,23 +30,21 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/standard.oam.dev/v1alpha1"
|
||||
"github.com/oam-dev/kubevela/pkg/controller/common"
|
||||
"github.com/oam-dev/kubevela/pkg/oam/discoverymapper"
|
||||
"github.com/oam-dev/kubevela/pkg/oam/util"
|
||||
oamutil "github.com/oam-dev/kubevela/pkg/oam/util"
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/standard.oam.dev/v1alpha1"
|
||||
"github.com/oam-dev/kubevela/pkg/controller/common"
|
||||
)
|
||||
|
||||
// nolint:golint
|
||||
const (
|
||||
SpecWarningTargetWorkloadNotSet = "Spec.targetWorkload is not set"
|
||||
SpecWarningStartAtTimeFormat = "startAt is not in the right format, which should be like `12:01`"
|
||||
SpecWarningStartAtTimeRequired = "spec.triggers.condition.startAt: Required value"
|
||||
SpecWarningDurationTimeRequired = "spec.triggers.condition.duration: Required value"
|
||||
SpecWarningReplicasRequired = "spec.triggers.condition.replicas: Required value"
|
||||
SpecWarningDurationTimeNotInRightFormat = "spec.triggers.condition.duration: not in the right format"
|
||||
SpecWarningSumOfStartAndDurationMoreThan24Hour = "the sum of the start hour and the duration hour has to be less than 24 hours."
|
||||
SpecWarningTargetWorkloadNotSet = "Spec.targetWorkload is not set"
|
||||
SpecWarningStartAtTimeFormat = "startAt is not in the right format, which should be like `12:01`"
|
||||
SpecWarningStartAtTimeRequired = "spec.triggers.condition.startAt: Required value"
|
||||
SpecWarningDurationTimeRequired = "spec.triggers.condition.duration: Required value"
|
||||
SpecWarningReplicasRequired = "spec.triggers.condition.replicas: Required value"
|
||||
SpecWarningDurationTimeNotInRightFormat = "spec.triggers.condition.duration: not in the right format"
|
||||
)
|
||||
|
||||
// ReconcileWaitResult is the time to wait between reconciliation.
|
||||
|
||||
@@ -59,7 +59,7 @@ func (h *ValidatingHandler) Handle(ctx context.Context, req admission.Request) a
|
||||
}
|
||||
|
||||
// try render to validate
|
||||
appParser := parser.NewParser(template.GetHanler(fclient.NewDefinitionClient(h.Client)))
|
||||
appParser := parser.NewParser(template.GetHandler(fclient.NewDefinitionClient(h.Client)))
|
||||
if _, err := appParser.Parse(app.Name, app); err != nil {
|
||||
return admission.Denied(err.Error())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user