Compare commits

..

6 Commits

Author SHA1 Message Date
Sun Jianbo
17ac119f9b Merge pull request #297 from wonderflow/readme
add more readme
2020-09-18 23:11:21 +08:00
天元
829b813b1a add move readme 2020-09-18 23:02:10 +08:00
Sun Jianbo
bce8bfd40f Merge pull request #296 from wonderflow/con
temporarily add containerized to chart
2020-09-18 22:12:01 +08:00
天元
66855265c8 temporarily add containerized to chart 2020-09-18 21:59:48 +08:00
Sun Jianbo
63f52ea556 Merge pull request #294 from hanxie-crypto/feature04
Components static page,bugfix,capability delete
2020-09-18 21:56:38 +08:00
hanxie
fa37bf0284 Components static page,bugfix,capability delete 2020-09-18 17:47:39 +08:00
525 changed files with 30103 additions and 50224 deletions

View File

@@ -8,9 +8,15 @@ on:
jobs:
build:
name: e2e-tests
runs-on: aliyun
name: Build
runs-on: ubuntu-latest
steps:
- name: Set up Go 1.13
uses: actions/setup-go@v1
with:
go-version: 1.13
id: go
- name: Check out code into the Go module directory
uses: actions/checkout@v2
@@ -18,21 +24,18 @@ jobs:
run: |
go get -v -t -d ./...
- name: Install ginkgo
run: |
sudo apt-get update
sudo apt-get install -y golang-ginkgo-dev
- name: Setup Kind Cluster
uses: engineerd/setup-kind@v0.4.0
with:
version: "v0.7.0"
skipClusterCreation: true
- name: Setup Kind Cluster
run: |
kind delete cluster
kind create cluster
kubectl version
kubectl cluster-info
- name: Load Image to kind cluster
run: make kind-load
- name: install Kubebuilder
uses: RyanSiu1995/kubebuilder-action@v1
- name: Run Make
run: make
@@ -42,7 +45,7 @@ jobs:
- name: Run e2e tests
run: |
make e2e-cleanup
make e2e-setup
make e2e-test
make e2e-api-test
make e2e-cleanup

View File

@@ -8,13 +8,13 @@ on:
jobs:
build:
name: unit-tests
runs-on: ubuntu-20.04
name: Build
runs-on: ubuntu-latest
steps:
- name: Set up Go 1.14
- name: Set up Go 1.13
uses: actions/setup-go@v1
with:
go-version: 1.14
go-version: 1.13
id: go
- name: Check out code into the Go module directory
@@ -22,6 +22,7 @@ jobs:
- name: Install ginkgo
run: |
sudo apt-get update
sudo apt-get install -y golang-ginkgo-dev
- name: Setup Kind Cluster
@@ -34,11 +35,3 @@ jobs:
- name: Run Make test
run: make test
- name: Upload coverage report
uses: codecov/codecov-action@v1
with:
token: ${{ secrets.CODECOV_TOKEN }}
file: ./coverage.txt
flags: unittests
name: codecov-umbrella

View File

@@ -13,10 +13,10 @@ jobs:
VELA_VERSION: ${{ github.ref }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- name: Set up Go 1.14
- name: Set up Go 1.13
uses: actions/setup-go@v1
with:
go-version: 1.14
go-version: 1.13
id: go
- name: Check out code into the Go module directory
uses: actions/checkout@v2

7
.gitignore vendored
View File

@@ -13,7 +13,6 @@ e2e/vela
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
coverage.txt
# Kubernetes Generated files - skip generated files, except for vendored files
@@ -37,14 +36,10 @@ config/crd/bases
tmp/
cmd/vela/fake/source.go
cmd/vela/fake/chart_source.go
charts/vela-core/crds/_.yaml
.test_vela
.vela/
# Dashboard
node_modules/
dashboard/node_modules/
.eslintcache
dashboard/dist/
dashboard/package-lock.json

View File

@@ -1,3 +0,0 @@
# Code of Conduct
KubeVela follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md).

View File

@@ -1,9 +1,5 @@
# CONTRIBUTING
## 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.
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).
@@ -15,7 +11,6 @@ contributing to `kubevela` or build a PoC (Proof of Concept).
4. golangci-lint 1.31.0+, it will install automatically if you run `make`, you can [install it manually](https://golangci-lint.run/usage/install/#local-installation) if the installation is too slow.
## Build
* Clone this project
```shell script
@@ -36,34 +31,15 @@ after build, make will create `vela` binary to `bin/`, Set this path to PATH.
export PATH=$PATH:/your/path/to/project/kubevela/bin
```
Then you can use `vela` command directly.
* Build Vela Core
* Install Vela Core
```shell script
make manager
vela install
```
* Run Vela Core
Firstly make sure your cluster has CRDs.
```shell script
make core-install
```
Run locally:
```shell script
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/).
## Use
* Create environment
* Create ENV
```shell script
vela env init myenv --namespace myenv --email my@email.com --domain kubevela.io
@@ -74,60 +50,43 @@ vela env init myenv --namespace myenv --email my@email.com --domain kubevela.io
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
$ vela comp run mycomp -t webservice --image crccheck/hello-world --port 8000
Creating AppConfig appcomp
SUCCEED
```
* 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
$ vela route mycomp
Adding route for app abc
Succeeded!
```
* 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
$ vela comp status abc
Showing status of Component abc deployed in Environment t2
Component Status:
Name: abc Containerized(type) UNKNOWN APIVersion standard.oam.dev/v1alpha1 Kind Containerized workload is unknown for HealthScope
Traits
└─Trait/route
Last Deployment:
Created at: 2020-09-18 18:47:09 +0800 CST
Updated at: 2020-09-18T18:47:16+08:00
```
* 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 app ls
abc
$ vela delete abc
Deleting Application "abc"
delete apps succeed abc from default
$ vela app delete abc
Deleting Application "abc"
delete apps succeed abc from t2
```
## Tests
@@ -139,15 +98,6 @@ make test
```
### E2E test
**Before e2e test start, make sure you have vela-core running.**
```shell script
make core-run
```
Start to test.
```
make e2e-test
```

View File

@@ -4,7 +4,7 @@ VELA_VERSION ?= 0.1.0
GIT_COMMIT ?= git-$(shell git rev-parse --short HEAD)
VELA_VERSION_VAR := github.com/oam-dev/kubevela/version.VelaVersion
VELA_GITVERSION_VAR := github.com/oam-dev/kubevela/version.GitRevision
LDFLAGS ?= "-X $(VELA_VERSION_VAR)=$(VELA_VERSION) -X $(VELA_GITVERSION_VAR)=$(GIT_COMMIT)"
LDFLAGS ?= "-X $(VELA_VERSION_VAR)=$(VELA_VERSION) -X $(VELA_GITVERSION_VAR)=$(GIT_COMMIT) -X main.chartTGZSource=$$(cat -) -s -w"
GOX = go run github.com/mitchellh/gox
TARGETS := darwin/amd64 linux/amd64 windows/amd64
@@ -20,17 +20,12 @@ endif
all: build
# Run tests
test: vet lint
go test -race -coverprofile=coverage.txt -covermode=atomic ./pkg/... ./cmd/...
test: fmt vet lint
go test ./pkg/... -coverprofile cover.out
# Build manager binary
build: fmt vet lint
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
vela-cli:
go build -o bin/vela -ldflags ${LDFLAGS} cmd/vela/main.go
go run hack/chart/generate.go | go build -o bin/vela -ldflags ${LDFLAGS} cmd/vela/main.go
npm-build:
cd dashboard && npm run build && cd ./..
@@ -38,16 +33,11 @@ npm-build:
npm-install:
cd dashboard && npm install && cd ./..
doc-gen:
rm -r docs/en/cli/*
go run hack/docgen/gen.go
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/
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/
compress:
( \
@@ -66,7 +56,6 @@ run: fmt vet
# Run go fmt against code
fmt:
go fmt ./...
./hack/cue-fmt.sh
# Run go vet against code
vet:
@@ -84,15 +73,13 @@ docker-push:
docker push ${IMG}
e2e-setup:
bin/vela install --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-test:
# Run e2e test
ginkgo -v -skipPackage capability,setup,apiserver -r e2e
ginkgo -v -skipPackage setup,apiserver -r e2e
e2e-api-test:
# Run e2e test
@@ -100,12 +87,7 @@ e2e-api-test:
e2e-cleanup:
# Clean up
rm -rf ~/.vela
# load docker image to the kind cluster
kind-load:
docker build -t vela-core-test:$(GIT_COMMIT) .
kind load docker-image vela-core-test:$(GIT_COMMIT) || { echo >&2 "kind not installed or error loading image: $(IMAGE)"; exit 1; }
# Image URL to use all building/pushing image targets
IMG ?= vela-core:latest
@@ -124,23 +106,22 @@ manager: generate fmt vet lint manifests
core-run: generate fmt vet manifests
go run ./cmd/core/main.go
# Install CRDs and Definitions of Vela Core into a cluster, this is for develop convenient.
# Install CRDs into a cluster
core-install: manifests
kubectl apply -f charts/vela-core/crds/
kubectl apply -f charts/vela-core/templates/defwithtemplate/
kubectl apply -f charts/vela-core/templates/definitions/
bin/vela system update
kustomize build config/crd | kubectl apply -f -
# Uninstall CRDs and Definitions of Vela Core from a cluster, this is for develop convenient.
# Uninstall CRDs from a cluster
core-uninstall: manifests
kubectl delete -f charts/vela-core/templates/definitions/
kubectl delete -f charts/vela-core/templates/defwithtemplate/
kubectl delete -f charts/vela-core/crds/
kustomize build config/crd | kubectl delete -f -
# Deploy controller in the configured Kubernetes cluster in ~/.kube/config
core-deploy: manifests
cd config/manager && kustomize edit set image controller=${IMG}
kustomize build config/default | kubectl apply -f -
# Generate manifests e.g. CRD, RBAC etc.
manifests: controller-gen
$(CONTROLLER_GEN) $(CRD_OPTIONS) rbac:roleName=manager-role webhook paths="./..." output:crd:artifacts:config=charts/vela-core/crds
./hack/vela-templates/gen_definitions.sh
# Generate code
generate: controller-gen

9
OWNERS
View File

@@ -1,9 +0,0 @@
approvers:
- kubevela-controller
- kubevela-devex
reviewers:
- kubevela-controller
- kubevela-dashboard
- oam-k8s-runtime
- oam-spec

View File

@@ -1,49 +0,0 @@
aliases:
kubevela-devex:
- hongchaodeng
- wonderflow
kubevela-dashboard:
- zzxwill
- hanxie-crypto
- hongchaodeng
kubevela-controller:
- resouer
- wonderflow
- hongchaodeng
- zzxwill
- ryanzhang-oss
oam-k8s-runtime: # inherit from https://github.com/crossplane/oam-kubernetes-runtime/blob/master/OWNERS.md
- hongchaodeng
- wonderflow
- ryanzhang-oss
- captainroy-hy
- negz
- hasheddan
oam-spec: # inherit from https://github.com/oam-dev/spec/blob/master/OWNERS.md
- hongchaodeng
- resouer
- vturecek
community-collaborators:
- Fei-Guo
- szihai
bootstrap-contributors: # thank you for bootstrapping KubeVela at the very early stage!
- xiaoyuaiheshui
- Ghostbaby
- wenxinnnnn
- silenceper
- erdun
- sunny0826
- mosesyou
- artursouza
- wonderflow
- hongchaodeng
- ryanzhang-oss
- woshilanren11
- hanxie-crypto
- zzxwill

327
README.md
View File

@@ -1,28 +1,321 @@
![alt](resources/KubeVela-03.png)
*Make shipping applications more enjoyable.*
# KubeVela
For developers, KubeVela is an easy-to-use tool that enables them to describe and ship their applications to Kubernetes with minimal effort.
The Open Application Platform based on Kubernetes and OAM.
For platform builders, KubeVela serves as a framework that empowers them to create developer facing yet highly extensible platforms at ease.
:rotating_light: **Warning: The project is still under heavy development, its UI/UX is also for demo purpose, please don't look inside unless you know what you are doing** Please contact @wonderflow if you are interested in its full story or becoming one of the boostrap contributors/maintainers. :rotating_light:
- Slack: [Discuss](https://cloud-native.slack.com/archives/C01BLQ3HTJA)
- Gitter: [Community](https://gitter.im/oam-dev/community)
## Install
> NOTE: KubeVela is still in early stage and iterating quickly. It's currently under preview release.
### Prerequisites
- Kubernetes cluster running Kubernetes v1.15.0 or greater
- kubectl current context is configured for the target cluster install
- ```kubectl config current-context```
## Quick Start
### Get the Vela CLI
Quick start guides are available on [this section](docs/quick-start.md).
Download the `vela` binary from the [Releases page](https://github.com/oam-dev/kubevela/releases). Unpack the `vela` binary and add it to `$PATH` to get started.
## Documentation
```shell
sudo mv ./vela /usr/local/bin/vela
```
To see full documentation, visit [kubevela.io](https://kubevela.io/).
### Install Vela Core
## Contributing
Check out [CONTRIBUTING](./CONTRIBUTING.md) to see how to develop with KubeVela.
```shell script
$ vela install
```
This command will install vela core controller into your K8s cluster, along with built-in workloads and traits.
## Demos
After `vela install` you will have workloads and traits locally, and available to use by vela cli.
```shell script
$ vela workloads
NAME DEFINITION
backend containerizeds.standard.oam.dev
containerized containerizedworkloads.core.oam.dev
task jobs
webservice containerizeds.standard.oam.dev
```
```shell script
$ vela traits
NAME DEFINITION APPLIES TO
route routes.standard.oam.dev webservice
backend
scale manualscalertraits.core.oam.dev webservice
backend
```
### Create ENV
Before working with your application, you should create an env for it.
```shell script
$ vela env init myenv --namespace myenv --email my@email.com --domain kubevela.io
ENV myenv CREATED, Namespace: myenv, Email: my@email.com.
```
It will create a namespace called myenv
```shell script
$ kubectl get ns
NAME STATUS AGE
myenv Active 40s
```
A namespace level issuer for certificate generation with email.
```shell script
$ kubectl get issuers.cert-manager.io -n myenv
NAME READY AGE
oam-env-myenv True 40s
```
A env metadata in your local:
```shell script
$ cat ~/.vela/envs/myenv/config.json
{"name":"myenv","namespace":"myenv","email":"my@email.com","domain":"kubevela.io","issuer":"oam-env-myenv"}
```
### Create Component
Then let's create application, we will use our env created by default.
```shell script
$ vela comp run mycomp -t webservice --image crccheck/hello-world --port 8000 --app myapp
Creating AppConfig appcomp
SUCCEED
```
It will create component named `mycomp`.
```shell script
$ kubectl get components -n myenv
NAME WORKLOAD-KIND AGE
mycomp Containerized 10s
```
And an AppConfig named myapp.
```shell script
$ kubectl get appconfig -n myenv
NAME AGE
myapp 24s
```
Vela Core will work for AppConfig and create K8s deployment and service.
```shell script
$ kubectl get deployment -n myenv
NAME READY UP-TO-DATE AVAILABLE AGE
mycomp 1/1 1 1 38s
```
```shell script
$ kubectl get svc -n myenv
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
mycomp ClusterIP 172.21.4.228 <none> 8080/TCP 49s
```
### Multiple Component
Creating a new component in the same application is easy, just use the `--app` flag.
```shell script
$ vela comp run db -t backend --image crccheck/hello-world --app myapp
Creating App myapp
SUCCEED
```
```shell script
$ vela comp ls
NAME APP WORKLOAD TRAITS STATUS CREATED-TIME
db myapp backend Deployed 2020-09-18 22:42:04 +0800 CST
mycomp myapp webservice Deployed 2020-09-18 22:42:04 +0800 CST
```
Now we can see the application deployed, let's add route trait for visiting.
### Add Trait
```shell script
$ vela route mycomp --app myapp
Adding route for app mycomp
Succeeded!
```
It will create route trait for this component.
```shell script
$ kubeclt get routes.standard.oam.dev -n myenv
NAME AGE
mycomp-trait-5b576c4fc 18s
```
Controller of route trait which is part of vela core will create an ingress for it.
```shell script
$ kubectl get ingress -n myenv
NAME HOSTS ADDRESS PORTS AGE
mycomp-trait-5b576c4fc mycomp.kubevela.io 123.57.10.233 80, 443 73s
```
Please configure your domain pointing to the public address.
Then you will be able to visit it by `https://mycomp.kubevela.io`, `mTLS` is automatically enabled.
### Check Status
App level:
```shell script
$ vela app show myapp
About:
Name: myapp
Created at: 2020-09-18 22:42:04.191171 +0800 CST
Updated at: 2020-09-18 22:51:11.128997 +0800 CST
Environment:
Namespace: myenv
Components:
Name Type Traits
db backend
mycomp webservice route
```
Component Level:
```shell script
$ vela comp show mycomp
About:
Name: mycomp
WorkloadType: webservice
Application: myapp
Environment:
Namespace: myenv
Arguments:
image: crccheck/hello-world
name: mycomp
port: 8000
Traits:
route:
domain: mycomp.kubevela.io
issuer: oam-env-myenv
name: route
```
```
$ vela comp status mycomp
Showing status of Component mycomp deployed in Environment myenv
Component Status:
Name: mycomp Containerized(type) UNKNOWN APIVersion standard.oam.dev/v1alpha1 Kind Containerized workload is unknown for HealthScope
Traits
└─Trait/route
Last Deployment:
Created at: 2020-09-18 22:42:04 +0800 CST
Updated at: 2020-09-18T22:51:11+08:00
```
### Delete App or Component
```shell script
$ vela app ls
myapp
```
```shell script
$ vela comp ls
NAME APP WORKLOAD TRAITS STATUS CREATED-TIME
db myapp backend Deployed 2020-09-18 22:42:04 +0800 CST
mycomp myapp webservice route Deployed 2020-09-18 22:42:04 +0800 CST
```
```shell script
$ vela comp delete db
Deleting Component 'db' from Application 'db'
```
```shell script
$ vela comp ls
NAME APP WORKLOAD TRAITS STATUS CREATED-TIME
mycomp myapp webservice route Deployed 2020-09-18 22:42:04 +0800 CST
```
```shell script
$ vela app delete myapp
Deleting Application "myapp"
delete apps succeed myapp from myenv
```
## Dashboard
We also prepared a dashboard for you, but it's still in heavily development.
```shell script
$ vela dashboard
```
#### Auto-Completion
##### bash
```shell script
To load completions in your current shell session:
$ source <(vela completion bash)
To load completions for every new session, execute once:
Linux:
$ vela completion bash > /etc/bash_completion.d/vela
MacOS:
$ vela completion bash > /usr/local/etc/bash_completion.d/vela
```
##### zsh
```shell script
To load completions in your current shell session:
$ source <(vela completion zsh)
To load completions for every new session, execute once:
$ vela completion zsh > "${fpath[1]}/_vela"
```
### Clean your environment
```shell script
$ helm uninstall vela-core -n oam-system
release "vela-core" uninstalled
```
```shell script
$ kubectl delete crd workloaddefinitions.core.oam.dev traitdefinitions.core.oam.dev
customresourcedefinition.apiextensions.k8s.io "workloaddefinitions.core.oam.dev" deleted
customresourcedefinition.apiextensions.k8s.io "traitdefinitions.core.oam.dev" deleted
```
```shell script
$ rm -r ~/.vela
```
## CONTRIBUTING
Check out [CONTRIBUTING.md](./CONTRIBUTING.md) to see how to develop with KubeVela.
## Code of Conduct
This project has adopted the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md). See [CODE OF CONDUCT](CODE_OF_CONDUCT.md) for details.

View File

@@ -1,59 +0,0 @@
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1alpha2
import (
runtimev1alpha1 "github.com/crossplane/crossplane-runtime/apis/core/v1alpha1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
// ApplicationDeploymentSpec defines the desired state of ApplicationDeployment
type ApplicationDeploymentSpec struct {
//TODO add spec here
}
// ApplicationDeploymentStatus defines the observed state of ApplicationDeployment
type ApplicationDeploymentStatus struct {
//TODO add status field here
runtimev1alpha1.ConditionedStatus `json:",inline"`
}
// +kubebuilder:object:root=true
// +kubebuilder:resource:categories={oam}
// +kubebuilder:subresource:status
// ApplicationDeployment is the Schema for the ApplicationDeployment API
type ApplicationDeployment struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec ApplicationDeploymentSpec `json:"spec,omitempty"`
Status ApplicationDeploymentStatus `json:"status,omitempty"`
}
// +kubebuilder:object:root=true
// ApplicationDeploymentList contains a list of ApplicationDeployment
type ApplicationDeploymentList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []ApplicationDeployment `json:"items"`
}
func init() {
SchemeBuilder.Register(&ApplicationDeployment{}, &ApplicationDeploymentList{})
}

View File

@@ -1,35 +0,0 @@
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package v1alpha2 contains API Schema definitions for the core.oam.dev v1alpha2 API group
// +kubebuilder:object:generate=true
// +groupName=core.oam.dev
package v1alpha2
import (
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/controller-runtime/pkg/scheme"
)
var (
// SchemeGroupVersion is group version used to register these objects
SchemeGroupVersion = schema.GroupVersion{Group: "core.oam.dev", Version: "v1alpha2"}
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion}
// AddToScheme adds the types in this group-version to the given scheme.
AddToScheme = SchemeBuilder.AddToScheme
)

View File

@@ -1,115 +0,0 @@
// +build !ignore_autogenerated
/*
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.
*/
// Code generated by controller-gen. DO NOT EDIT.
package v1alpha2
import (
runtime "k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ApplicationDeployment) DeepCopyInto(out *ApplicationDeployment) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
out.Spec = in.Spec
in.Status.DeepCopyInto(&out.Status)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationDeployment.
func (in *ApplicationDeployment) DeepCopy() *ApplicationDeployment {
if in == nil {
return nil
}
out := new(ApplicationDeployment)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ApplicationDeployment) 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 *ApplicationDeploymentList) DeepCopyInto(out *ApplicationDeploymentList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]ApplicationDeployment, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationDeploymentList.
func (in *ApplicationDeploymentList) DeepCopy() *ApplicationDeploymentList {
if in == nil {
return nil
}
out := new(ApplicationDeploymentList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ApplicationDeploymentList) 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 *ApplicationDeploymentSpec) DeepCopyInto(out *ApplicationDeploymentSpec) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationDeploymentSpec.
func (in *ApplicationDeploymentSpec) DeepCopy() *ApplicationDeploymentSpec {
if in == nil {
return nil
}
out := new(ApplicationDeploymentSpec)
in.DeepCopyInto(out)
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
}

View File

@@ -21,7 +21,6 @@ import (
"fmt"
"cuelang.org/go/cue"
"github.com/google/go-cmp/cmp"
"github.com/spf13/pflag"
"k8s.io/apimachinery/pkg/runtime"
)
@@ -47,7 +46,6 @@ type Capability struct {
CrdName string `json:"crdName,omitempty"`
Center string `json:"center,omitempty"`
Status string `json:"status,omitempty"`
Description string `json:"description,omitempty"`
//trait only
AppliesTo []string `json:"appliesTo,omitempty"`
@@ -85,7 +83,6 @@ type Parameter struct {
Default interface{} `json:"default,omitempty"`
Usage string `json:"usage,omitempty"`
Type cue.Kind `json:"type,omitempty"`
Alias string `json:"alias,omitempty"`
}
// ConvertTemplateJSON2Object convert spec.extension to object
@@ -106,10 +103,6 @@ func ConvertTemplateJSON2Object(in *runtime.RawExtension) (Capability, error) {
}
func SetFlagBy(flags *pflag.FlagSet, v Parameter) {
name := v.Name
if v.Alias != "" {
name = v.Alias
}
switch v.Type {
case cue.IntKind:
var vv int64
@@ -123,11 +116,11 @@ func SetFlagBy(flags *pflag.FlagSet, v Parameter) {
case float64:
vv = int64(val)
}
flags.Int64P(name, v.Short, vv, v.Usage)
flags.Int64P(v.Name, v.Short, vv, v.Usage)
case cue.StringKind:
flags.StringP(name, v.Short, v.Default.(string), v.Usage)
flags.StringP(v.Name, v.Short, v.Default.(string), v.Usage)
case cue.BoolKind:
flags.BoolP(name, v.Short, v.Default.(bool), v.Usage)
flags.BoolP(v.Name, v.Short, v.Default.(bool), v.Usage)
case cue.NumberKind, cue.FloatKind:
var vv float64
switch val := v.Default.(type) {
@@ -140,71 +133,6 @@ func SetFlagBy(flags *pflag.FlagSet, v Parameter) {
case float64:
vv = val
}
flags.Float64P(name, v.Short, vv, v.Usage)
flags.Float64P(v.Name, v.Short, vv, v.Usage)
}
}
var CapabilityCmpOptions = []cmp.Option{
cmp.Comparer(func(a, b Parameter) bool {
if a.Name != b.Name || a.Short != b.Short || a.Required != b.Required ||
a.Usage != b.Usage || a.Type != b.Type {
return false
}
switch a.Type {
case cue.IntKind:
var va, vb int64
switch vala := a.Default.(type) {
case int64:
va = vala
case json.Number:
va, _ = vala.Int64()
case int:
va = int64(vala)
case float64:
va = int64(vala)
}
switch valb := b.Default.(type) {
case int64:
vb = valb
case json.Number:
vb, _ = valb.Int64()
case int:
vb = int64(valb)
case float64:
vb = int64(valb)
}
return va == vb
case cue.StringKind:
return a.Default.(string) == b.Default.(string)
case cue.BoolKind:
return a.Default.(bool) == b.Default.(bool)
case cue.NumberKind, cue.FloatKind:
var va, vb float64
switch vala := a.Default.(type) {
case int64:
va = float64(vala)
case json.Number:
va, _ = vala.Float64()
case int:
va = float64(vala)
case float64:
va = float64(vala)
}
switch valb := b.Default.(type) {
case int64:
vb = float64(valb)
case json.Number:
vb, _ = valb.Float64()
case int:
vb = float64(valb)
case float64:
vb = float64(valb)
}
return va == vb
}
return true
})}
func EqualCapability(a, b Capability) bool {
return cmp.Equal(a, b, CapabilityCmpOptions...)
}

View File

@@ -1,8 +1,8 @@
package types
const (
DefaultOAMNS = "vela-system"
DefaultOAMReleaseName = "kubevela"
DefaultOAMNS = "oam-system"
DefaultOAMReleaseName = "vela-core"
DefaultOAMRuntimeChartName = "vela-core"
DefaultOAMVersion = ">0.0.0-0"
@@ -11,11 +11,13 @@ const (
)
const (
AnnAPIVersion = "definition.oam.dev/apiVersion"
AnnKind = "definition.oam.dev/kind"
AnnDescription = "definition.oam.dev/description"
AnnAPIVersion = "definition.oam.dev/apiVersion"
AnnKind = "definition.oam.dev/kind"
LabelPodSpecable = "workload.oam.dev/podspecable"
// Indicate which workloadDefinition generate from
AnnWorkloadDef = "workload.oam.dev/name"
// Indicate which traitDefinition generate from
AnnTraitDef = "trait.oam.dev/name"
)
const (

View File

@@ -1,118 +0,0 @@
/*
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 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"
)
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
// Protocol defines network protocols supported for things like container ports.
type Protocol string
// TriggerType defines the type of trigger
type TriggerType string
// +kubebuilder:object:root=true
// +kubebuilder:resource:categories={oam}
// Autoscaler is the Schema for the autoscalers API
type Autoscaler struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec AutoscalerSpec `json:"spec"`
Status AutoscalerStatus `json:"status,omitempty"`
}
func (as *Autoscaler) SetConditions(c ...v1alpha1.Condition) {
as.Status.SetConditions(c...)
}
func (as *Autoscaler) GetCondition(conditionType v1alpha1.ConditionType) v1alpha1.Condition {
return as.Status.GetCondition(conditionType)
}
func (as *Autoscaler) GetWorkloadReference() v1alpha1.TypedReference {
return as.Spec.WorkloadReference
}
func (as *Autoscaler) SetWorkloadReference(reference v1alpha1.TypedReference) {
as.Spec.WorkloadReference = reference
}
// Trigger defines the trigger of Autoscaler
type Trigger struct {
// Name is the trigger name, if not set, it will be automatically generated and make it globally unique
Name string `json:"name,omitempty"`
// Type allows value in [cpu/memory/storage/ephemeral-storage、cron、pps、qps/rps、custom]
Type TriggerType `json:"type"`
// Condition set the condition when to trigger scaling
Condition map[string]string `json:"condition"`
}
// AutoscalerSpec defines the desired state of Autoscaler
type AutoscalerSpec struct {
// MinReplicas is the minimal replicas
// +optional
MinReplicas *int32 `json:"minReplicas,omitempty"`
// MinReplicas is the maximal replicas
// +optional
MaxReplicas *int32 `json:"maxReplicas,omitempty"`
// Triggers lists all triggers
Triggers []Trigger `json:"triggers"`
// TargetWorkload specify the workload which is going to be scaled,
// it could be WorkloadReference or the child resource of it
TargetWorkload TargetWorkload `json:"targetWorkload,omitempty"`
// WorkloadReference marks the owner of the workload
WorkloadReference runtimev1alpha1.TypedReference `json:"workloadRef,omitempty"`
}
// TargetWorkload holds the a reference to the scale target Object
type TargetWorkload struct {
Name string `json:"name"`
// +optional
APIVersion string `json:"apiVersion,omitempty"`
// +optional
Kind string `json:"kind,omitempty"`
}
// AutoscalerStatus defines the observed state of Autoscaler
type AutoscalerStatus struct {
runtimev1alpha1.ConditionedStatus `json:",inline"`
}
// +kubebuilder:object:root=true
// AutoscalerList contains a list of Autoscaler
type AutoscalerList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []Autoscaler `json:"items"`
}
func init() {
SchemeBuilder.Register(&Autoscaler{}, &AutoscalerList{})
}

View File

@@ -23,20 +23,20 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// PodSpecWorkloadSpec defines the desired state of PodSpecWorkload
type PodSpecWorkloadSpec struct {
// ContainerizedSpec defines the desired state of Containerized
type ContainerizedSpec struct {
// Replicas is the desired number of replicas of the given podSpec.
// These are replicas in the sense that they are instantiations of the same podSpec.
// If unspecified, defaults to 1.
Replicas *int32 `json:"replicas,omitempty"`
Replicas *int32 `json:"replicas"`
// PodSpec describes the pods that will be created,
// we omit the meta part as it will be exactly the same as the PodSpecWorkload
// we omit the meta part as it will be exactly the same as the containerized
PodSpec v1.PodSpec `json:"podSpec"`
}
// PodSpecWorkloadStatus defines the observed state of PodSpecWorkload
type PodSpecWorkloadStatus struct {
// ContainerizedStatus defines the observed state of Containerized
type ContainerizedStatus struct {
cpv1alpha1.ConditionedStatus `json:",inline"`
// Resources managed by this workload.
@@ -45,38 +45,36 @@ type PodSpecWorkloadStatus struct {
// +kubebuilder:object:root=true
// PodSpecWorkload is the Schema for the PodSpec API
// +genclient:method=GetScale,verb=get,subresource=scale,result=k8s.io/api/autoscaling/v1.Scale
// +genclient:method=UpdateScale,verb=update,subresource=scale,input=k8s.io/api/autoscaling/v1.Scale,result=k8s.io/api/autoscaling/v1.Scale
// Containerized is the Schema for the containerizeds API
// +kubebuilder:resource:categories={oam}
// +kubebuilder:subresource:status
type PodSpecWorkload struct {
type Containerized struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec PodSpecWorkloadSpec `json:"spec,omitempty"`
Status PodSpecWorkloadStatus `json:"status,omitempty"`
Spec ContainerizedSpec `json:"spec,omitempty"`
Status ContainerizedStatus `json:"status,omitempty"`
}
// +kubebuilder:object:root=true
// PodSpecWorkloadList contains a list of PodSpecWorkload
type PodSpecWorkloadList struct {
// ContainerizedList contains a list of Containerized
type ContainerizedList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []PodSpecWorkload `json:"items"`
Items []Containerized `json:"items"`
}
func init() {
SchemeBuilder.Register(&PodSpecWorkload{}, &PodSpecWorkloadList{})
SchemeBuilder.Register(&Containerized{}, &ContainerizedList{})
}
var _ oam.Workload = &PodSpecWorkload{}
var _ oam.Workload = &Containerized{}
func (in *PodSpecWorkload) SetConditions(c ...cpv1alpha1.Condition) {
func (in *Containerized) SetConditions(c ...cpv1alpha1.Condition) {
in.Status.SetConditions(c...)
}
func (in *PodSpecWorkload) GetCondition(c cpv1alpha1.ConditionType) cpv1alpha1.Condition {
func (in *Containerized) GetCondition(c cpv1alpha1.ConditionType) cpv1alpha1.Condition {
return in.Status.GetCondition(c)
}

View File

@@ -39,11 +39,12 @@ type ScapeServiceEndPoint struct {
// The default and only supported format is "prometheus" for now
Format string `json:"format,omitempty"`
// Number or name of the port to access on the pods targeted by the service.
// The default is discovered automatically from podTemplate, metricTrait will create a service for the workload
// When this field has value implies that we need to create a service for the workload
// Mutually exclusive with port.
TargetPort intstr.IntOrString `json:"port,omitempty"`
// Route service traffic to pods with label keys and values matching this
// The default is discovered automatically from podTemplate.
// If no podTemplate, use the labels specified here, or use the labels of the workload
// The default is the labels in the workload
// Mutually exclusive with port.
TargetSelector map[string]string `json:"selector,omitempty"`
// HTTP path to scrape for metrics.
// default is /metrics
@@ -62,13 +63,8 @@ type ScapeServiceEndPoint struct {
type MetricsTraitStatus struct {
runtimev1alpha1.ConditionedStatus `json:",inline"`
// ServiceMonitorName managed by this trait
ServiceMonitorName string `json:"serviceMonitorName,omitempty"`
// Port is the real port monitoring
Port intstr.IntOrString `json:"port,omitempty"`
// SelectorLabels is the real labels selected
SelectorLabels map[string]string `json:"selectorLabels,omitempty"`
// ServiceMonitorNames managed by this trait
ServiceMonitorNames []string `json:"serviceMonitorName,omitempty"`
}
// +kubebuilder:object:root=true

View File

@@ -19,6 +19,7 @@ package v1alpha1
import (
runtimev1alpha1 "github.com/crossplane/crossplane-runtime/apis/core/v1alpha1"
"github.com/crossplane/oam-kubernetes-runtime/pkg/oam"
"k8s.io/api/networking/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
)
@@ -33,24 +34,15 @@ type RouteSpec struct {
// Host is the host of the route
Host string `json:"host"`
// Path is location Path, default for "/"
Path string `json:"path,omitempty"`
// TLS indicate route trait will create SSL secret using cert-manager with specified issuer
// If this is nil, route trait will use a selfsigned issuer
TLS *TLS `json:"tls,omitempty"`
// Rules contain multiple rules of route
Rules []Rule `json:"rules,omitempty"`
// Provider indicate which ingress controller implementation the route trait will use, by default it's nginx-ingress
Provider string `json:"provider,omitempty"`
}
// Rule defines to route rule
type Rule struct {
// Name will become the suffix of underlying ingress created by this rule, if not, will use index as suffix.
Name string `json:"name,omitempty"`
// Path is location Path, default for "/"
Path string `json:"path,omitempty"`
// DefaultBackend uses serviceName
DefaultBackend *v1beta1.IngressBackend `json:"defaultBackend,omitempty"`
// RewriteTarget will rewrite request from Path to RewriteTarget path.
RewriteTarget string `json:"rewriteTarget,omitempty"`
@@ -58,9 +50,6 @@ type Rule struct {
// CustomHeaders pass a custom list of headers to the backend service.
CustomHeaders map[string]string `json:"customHeaders,omitempty"`
// DefaultBackend will become the ingress default backend if the backend is not available
DefaultBackend *runtimev1alpha1.TypedReference `json:"defaultBackend,omitempty"`
// Backend indicate how to connect backend service
// If it's nil, will auto discovery
Backend *Backend `json:"backend,omitempty"`
@@ -69,8 +58,7 @@ type Rule struct {
type TLS struct {
IssuerName string `json:"issuerName,omitempty"`
// Type indicate the issuer is ClusterIssuer or Issuer(namespace issuer), by default, it's Issuer
// +kubebuilder:default:=Issuer
// Type indicate the issuer is ClusterIssuer or NamespaceIssuer
Type IssuerType `json:"type,omitempty"`
}
@@ -81,31 +69,27 @@ const (
NamespaceIssuer IssuerType = "Issuer"
)
// Route will automatically discover podSpec and label for BackendService.
// If BackendService is already set, discovery won't work.
// If BackendService is not set, the discovery mechanism will work.
// Route will automatically discover podTemplate for Port and SelectLabels if they are not set.
// If Port and SelectLabels are already set, discovery won't work.
// If Port is not set, the first port discovered will be set.
// If SelectLabels are not set, all selectorLabels discovered will be set.
type Backend struct {
// Protocol means backend-protocol, HTTP, HTTPS, GRPC, GRPCS, AJP and FCGI, By default uses HTTP
Protocol string `json:"protocol,omitempty"`
// ReadTimeout used for setting read timeout duration for backend service, the unit is second.
ReadTimeout int `json:"readTimeout,omitempty"`
// SendTimeout used for setting send timeout duration for backend service, the unit is second.
SendTimeout int `json:"sendTimeout,omitempty"`
// BackendService specifies the backend K8s service and port, it's optional
BackendService *BackendServiceRef `json:"backendService,omitempty"`
}
// BackendServiceRef specifies the backend K8s service and port, if specified, the two fields are all required
type BackendServiceRef struct {
// Port allow you direct specify backend service port.
Port intstr.IntOrString `json:"port"`
// ServiceName allow you direct specify K8s service for backend service.
ServiceName string `json:"serviceName"`
// Port points to backend service port.
Port intstr.IntOrString `json:"port,omitempty"`
// SelectLabels for backend service.
SelectLabels map[string]string `json:"selectLabels,omitempty"`
}
// RouteStatus defines the observed state of Route
type RouteStatus struct {
Ingresses []runtimev1alpha1.TypedReference `json:"ingresses,omitempty"`
Service *runtimev1alpha1.TypedReference `json:"service,omitempty"`
Status string `json:"status,omitempty"`
Ingress *runtimev1alpha1.TypedReference `json:"ingress,omitempty"`
Service *runtimev1alpha1.TypedReference `json:"service,omitempty"`
runtimev1alpha1.ConditionedStatus `json:",inline"`
}

View File

@@ -22,125 +22,20 @@ package v1alpha1
import (
corev1alpha1 "github.com/crossplane/crossplane-runtime/apis/core/v1alpha1"
"k8s.io/api/networking/v1beta1"
runtime "k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Autoscaler) DeepCopyInto(out *Autoscaler) {
*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 Autoscaler.
func (in *Autoscaler) DeepCopy() *Autoscaler {
if in == nil {
return nil
}
out := new(Autoscaler)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *Autoscaler) 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 *AutoscalerList) DeepCopyInto(out *AutoscalerList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]Autoscaler, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AutoscalerList.
func (in *AutoscalerList) DeepCopy() *AutoscalerList {
if in == nil {
return nil
}
out := new(AutoscalerList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *AutoscalerList) 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 *AutoscalerSpec) DeepCopyInto(out *AutoscalerSpec) {
*out = *in
if in.MinReplicas != nil {
in, out := &in.MinReplicas, &out.MinReplicas
*out = new(int32)
**out = **in
}
if in.MaxReplicas != nil {
in, out := &in.MaxReplicas, &out.MaxReplicas
*out = new(int32)
**out = **in
}
if in.Triggers != nil {
in, out := &in.Triggers, &out.Triggers
*out = make([]Trigger, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
out.TargetWorkload = in.TargetWorkload
out.WorkloadReference = in.WorkloadReference
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AutoscalerSpec.
func (in *AutoscalerSpec) DeepCopy() *AutoscalerSpec {
if in == nil {
return nil
}
out := new(AutoscalerSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AutoscalerStatus) DeepCopyInto(out *AutoscalerStatus) {
*out = *in
in.ConditionedStatus.DeepCopyInto(&out.ConditionedStatus)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AutoscalerStatus.
func (in *AutoscalerStatus) DeepCopy() *AutoscalerStatus {
if in == nil {
return nil
}
out := new(AutoscalerStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Backend) DeepCopyInto(out *Backend) {
*out = *in
if in.BackendService != nil {
in, out := &in.BackendService, &out.BackendService
*out = new(BackendServiceRef)
**out = **in
out.Port = in.Port
if in.SelectLabels != nil {
in, out := &in.SelectLabels, &out.SelectLabels
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
}
@@ -155,17 +50,102 @@ func (in *Backend) DeepCopy() *Backend {
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *BackendServiceRef) DeepCopyInto(out *BackendServiceRef) {
func (in *Containerized) DeepCopyInto(out *Containerized) {
*out = *in
out.Port = in.Port
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 BackendServiceRef.
func (in *BackendServiceRef) DeepCopy() *BackendServiceRef {
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Containerized.
func (in *Containerized) DeepCopy() *Containerized {
if in == nil {
return nil
}
out := new(BackendServiceRef)
out := new(Containerized)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *Containerized) 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 *ContainerizedList) DeepCopyInto(out *ContainerizedList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]Containerized, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContainerizedList.
func (in *ContainerizedList) DeepCopy() *ContainerizedList {
if in == nil {
return nil
}
out := new(ContainerizedList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ContainerizedList) 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 *ContainerizedSpec) DeepCopyInto(out *ContainerizedSpec) {
*out = *in
if in.Replicas != nil {
in, out := &in.Replicas, &out.Replicas
*out = new(int32)
**out = **in
}
in.PodSpec.DeepCopyInto(&out.PodSpec)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContainerizedSpec.
func (in *ContainerizedSpec) DeepCopy() *ContainerizedSpec {
if in == nil {
return nil
}
out := new(ContainerizedSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ContainerizedStatus) DeepCopyInto(out *ContainerizedStatus) {
*out = *in
in.ConditionedStatus.DeepCopyInto(&out.ConditionedStatus)
if in.Resources != nil {
in, out := &in.Resources, &out.Resources
*out = make([]corev1alpha1.TypedReference, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContainerizedStatus.
func (in *ContainerizedStatus) DeepCopy() *ContainerizedStatus {
if in == nil {
return nil
}
out := new(ContainerizedStatus)
in.DeepCopyInto(out)
return out
}
@@ -250,13 +230,10 @@ func (in *MetricsTraitSpec) DeepCopy() *MetricsTraitSpec {
func (in *MetricsTraitStatus) DeepCopyInto(out *MetricsTraitStatus) {
*out = *in
in.ConditionedStatus.DeepCopyInto(&out.ConditionedStatus)
out.Port = in.Port
if in.SelectorLabels != nil {
in, out := &in.SelectorLabels, &out.SelectorLabels
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
if in.ServiceMonitorNames != nil {
in, out := &in.ServiceMonitorNames, &out.ServiceMonitorNames
*out = make([]string, len(*in))
copy(*out, *in)
}
}
@@ -270,107 +247,6 @@ func (in *MetricsTraitStatus) DeepCopy() *MetricsTraitStatus {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PodSpecWorkload) DeepCopyInto(out *PodSpecWorkload) {
*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 PodSpecWorkload.
func (in *PodSpecWorkload) DeepCopy() *PodSpecWorkload {
if in == nil {
return nil
}
out := new(PodSpecWorkload)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *PodSpecWorkload) 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 *PodSpecWorkloadList) DeepCopyInto(out *PodSpecWorkloadList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]PodSpecWorkload, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodSpecWorkloadList.
func (in *PodSpecWorkloadList) DeepCopy() *PodSpecWorkloadList {
if in == nil {
return nil
}
out := new(PodSpecWorkloadList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *PodSpecWorkloadList) 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 *PodSpecWorkloadSpec) DeepCopyInto(out *PodSpecWorkloadSpec) {
*out = *in
if in.Replicas != nil {
in, out := &in.Replicas, &out.Replicas
*out = new(int32)
**out = **in
}
in.PodSpec.DeepCopyInto(&out.PodSpec)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodSpecWorkloadSpec.
func (in *PodSpecWorkloadSpec) DeepCopy() *PodSpecWorkloadSpec {
if in == nil {
return nil
}
out := new(PodSpecWorkloadSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PodSpecWorkloadStatus) DeepCopyInto(out *PodSpecWorkloadStatus) {
*out = *in
in.ConditionedStatus.DeepCopyInto(&out.ConditionedStatus)
if in.Resources != nil {
in, out := &in.Resources, &out.Resources
*out = make([]corev1alpha1.TypedReference, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PodSpecWorkloadStatus.
func (in *PodSpecWorkloadStatus) DeepCopy() *PodSpecWorkloadStatus {
if in == nil {
return nil
}
out := new(PodSpecWorkloadStatus)
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
@@ -439,13 +315,23 @@ func (in *RouteSpec) DeepCopyInto(out *RouteSpec) {
*out = new(TLS)
**out = **in
}
if in.Rules != nil {
in, out := &in.Rules, &out.Rules
*out = make([]Rule, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
if in.DefaultBackend != nil {
in, out := &in.DefaultBackend, &out.DefaultBackend
*out = new(v1beta1.IngressBackend)
(*in).DeepCopyInto(*out)
}
if in.CustomHeaders != nil {
in, out := &in.CustomHeaders, &out.CustomHeaders
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.Backend != nil {
in, out := &in.Backend, &out.Backend
*out = new(Backend)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteSpec.
@@ -461,10 +347,10 @@ func (in *RouteSpec) DeepCopy() *RouteSpec {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *RouteStatus) DeepCopyInto(out *RouteStatus) {
*out = *in
if in.Ingresses != nil {
in, out := &in.Ingresses, &out.Ingresses
*out = make([]corev1alpha1.TypedReference, len(*in))
copy(*out, *in)
if in.Ingress != nil {
in, out := &in.Ingress, &out.Ingress
*out = new(corev1alpha1.TypedReference)
**out = **in
}
if in.Service != nil {
in, out := &in.Service, &out.Service
@@ -484,38 +370,6 @@ func (in *RouteStatus) DeepCopy() *RouteStatus {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Rule) DeepCopyInto(out *Rule) {
*out = *in
if in.CustomHeaders != nil {
in, out := &in.CustomHeaders, &out.CustomHeaders
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.DefaultBackend != nil {
in, out := &in.DefaultBackend, &out.DefaultBackend
*out = new(corev1alpha1.TypedReference)
**out = **in
}
if in.Backend != nil {
in, out := &in.Backend, &out.Backend
*out = new(Backend)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Rule.
func (in *Rule) DeepCopy() *Rule {
if in == nil {
return nil
}
out := new(Rule)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ScapeServiceEndPoint) DeepCopyInto(out *ScapeServiceEndPoint) {
*out = *in
@@ -558,40 +412,3 @@ func (in *TLS) DeepCopy() *TLS {
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *TargetWorkload) DeepCopyInto(out *TargetWorkload) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TargetWorkload.
func (in *TargetWorkload) DeepCopy() *TargetWorkload {
if in == nil {
return nil
}
out := new(TargetWorkload)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Trigger) DeepCopyInto(out *Trigger) {
*out = *in
if in.Condition != nil {
in, out := &in.Condition, &out.Condition
*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 Trigger.
func (in *Trigger) DeepCopy() *Trigger {
if in == nil {
return nil
}
out := new(Trigger)
in.DeepCopyInto(out)
return out
}

View File

@@ -0,0 +1,44 @@
#!/bin/bash
# Copyright 2019 The Knative 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.
#!/usr/bin/env bash
# Download and unpack cert-manager
CERT_MANAGER_VERSION=1.0.0
ARCHIVE_DOWNLOAD_URL=https://github.com/jetstack/cert-manager/archive/v${CERT_MANAGER_VERSION}.tar.gz
YAML_URL=https://github.com/jetstack/cert-manager/releases/download/v${CERT_MANAGER_VERSION}/cert-manager.yaml
wget $ARCHIVE_DOWNLOAD_URL
tar xzf v${CERT_MANAGER_VERSION}.tar.gz
(
# subshell in downloaded directory
cd cert-manager-${CERT_MANAGER_VERSION} || exit
# Copy the CRD yaml file
cp deploy/manifests/00-crds.yaml ../cert-manager-crds.yaml
)
# Download the cert-manager yaml file
wget $YAML_URL
# Clean up.
rm -rf cert-manager-${CERT_MANAGER_VERSION}
rm v${CERT_MANAGER_VERSION}.tar.gz
# Add enable-certificate-owner-ref option to cert-manager's controller.
# The option is to cleans up secret(certificate) by adding ownerref.
patch -l cert-manager.yaml owner-ref.patch

View File

@@ -0,0 +1,4 @@
#!/bin/bash
# Download and unpack operator Lifecycle Manager (coreos)
curl -sL https://github.com/operator-framework/operator-lifecycle-manager/releases/download/0.15.1/install.sh | bash -s 0.15.1

View File

@@ -0,0 +1,24 @@
apiVersion: v1
kind: Namespace
metadata:
name: my-grafana-operator
---
apiVersion: operators.coreos.com/v1
kind: OperatorGroup
metadata:
name: operatorgroup
namespace: my-grafana-operator
spec:
targetNamespaces:
- my-grafana-operator
---
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
name: my-grafana-operator
namespace: my-grafana-operator
spec:
channel: alpha
name: grafana-operator
source: operatorhubio-catalog
sourceNamespace: olm

View File

@@ -0,0 +1,6 @@
apiVersion: v1
kind: Namespace
metadata:
labels:
mornitoring: oam
name: monitoring

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,265 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.2.4
creationTimestamp: null
name: podmonitors.monitoring.coreos.com
spec:
group: monitoring.coreos.com
names:
kind: PodMonitor
listKind: PodMonitorList
plural: podmonitors
singular: podmonitor
scope: Namespaced
versions:
- name: v1
schema:
openAPIV3Schema:
description: PodMonitor defines monitoring for a set of pods.
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: Specification of desired Pod selection for target discovery
by Prometheus.
properties:
jobLabel:
description: The label to use to retrieve the job name from.
type: string
namespaceSelector:
description: Selector to select which namespaces the Endpoints objects
are discovered from.
properties:
any:
description: Boolean describing whether all namespaces are selected
in contrast to a list restricting them.
type: boolean
matchNames:
description: List of namespace names.
items:
type: string
type: array
type: object
podMetricsEndpoints:
description: A list of endpoints allowed as part of this PodMonitor.
items:
description: PodMetricsEndpoint defines a scrapeable endpoint of
a Kubernetes Pod serving Prometheus metrics.
properties:
honorLabels:
description: HonorLabels chooses the metric's labels on collisions
with target labels.
type: boolean
honorTimestamps:
description: HonorTimestamps controls whether Prometheus respects
the timestamps present in scraped data.
type: boolean
interval:
description: Interval at which metrics should be scraped
type: string
metricRelabelings:
description: MetricRelabelConfigs to apply to samples before
ingestion.
items:
description: 'RelabelConfig allows dynamic rewriting of the
label set, being applied to samples before ingestion. It
defines `<metric_relabel_configs>`-section of Prometheus
configuration. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs'
properties:
action:
description: Action to perform based on regex matching.
Default is 'replace'
type: string
modulus:
description: Modulus to take of the hash of the source
label values.
format: int64
type: integer
regex:
description: Regular expression against which the extracted
value is matched. Default is '(.*)'
type: string
replacement:
description: Replacement value against which a regex replace
is performed if the regular expression matches. Regex
capture groups are available. Default is '$1'
type: string
separator:
description: Separator placed between concatenated source
label values. default is ';'.
type: string
sourceLabels:
description: The source labels select values from existing
labels. Their content is concatenated using the configured
separator and matched against the configured regular
expression for the replace, keep, and drop actions.
items:
type: string
type: array
targetLabel:
description: Label to which the resulting value is written
in a replace action. It is mandatory for replace actions.
Regex capture groups are available.
type: string
type: object
type: array
params:
additionalProperties:
items:
type: string
type: array
description: Optional HTTP URL parameters
type: object
path:
description: HTTP path to scrape for metrics.
type: string
port:
description: Name of the pod port this endpoint refers to. Mutually
exclusive with targetPort.
type: string
proxyUrl:
description: ProxyURL eg http://proxyserver:2195 Directs scrapes
to proxy through this endpoint.
type: string
relabelings:
description: 'RelabelConfigs to apply to samples before ingestion.
More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config'
items:
description: 'RelabelConfig allows dynamic rewriting of the
label set, being applied to samples before ingestion. It
defines `<metric_relabel_configs>`-section of Prometheus
configuration. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs'
properties:
action:
description: Action to perform based on regex matching.
Default is 'replace'
type: string
modulus:
description: Modulus to take of the hash of the source
label values.
format: int64
type: integer
regex:
description: Regular expression against which the extracted
value is matched. Default is '(.*)'
type: string
replacement:
description: Replacement value against which a regex replace
is performed if the regular expression matches. Regex
capture groups are available. Default is '$1'
type: string
separator:
description: Separator placed between concatenated source
label values. default is ';'.
type: string
sourceLabels:
description: The source labels select values from existing
labels. Their content is concatenated using the configured
separator and matched against the configured regular
expression for the replace, keep, and drop actions.
items:
type: string
type: array
targetLabel:
description: Label to which the resulting value is written
in a replace action. It is mandatory for replace actions.
Regex capture groups are available.
type: string
type: object
type: array
scheme:
description: HTTP scheme to use for scraping.
type: string
scrapeTimeout:
description: Timeout after which the scrape is ended
type: string
targetPort:
anyOf:
- type: integer
- type: string
description: 'Deprecated: Use ''port'' instead.'
x-kubernetes-int-or-string: true
type: object
type: array
podTargetLabels:
description: PodTargetLabels transfers labels on the Kubernetes Pod
onto the target.
items:
type: string
type: array
sampleLimit:
description: SampleLimit defines per-scrape limit on number of scraped
samples that will be accepted.
format: int64
type: integer
selector:
description: Selector to select Pod objects.
properties:
matchExpressions:
description: matchExpressions is a list of label selector requirements.
The requirements are ANDed.
items:
description: A label selector requirement is a selector that
contains values, a key, and an operator that relates the key
and values.
properties:
key:
description: key is the label key that the selector applies
to.
type: string
operator:
description: operator represents a key's relationship to
a set of values. Valid operators are In, NotIn, Exists
and DoesNotExist.
type: string
values:
description: values is an array of string values. If the
operator is In or NotIn, the values array must be non-empty.
If the operator is Exists or DoesNotExist, the values
array must be empty. This array is replaced during a strategic
merge patch.
items:
type: string
type: array
required:
- key
- operator
type: object
type: array
matchLabels:
additionalProperties:
type: string
description: matchLabels is a map of {key,value} pairs. A single
{key,value} in the matchLabels map is equivalent to an element
of matchExpressions, whose key field is "key", the operator
is "In", and the values array contains only "value". The requirements
are ANDed.
type: object
type: object
required:
- podMetricsEndpoints
- selector
type: object
required:
- spec
type: object
served: true
storage: true
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

View File

@@ -0,0 +1,212 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.2.4
creationTimestamp: null
name: probes.monitoring.coreos.com
spec:
group: monitoring.coreos.com
names:
kind: Probe
listKind: ProbeList
plural: probes
singular: probe
scope: Namespaced
versions:
- name: v1
schema:
openAPIV3Schema:
description: Probe defines monitoring for a set of static targets or ingresses.
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: Specification of desired Ingress selection for target discovery
by Prometheus.
properties:
interval:
description: Interval at which targets are probed using the configured
prober. If not specified Prometheus' global scrape interval is used.
type: string
jobName:
description: The job name assigned to scraped metrics by default.
type: string
module:
description: 'The module to use for probing specifying how to probe
the target. Example module configuring in the blackbox exporter:
https://github.com/prometheus/blackbox_exporter/blob/master/example.yml'
type: string
prober:
description: Specification for the prober to use for probing targets.
The prober.URL parameter is required. Targets cannot be probed if
left empty.
properties:
path:
description: Path to collect metrics from. Defaults to `/probe`.
type: string
scheme:
description: HTTP scheme to use for scraping. Defaults to `http`.
type: string
url:
description: Mandatory URL of the prober.
type: string
required:
- url
type: object
scrapeTimeout:
description: Timeout for scraping metrics from the Prometheus exporter.
type: string
targets:
description: Targets defines a set of static and/or dynamically discovered
targets to be probed using the prober.
properties:
ingress:
description: Ingress defines the set of dynamically discovered
ingress objects which hosts are considered for probing.
properties:
namespaceSelector:
description: Select Ingress objects by namespace.
properties:
any:
description: Boolean describing whether all namespaces
are selected in contrast to a list restricting them.
type: boolean
matchNames:
description: List of namespace names.
items:
type: string
type: array
type: object
relabelingConfigs:
description: 'RelabelConfigs to apply to samples before ingestion.
More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config'
items:
description: 'RelabelConfig allows dynamic rewriting of
the label set, being applied to samples before ingestion.
It defines `<metric_relabel_configs>`-section of Prometheus
configuration. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs'
properties:
action:
description: Action to perform based on regex matching.
Default is 'replace'
type: string
modulus:
description: Modulus to take of the hash of the source
label values.
format: int64
type: integer
regex:
description: Regular expression against which the extracted
value is matched. Default is '(.*)'
type: string
replacement:
description: Replacement value against which a regex
replace is performed if the regular expression matches.
Regex capture groups are available. Default is '$1'
type: string
separator:
description: Separator placed between concatenated source
label values. default is ';'.
type: string
sourceLabels:
description: The source labels select values from existing
labels. Their content is concatenated using the configured
separator and matched against the configured regular
expression for the replace, keep, and drop actions.
items:
type: string
type: array
targetLabel:
description: Label to which the resulting value is written
in a replace action. It is mandatory for replace actions.
Regex capture groups are available.
type: string
type: object
type: array
selector:
description: Select Ingress objects by labels.
properties:
matchExpressions:
description: matchExpressions is a list of label selector
requirements. The requirements are ANDed.
items:
description: A label selector requirement is a selector
that contains values, a key, and an operator that
relates the key and values.
properties:
key:
description: key is the label key that the selector
applies to.
type: string
operator:
description: operator represents a key's relationship
to a set of values. Valid operators are In, NotIn,
Exists and DoesNotExist.
type: string
values:
description: values is an array of string values.
If the operator is In or NotIn, the values array
must be non-empty. If the operator is Exists or
DoesNotExist, the values array must be empty.
This array is replaced during a strategic merge
patch.
items:
type: string
type: array
required:
- key
- operator
type: object
type: array
matchLabels:
additionalProperties:
type: string
description: matchLabels is a map of {key,value} pairs.
A single {key,value} in the matchLabels map is equivalent
to an element of matchExpressions, whose key field is
"key", the operator is "In", and the values array contains
only "value". The requirements are ANDed.
type: object
type: object
type: object
staticConfig:
description: 'StaticConfig defines static targets which are considers
for probing. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#static_config.'
properties:
labels:
additionalProperties:
type: string
description: Labels assigned to all metrics scraped from the
targets.
type: object
static:
description: Targets is a list of URLs to probe using the
configured prober.
items:
type: string
type: array
type: object
type: object
type: object
required:
- spec
type: object
served: true
storage: true
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,94 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.2.4
creationTimestamp: null
name: prometheusrules.monitoring.coreos.com
spec:
group: monitoring.coreos.com
names:
kind: PrometheusRule
listKind: PrometheusRuleList
plural: prometheusrules
singular: prometheusrule
scope: Namespaced
versions:
- name: v1
schema:
openAPIV3Schema:
description: PrometheusRule defines alerting rules for a Prometheus instance
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: Specification of desired alerting rule definitions for Prometheus.
properties:
groups:
description: Content of Prometheus rule file
items:
description: 'RuleGroup is a list of sequentially evaluated recording
and alerting rules. Note: PartialResponseStrategy is only used
by ThanosRuler and will be ignored by Prometheus instances. Valid
values for this field are ''warn'' or ''abort''. More info: https://github.com/thanos-io/thanos/blob/master/docs/components/rule.md#partial-response'
properties:
interval:
type: string
name:
type: string
partial_response_strategy:
type: string
rules:
items:
description: Rule describes an alerting or recording rule.
properties:
alert:
type: string
annotations:
additionalProperties:
type: string
type: object
expr:
anyOf:
- type: integer
- type: string
x-kubernetes-int-or-string: true
for:
type: string
labels:
additionalProperties:
type: string
type: object
record:
type: string
required:
- expr
type: object
type: array
required:
- name
- rules
type: object
type: array
type: object
required:
- spec
type: object
served: true
storage: true
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,82 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/name: prometheus-operator
app.kubernetes.io/version: v0.41.1
name: prometheus-operator
rules:
- apiGroups:
- monitoring.coreos.com
resources:
- alertmanagers
- alertmanagers/finalizers
- prometheuses
- prometheuses/finalizers
- thanosrulers
- thanosrulers/finalizers
- servicemonitors
- podmonitors
- probes
- prometheusrules
verbs:
- '*'
- apiGroups:
- apps
resources:
- statefulsets
verbs:
- '*'
- apiGroups:
- ""
resources:
- configmaps
- secrets
verbs:
- '*'
- apiGroups:
- ""
resources:
- pods
verbs:
- list
- delete
- apiGroups:
- ""
resources:
- services
- services/finalizers
- endpoints
verbs:
- get
- create
- update
- delete
- apiGroups:
- ""
resources:
- nodes
verbs:
- list
- watch
- apiGroups:
- ""
resources:
- namespaces
verbs:
- get
- list
- watch
- apiGroups:
- authentication.k8s.io
resources:
- tokenreviews
verbs:
- create
- apiGroups:
- authorization.k8s.io
resources:
- subjectaccessreviews
verbs:
- create

View File

@@ -0,0 +1,34 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/name: prometheus-operator
app.kubernetes.io/version: v0.41.1
name: prometheus-operator
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: prometheus-operator
subjects:
- kind: ServiceAccount
name: prometheus-operator
namespace: monitoring
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/name: prometheus-operator
app.kubernetes.io/version: v0.41.1
name: prometheus-operator-admin
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: "cluster-admin"
subjects:
- kind: ServiceAccount
name: prometheus-operator
namespace: monitoring

View File

@@ -0,0 +1,60 @@
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/name: prometheus-operator
app.kubernetes.io/version: v0.41.1
name: prometheus-operator
namespace: monitoring
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/component: controller
app.kubernetes.io/name: prometheus-operator
template:
metadata:
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/name: prometheus-operator
app.kubernetes.io/version: v0.41.1
spec:
containers:
- args:
- --kubelet-service=kube-system/kubelet
- --logtostderr=true
- --config-reloader-image=jimmidyson/configmap-reload:v0.4.0
- --prometheus-config-reloader=quay.io/coreos/prometheus-config-reloader:v0.41.1
image: quay.io/coreos/prometheus-operator:v0.41.1
name: prometheus-operator
ports:
- containerPort: 8080
name: http
resources:
limits:
cpu: 200m
memory: 200Mi
requests:
cpu: 100m
memory: 100Mi
securityContext:
allowPrivilegeEscalation: false
- args:
- --logtostderr
- --secure-listen-address=:8443
- --tls-cipher-suites=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
- --upstream=http://127.0.0.1:8080/
image: quay.io/coreos/kube-rbac-proxy:v0.4.1
name: kube-rbac-proxy
ports:
- containerPort: 8443
name: https
securityContext:
runAsUser: 65534
nodeSelector:
beta.kubernetes.io/os: linux
securityContext:
runAsNonRoot: true
runAsUser: 65534
serviceAccountName: prometheus-operator

View File

@@ -0,0 +1,18 @@
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/name: prometheus-operator
app.kubernetes.io/version: v0.41.1
name: prometheus-operator
namespace: monitoring
spec:
clusterIP: None
ports:
- name: https
port: 8443
targetPort: https
selector:
app.kubernetes.io/component: controller
app.kubernetes.io/name: prometheus-operator

View File

@@ -0,0 +1,9 @@
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/name: prometheus-operator
app.kubernetes.io/version: v0.41.1
name: prometheus-operator
namespace: monitoring

View File

@@ -1,6 +1,6 @@
apiVersion: v2
name: vela-core
description: A Helm chart for Kube Vela core
description: A Helm chart for Kubernetes
# A chart can be either an 'application' or a 'library' chart.
#

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -101,29 +101,16 @@ spec:
to match a value.
properties:
fieldPath:
description: FieldPath specifies got value from
workload/trait object
type: string
op:
description: ConditionOperator specifies the operator
to match a value.
type: string
value:
description: Value specifies an expected value This
is mutually exclusive with ValueFrom
type: string
valueFrom:
description: ValueFrom specifies expected value
from AppConfig This is mutually exclusive with
Value
properties:
fieldPath:
type: string
required:
- fieldPath
type: object
required:
- op
- value
type: object
type: array
fieldPath:
@@ -246,29 +233,16 @@ spec:
requirement to match a value.
properties:
fieldPath:
description: FieldPath specifies got value
from workload/trait object
type: string
op:
description: ConditionOperator specifies the
operator to match a value.
type: string
value:
description: Value specifies an expected value
This is mutually exclusive with ValueFrom
type: string
valueFrom:
description: ValueFrom specifies expected
value from AppConfig This is mutually exclusive
with Value
properties:
fieldPath:
type: string
required:
- fieldPath
type: object
required:
- op
- value
type: object
type: array
fieldPath:
@@ -364,8 +338,6 @@ spec:
- kind
- name
type: object
reason:
type: string
to:
description: DependencyToObject represents the object that
dependency data goes to.
@@ -393,47 +365,10 @@ spec:
type: object
required:
- from
- reason
- to
type: object
type: array
type: object
historyWorkloads:
description: HistoryWorkloads will record history but still working
revision workloads.
items:
description: HistoryWorkload contain the old component revision
that are still running
properties:
revision:
description: component revision of this workload
type: string
workloadRef:
description: Reference to running workload.
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: object
type: array
observedGeneration:
description: The generation observed by the appConfig controller.
format: int64
type: integer
status:
description: Status is a place holder for a customized controller
to fill if it needs a single place to summarize the status of the
@@ -547,6 +482,8 @@ spec:
type: object
type: object
type: array
required:
- dependency
type: object
type: object
served: true

View File

@@ -1,90 +0,0 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.2.5
creationTimestamp: null
name: applicationdeployments.core.oam.dev
spec:
group: core.oam.dev
names:
categories:
- oam
kind: ApplicationDeployment
listKind: ApplicationDeploymentList
plural: applicationdeployments
singular: applicationdeployment
scope: Namespaced
versions:
- name: v1alpha2
schema:
openAPIV3Schema:
description: ApplicationDeployment is the Schema for the ApplicationDeployment
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: ApplicationDeploymentSpec defines the desired state of ApplicationDeployment
type: object
status:
description: ApplicationDeploymentStatus defines the observed state of
ApplicationDeployment
properties:
conditions:
description: Conditions of the resource.
items:
description: A Condition that may apply to a resource.
properties:
lastTransitionTime:
description: LastTransitionTime is the last time this condition
transitioned from one status to another.
format: date-time
type: string
message:
description: A Message containing details about this condition's
last transition from one status to another, if any.
type: string
reason:
description: A Reason for this condition's last transition from
one status to another.
type: string
status:
description: Status of this condition; is it currently True,
False, or Unknown?
type: string
type:
description: Type of this condition. At most one of each condition
type may apply to a resource at any point in time.
type: string
required:
- lastTransitionTime
- reason
- status
- type
type: object
type: array
type: object
type: object
served: true
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

View File

@@ -72,7 +72,6 @@ spec:
will specify parameter values using this name.
type: string
required:
default: false
description: Required specifies whether or not a value for this
parameter must be supplied when authoring an ApplicationConfiguration.
type: boolean
@@ -83,9 +82,7 @@ spec:
type: array
workload:
description: A Workload that will be created for each ApplicationConfiguration
that includes this Component. Workload is an instance of a workloadDefinition.
We either use the GVK info or a special "type" field in the workload
to associate the content of the workload with its workloadDefinition
that includes this Component. Workloads must be defined by a WorkloadDefinition.
type: object
x-kubernetes-embedded-resource: true
x-kubernetes-preserve-unknown-fields: true
@@ -140,10 +137,6 @@ spec:
- name
- revision
type: object
observedGeneration:
description: The generation observed by the component controller.
format: int64
type: integer
type: object
type: object
served: true

View File

@@ -11,190 +11,190 @@ spec:
group: core.oam.dev
names:
categories:
- crossplane
- oam
- crossplane
- oam
kind: HealthScope
listKind: HealthScopeList
plural: healthscopes
singular: healthscope
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .status.health
name: HEALTH
type: string
name: v1alpha2
schema:
openAPIV3Schema:
description: A HealthScope determines an aggregate health status based of
the health of components.
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
- additionalPrinterColumns:
- jsonPath: .status.health
name: HEALTH
type: string
name: v1alpha2
schema:
openAPIV3Schema:
description: A HealthScope determines an aggregate health status based of
the health of components.
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
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: A HealthScopeSpec defines the desired state of a HealthScope.
properties:
probe-interval:
description: ProbeInterval is the amount of time in seconds between
probing tries.
format: int32
type: integer
probe-timeout:
description: ProbeTimeout is the amount of time in seconds to wait
when receiving a response before marked failure.
format: int32
type: integer
workloadRefs:
description: WorkloadReferences to the workloads that are in this
scope.
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
required:
- workloadRefs
type: object
status:
description: A HealthScopeStatus represents the observed state of a HealthScope.
properties:
conditions:
description: Conditions of the resource.
items:
description: A Condition that may apply to a resource.
properties:
lastTransitionTime:
description: LastTransitionTime is the last time this condition
transitioned from one status to another.
format: date-time
type: string
message:
description: A Message containing details about this condition's
last transition from one status to another, if any.
type: string
reason:
description: A Reason for this condition's last transition from
one status to another.
type: string
status:
description: Status of this condition; is it currently True,
False, or Unknown?
type: string
type:
description: Type of this condition. At most one of each condition
type may apply to a resource at any point in time.
type: string
required:
- lastTransitionTime
- reason
- status
- type
type: object
type: array
healthConditions:
description: WorkloadHealthConditions represents health condition
of workloads in the scope
items:
description: WorkloadHealthCondition represents informative health
condition.
properties:
componentName:
description: ComponentName represents the component name if
target is a workload
type: string
diagnosis:
type: string
healthStatus:
description: HealthStatus represents health status strings.
type: string
targetWorkload:
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:
type: string
metadata:
type: object
spec:
description: A HealthScopeSpec defines the desired state of a HealthScope.
properties:
probe-interval:
description: ProbeInterval is the amount of time in seconds between
probing tries.
format: int32
type: integer
probe-timeout:
description: ProbeTimeout is the amount of time in seconds to wait
when receiving a response before marked failure.
format: int32
type: integer
workloadRefs:
description: WorkloadReferences to the workloads that are in this
scope.
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
workloadStatus:
description: WorkloadStatus represents status of workloads whose
HealthStatus is UNKNOWN.
type: object
type: array
required:
- workloadRefs
type: object
status:
description: A HealthScopeStatus represents the observed state of a HealthScope.
properties:
conditions:
description: Conditions of the resource.
items:
description: A Condition that may apply to a resource.
properties:
lastTransitionTime:
description: LastTransitionTime is the last time this condition
transitioned from one status to another.
format: date-time
type: string
message:
description: A Message containing details about this condition's
last transition from one status to another, if any.
type: string
reason:
description: A Reason for this condition's last transition from
one status to another.
type: string
status:
description: Status of this condition; is it currently True,
False, or Unknown?
type: string
type:
description: Type of this condition. At most one of each condition
type may apply to a resource at any point in time.
type: string
required:
- lastTransitionTime
- reason
- status
- type
type: object
type: array
healthConditions:
description: WorkloadHealthConditions represents health condition
of workloads in the scope
items:
description: WorkloadHealthCondition represents informative health
condition.
properties:
componentName:
description: ComponentName represents the component name if
target is a workload
type: string
diagnosis:
type: string
healthStatus:
description: HealthStatus represents health status strings.
type: string
targetWorkload:
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
workloadStatus:
description: WorkloadStatus represents status of workloads whose
HealthStatus is UNKNOWN.
type: string
required:
- healthStatus
type: object
type: array
scopeHealthCondition:
description: ScopeHealthCondition represents health condition summary
of the scope
properties:
healthStatus:
description: HealthStatus represents health status strings.
type: string
healthyWorkloads:
format: int64
type: integer
total:
format: int64
type: integer
unhealthyWorkloads:
format: int64
type: integer
unknownWorkloads:
format: int64
type: integer
required:
- healthStatus
- healthStatus
type: object
type: array
scopeHealthCondition:
description: ScopeHealthCondition represents health condition summary
of the scope
properties:
healthStatus:
description: HealthStatus represents health status strings.
type: string
healthyWorkloads:
format: int64
type: integer
total:
format: int64
type: integer
unhealthyWorkloads:
format: int64
type: integer
unknownWorkloads:
format: int64
type: integer
required:
- healthStatus
type: object
required:
- scopeHealthCondition
type: object
type: object
served: true
storage: true
subresources:
status: {}
required:
- scopeHealthCondition
type: object
type: object
served: true
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""

View File

@@ -85,16 +85,6 @@ spec:
builders
type: object
x-kubernetes-preserve-unknown-fields: true
podSpecPath:
description: PodSpecPath indicates where/if this workload has K8s
podSpec field if one workload has podSpec, trait can do lot's of
assumption such as port, env, volume fields.
type: string
revisionLabel:
description: RevisionLabel indicates which label for underlying resources(e.g.
pods) of this workload can be used by trait to create resource selectors(e.g.
label selector for pods).
type: string
required:
- definitionRef
type: object

View File

@@ -0,0 +1,465 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.2.4
creationTimestamp: null
name: servicemonitors.monitoring.coreos.com
spec:
group: monitoring.coreos.com
names:
kind: ServiceMonitor
listKind: ServiceMonitorList
plural: servicemonitors
singular: servicemonitor
scope: Namespaced
versions:
- name: v1
schema:
openAPIV3Schema:
description: ServiceMonitor defines monitoring for a set of services.
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: Specification of desired Service selection for target discovery
by Prometheus.
properties:
endpoints:
description: A list of endpoints allowed as part of this ServiceMonitor.
items:
description: Endpoint defines a scrapeable endpoint serving Prometheus
metrics.
properties:
basicAuth:
description: 'BasicAuth allow an endpoint to authenticate over
basic authentication More info: https://prometheus.io/docs/operating/configuration/#endpoints'
properties:
password:
description: The secret in the service monitor namespace
that contains the password for authentication.
properties:
key:
description: The key of the secret to select from. Must
be a valid secret key.
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind, uid?'
type: string
optional:
description: Specify whether the Secret or its key must
be defined
type: boolean
required:
- key
type: object
username:
description: The secret in the service monitor namespace
that contains the username for authentication.
properties:
key:
description: The key of the secret to select from. Must
be a valid secret key.
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind, uid?'
type: string
optional:
description: Specify whether the Secret or its key must
be defined
type: boolean
required:
- key
type: object
type: object
bearerTokenFile:
description: File to read bearer token for scraping targets.
type: string
bearerTokenSecret:
description: Secret to mount to read bearer token for scraping
targets. The secret needs to be in the same namespace as the
service monitor and accessible by the Prometheus Operator.
properties:
key:
description: The key of the secret to select from. Must
be a valid secret key.
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind, uid?'
type: string
optional:
description: Specify whether the Secret or its key must
be defined
type: boolean
required:
- key
type: object
honorLabels:
description: HonorLabels chooses the metric's labels on collisions
with target labels.
type: boolean
honorTimestamps:
description: HonorTimestamps controls whether Prometheus respects
the timestamps present in scraped data.
type: boolean
interval:
description: Interval at which metrics should be scraped
type: string
metricRelabelings:
description: MetricRelabelConfigs to apply to samples before
ingestion.
items:
description: 'RelabelConfig allows dynamic rewriting of the
label set, being applied to samples before ingestion. It
defines `<metric_relabel_configs>`-section of Prometheus
configuration. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs'
properties:
action:
description: Action to perform based on regex matching.
Default is 'replace'
type: string
modulus:
description: Modulus to take of the hash of the source
label values.
format: int64
type: integer
regex:
description: Regular expression against which the extracted
value is matched. Default is '(.*)'
type: string
replacement:
description: Replacement value against which a regex replace
is performed if the regular expression matches. Regex
capture groups are available. Default is '$1'
type: string
separator:
description: Separator placed between concatenated source
label values. default is ';'.
type: string
sourceLabels:
description: The source labels select values from existing
labels. Their content is concatenated using the configured
separator and matched against the configured regular
expression for the replace, keep, and drop actions.
items:
type: string
type: array
targetLabel:
description: Label to which the resulting value is written
in a replace action. It is mandatory for replace actions.
Regex capture groups are available.
type: string
type: object
type: array
params:
additionalProperties:
items:
type: string
type: array
description: Optional HTTP URL parameters
type: object
path:
description: HTTP path to scrape for metrics.
type: string
port:
description: Name of the service port this endpoint refers to.
Mutually exclusive with targetPort.
type: string
proxyUrl:
description: ProxyURL eg http://proxyserver:2195 Directs scrapes
to proxy through this endpoint.
type: string
relabelings:
description: 'RelabelConfigs to apply to samples before scraping.
More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config'
items:
description: 'RelabelConfig allows dynamic rewriting of the
label set, being applied to samples before ingestion. It
defines `<metric_relabel_configs>`-section of Prometheus
configuration. More info: https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs'
properties:
action:
description: Action to perform based on regex matching.
Default is 'replace'
type: string
modulus:
description: Modulus to take of the hash of the source
label values.
format: int64
type: integer
regex:
description: Regular expression against which the extracted
value is matched. Default is '(.*)'
type: string
replacement:
description: Replacement value against which a regex replace
is performed if the regular expression matches. Regex
capture groups are available. Default is '$1'
type: string
separator:
description: Separator placed between concatenated source
label values. default is ';'.
type: string
sourceLabels:
description: The source labels select values from existing
labels. Their content is concatenated using the configured
separator and matched against the configured regular
expression for the replace, keep, and drop actions.
items:
type: string
type: array
targetLabel:
description: Label to which the resulting value is written
in a replace action. It is mandatory for replace actions.
Regex capture groups are available.
type: string
type: object
type: array
scheme:
description: HTTP scheme to use for scraping.
type: string
scrapeTimeout:
description: Timeout after which the scrape is ended
type: string
targetPort:
anyOf:
- type: integer
- type: string
description: Name or number of the pod port this endpoint refers
to. Mutually exclusive with port.
x-kubernetes-int-or-string: true
tlsConfig:
description: TLS configuration to use when scraping the endpoint
properties:
ca:
description: Stuct containing the CA cert to use for the
targets.
properties:
configMap:
description: ConfigMap containing data to use for the
targets.
properties:
key:
description: The key to select.
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind,
uid?'
type: string
optional:
description: Specify whether the ConfigMap or its
key must be defined
type: boolean
required:
- key
type: object
secret:
description: Secret containing data to use for the targets.
properties:
key:
description: The key of the secret to select from. Must
be a valid secret key.
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind,
uid?'
type: string
optional:
description: Specify whether the Secret or its key
must be defined
type: boolean
required:
- key
type: object
type: object
caFile:
description: Path to the CA cert in the Prometheus container
to use for the targets.
type: string
cert:
description: Struct containing the client cert file for
the targets.
properties:
configMap:
description: ConfigMap containing data to use for the
targets.
properties:
key:
description: The key to select.
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind,
uid?'
type: string
optional:
description: Specify whether the ConfigMap or its
key must be defined
type: boolean
required:
- key
type: object
secret:
description: Secret containing data to use for the targets.
properties:
key:
description: The key of the secret to select from. Must
be a valid secret key.
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind,
uid?'
type: string
optional:
description: Specify whether the Secret or its key
must be defined
type: boolean
required:
- key
type: object
type: object
certFile:
description: Path to the client cert file in the Prometheus
container for the targets.
type: string
insecureSkipVerify:
description: Disable target certificate validation.
type: boolean
keyFile:
description: Path to the client key file in the Prometheus
container for the targets.
type: string
keySecret:
description: Secret containing the client key file for the
targets.
properties:
key:
description: The key of the secret to select from. Must
be a valid secret key.
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind, uid?'
type: string
optional:
description: Specify whether the Secret or its key must
be defined
type: boolean
required:
- key
type: object
serverName:
description: Used to verify the hostname for the targets.
type: string
type: object
type: object
type: array
jobLabel:
description: The label to use to retrieve the job name from.
type: string
namespaceSelector:
description: Selector to select which namespaces the Endpoints objects
are discovered from.
properties:
any:
description: Boolean describing whether all namespaces are selected
in contrast to a list restricting them.
type: boolean
matchNames:
description: List of namespace names.
items:
type: string
type: array
type: object
podTargetLabels:
description: PodTargetLabels transfers labels on the Kubernetes Pod
onto the target.
items:
type: string
type: array
sampleLimit:
description: SampleLimit defines per-scrape limit on number of scraped
samples that will be accepted.
format: int64
type: integer
selector:
description: Selector to select Endpoints objects.
properties:
matchExpressions:
description: matchExpressions is a list of label selector requirements.
The requirements are ANDed.
items:
description: A label selector requirement is a selector that
contains values, a key, and an operator that relates the key
and values.
properties:
key:
description: key is the label key that the selector applies
to.
type: string
operator:
description: operator represents a key's relationship to
a set of values. Valid operators are In, NotIn, Exists
and DoesNotExist.
type: string
values:
description: values is an array of string values. If the
operator is In or NotIn, the values array must be non-empty.
If the operator is Exists or DoesNotExist, the values
array must be empty. This array is replaced during a strategic
merge patch.
items:
type: string
type: array
required:
- key
- operator
type: object
type: array
matchLabels:
additionalProperties:
type: string
description: matchLabels is a map of {key,value} pairs. A single
{key,value} in the matchLabels map is equivalent to an element
of matchExpressions, whose key field is "key", the operator
is "In", and the values array contains only "value". The requirements
are ANDed.
type: object
type: object
targetLabels:
description: TargetLabels transfers labels on the Kubernetes Service
onto the target.
items:
type: string
type: array
required:
- endpoints
- selector
type: object
required:
- spec
type: object
served: true
storage: true
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

View File

@@ -1,155 +0,0 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.2.5
creationTimestamp: null
name: autoscalers.standard.oam.dev
spec:
group: standard.oam.dev
names:
categories:
- oam
kind: Autoscaler
listKind: AutoscalerList
plural: autoscalers
singular: autoscaler
scope: Namespaced
versions:
- name: v1alpha1
schema:
openAPIV3Schema:
description: Autoscaler is the Schema for the autoscalers 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: AutoscalerSpec defines the desired state of Autoscaler
properties:
maxReplicas:
description: MinReplicas is the maximal replicas
format: int32
type: integer
minReplicas:
description: MinReplicas is the minimal replicas
format: int32
type: integer
targetWorkload:
description: TargetWorkload specify the workload which is going to
be scaled, it could be WorkloadReference or the child resource of
it
properties:
apiVersion:
type: string
kind:
type: string
name:
type: string
required:
- name
type: object
triggers:
description: Triggers lists all triggers
items:
description: Trigger defines the trigger of Autoscaler
properties:
condition:
additionalProperties:
type: string
description: Condition set the condition when to trigger scaling
type: object
name:
description: Name is the trigger name, if not set, it will be
automatically generated and make it globally unique
type: string
type:
description: Type allows value in [cpu/memory/storage/ephemeral-storage、cron、pps、qps/rps、custom]
type: string
required:
- condition
- type
type: object
type: array
workloadRef:
description: WorkloadReference marks the owner of the workload
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:
- triggers
type: object
status:
description: AutoscalerStatus defines the observed state of Autoscaler
properties:
conditions:
description: Conditions of the resource.
items:
description: A Condition that may apply to a resource.
properties:
lastTransitionTime:
description: LastTransitionTime is the last time this condition
transitioned from one status to another.
format: date-time
type: string
message:
description: A Message containing details about this condition's
last transition from one status to another, if any.
type: string
reason:
description: A Reason for this condition's last transition from
one status to another.
type: string
status:
description: Status of this condition; is it currently True,
False, or Unknown?
type: string
type:
description: Type of this condition. At most one of each condition
type may apply to a resource at any point in time.
type: string
required:
- lastTransitionTime
- reason
- status
- type
type: object
type: array
type: object
required:
- spec
type: object
served: true
storage: true
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

View File

@@ -6,22 +6,22 @@ metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.2.5
creationTimestamp: null
name: podspecworkloads.standard.oam.dev
name: containerizeds.standard.oam.dev
spec:
group: standard.oam.dev
names:
categories:
- oam
kind: PodSpecWorkload
listKind: PodSpecWorkloadList
plural: podspecworkloads
singular: podspecworkload
kind: Containerized
listKind: ContainerizedList
plural: containerizeds
singular: containerized
scope: Namespaced
versions:
- name: v1alpha1
schema:
openAPIV3Schema:
description: PodSpecWorkload is the Schema for the PodSpec API
description: Containerized is the Schema for the containerizeds API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
@@ -36,11 +36,11 @@ spec:
metadata:
type: object
spec:
description: PodSpecWorkloadSpec defines the desired state of PodSpecWorkload
description: ContainerizedSpec defines the desired state of Containerized
properties:
podSpec:
description: PodSpec describes the pods that will be created, we omit
the meta part as it will be exactly the same as the PodSpecWorkload
the meta part as it will be exactly the same as the containerized
properties:
activeDeadlineSeconds:
description: Optional duration in seconds the pod may be active
@@ -5691,9 +5691,10 @@ spec:
type: integer
required:
- podSpec
- replicas
type: object
status:
description: PodSpecWorkloadStatus defines the observed state of PodSpecWorkload
description: ContainerizedStatus defines the observed state of Containerized
properties:
conditions:
description: Conditions of the resource.

View File

@@ -56,9 +56,9 @@ spec:
- type: integer
- type: string
description: Number or name of the port to access on the pods
targeted by the service. The default is discovered automatically
from podTemplate, metricTrait will create a service for the
workload
targeted by the service. When this field has value implies that
we need to create a service for the workload Mutually exclusive
with port.
x-kubernetes-int-or-string: true
scheme:
description: Scheme at which metrics should be scraped The default
@@ -68,9 +68,8 @@ spec:
additionalProperties:
type: string
description: Route service traffic to pods with label keys and
values matching this The default is discovered automatically
from podTemplate. If no podTemplate, use the labels specified
here, or use the labels of the workload
values matching this The default is the labels in the workload
Mutually exclusive with port.
type: object
type: object
workloadRef:
@@ -133,20 +132,11 @@ spec:
- type
type: object
type: array
port:
anyOf:
- type: integer
- type: string
description: Port is the real port monitoring
x-kubernetes-int-or-string: true
selectorLabels:
additionalProperties:
type: string
description: SelectorLabels is the real labels selected
type: object
serviceMonitorName:
description: ServiceMonitorName managed by this trait
type: string
description: ServiceMonitorNames managed by this trait
items:
type: string
type: array
type: object
required:
- spec

View File

@@ -38,90 +38,84 @@ spec:
spec:
description: RouteSpec defines the desired state of Route
properties:
backend:
description: Backend indicate how to connect backend service If it's
nil, will auto discovery
properties:
port:
anyOf:
- type: integer
- type: string
description: Port points to backend service port.
x-kubernetes-int-or-string: true
protocol:
description: Protocol means backend-protocol, HTTP, HTTPS, GRPC,
GRPCS, AJP and FCGI, By default uses HTTP
type: string
readTimeout:
description: ReadTimeout used for setting read timeout duration
for backend service, the unit is second.
type: integer
selectLabels:
additionalProperties:
type: string
description: SelectLabels for backend service.
type: object
sendTimeout:
description: SendTimeout used for setting send timeout duration
for backend service, the unit is second.
type: integer
type: object
customHeaders:
additionalProperties:
type: string
description: CustomHeaders pass a custom list of headers to the backend
service.
type: object
defaultBackend:
description: DefaultBackend uses serviceName
properties:
resource:
description: Resource is an ObjectRef to another Kubernetes resource
in the namespace of the Ingress object. If resource is specified,
serviceName and servicePort must not be specified.
properties:
apiGroup:
description: APIGroup is the group for the resource being
referenced. If APIGroup is not specified, the specified
Kind must be in the core API group. For any other third-party
types, APIGroup is required.
type: string
kind:
description: Kind is the type of resource being referenced
type: string
name:
description: Name is the name of resource being referenced
type: string
required:
- kind
- name
type: object
serviceName:
description: Specifies the name of the referenced service.
type: string
servicePort:
anyOf:
- type: integer
- type: string
description: Specifies the port of the referenced service.
x-kubernetes-int-or-string: true
type: object
host:
description: Host is the host of the route
type: string
provider:
description: Provider indicate which ingress controller implementation
the route trait will use, by default it's nginx-ingress
path:
description: Path is location Path, default for "/"
type: string
rewriteTarget:
description: RewriteTarget will rewrite request from Path to RewriteTarget
path.
type: string
rules:
description: Rules contain multiple rules of route
items:
description: Rule defines to route rule
properties:
backend:
description: Backend indicate how to connect backend service
If it's nil, will auto discovery
properties:
backendService:
description: BackendService specifies the backend K8s service
and port, it's optional
properties:
port:
anyOf:
- type: integer
- type: string
description: Port allow you direct specify backend service
port.
x-kubernetes-int-or-string: true
serviceName:
description: ServiceName allow you direct specify K8s
service for backend service.
type: string
required:
- port
- serviceName
type: object
readTimeout:
description: ReadTimeout used for setting read timeout duration
for backend service, the unit is second.
type: integer
sendTimeout:
description: SendTimeout used for setting send timeout duration
for backend service, the unit is second.
type: integer
type: object
customHeaders:
additionalProperties:
type: string
description: CustomHeaders pass a custom list of headers to
the backend service.
type: object
defaultBackend:
description: DefaultBackend will become the ingress default
backend if the backend is not available
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
name:
description: Name will become the suffix of underlying ingress
created by this rule, if not, will use index as suffix.
type: string
path:
description: Path is location Path, default for "/"
type: string
rewriteTarget:
description: RewriteTarget will rewrite request from Path to
RewriteTarget path.
type: string
type: object
type: array
tls:
description: TLS indicate route trait will create SSL secret using
cert-manager with specified issuer If this is nil, route trait will
@@ -130,9 +124,7 @@ spec:
issuerName:
type: string
type:
default: Issuer
description: Type indicate the issuer is ClusterIssuer or Issuer(namespace
issuer), by default, it's Issuer
description: Type indicate the issuer is ClusterIssuer or NamespaceIssuer
type: string
type: object
workloadRef:
@@ -195,30 +187,28 @@ spec:
- type
type: object
type: array
ingresses:
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
ingress:
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
service:
description: A TypedReference refers to an object by Name, Kind, and
APIVersion. It is commonly used to reference cluster-scoped objects
@@ -241,8 +231,6 @@ spec:
- kind
- name
type: object
status:
type: string
type: object
type: object
served: true

View File

@@ -0,0 +1,37 @@
apiVersion: core.oam.dev/v1alpha2
kind: WorkloadDefinition
metadata:
name: backend
annotations:
definition.oam.dev/apiVersion: "standard.oam.dev/v1alpha1"
definition.oam.dev/kind: "Containerized"
spec:
definitionRef:
name: containerizeds.standard.oam.dev
childResourceKinds:
- apiVersion: apps/v1
kind: Deployment
extension:
template: |
#Template: {
apiVersion: "standard.oam.dev/v1alpha1"
kind: "Containerized"
metadata:
name: backend.name
spec: {
replicas: 1
podSpec: {
containers: [{
image: backend.image
name: backend.name
}]
}
}
}
backend: {
name: string
// +usage=specify app image
// +short=i
image: string
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,46 @@
apiVersion: core.oam.dev/v1alpha2
kind: WorkloadDefinition
metadata:
name: containerizeds.standard.oam.dev
annotations:
definition.oam.dev/apiVersion: "standard.oam.dev/v1alpha1"
definition.oam.dev/kind: "Containerized"
spec:
definitionRef:
name: containerizeds.standard.oam.dev
childResourceKinds:
- apiVersion: apps/v1
kind: Deployment
- apiVersion: v1
kind: Service
extension:
template: |
#Template: {
apiVersion: "standard.oam.dev/v1alpha1"
kind: "Containerized"
metadata:
name: webservice.name
spec: {
replicas: 1
podSpec: {
containers: [{
image: webservice.image
name: webservice.name
ports: [{
containerPort: webservice.port
protocol: "TCP"
name: "default"
}]
}]
}
}
}
webservice: {
name: string
// +usage=specify app image
// +short=i
image: string
// +usage=specify port for container
// +short=p
port: *6379 | int
}

View File

@@ -1,73 +0,0 @@
apiVersion: core.oam.dev/v1alpha2
kind: TraitDefinition
metadata:
name: autoscale
annotations:
definition.oam.dev/apiVersion: standard.oam.dev/v1alpha1
definition.oam.dev/kind: Autoscaler
definition.oam.dev/description: "Automatically scale workloads"
spec:
appliesToWorkloads:
- webservice
- backend
- deployments.apps
- podspecworkload
workloadRefPath: spec.workloadRef
definitionRef:
name: autoscalers.standard.oam.dev
extension:
template: |
output: {
apiVersion: "standard.oam.dev/v1alpha1"
kind: "Autoscaler"
spec: {
minReplicas: parameter.min
maxReplicas: parameter.max
if parameter["cpu"] != _|_ && parameter["cron"] != _|_ {
triggers: [cpuScaler, cronScaler]
}
if parameter["cpu"] != _|_ && parameter["cron"] == _|_ {
triggers: [cpuScaler]
}
if parameter["cpu"] == _|_ && parameter["cron"] != _|_ {
triggers: [cronScaler]
}
}
}
cpuScaler: {
type: "cpu"
condition: {
type: "Utilization"
if parameter["cpu"] != _|_ {
value: parameter.cpu
}
}
}
cronScaler: {
type: "cron"
if parameter["cron"] != _|_ {
condition: parameter.cron
}
}
parameter: {
// +usage=minimal replicas of the workload
min: int
// +usage=maximal replicas of the workload
max: int
// +usage=specify the value for CPU utilization, like 80, which means 80%
cpu?: string
// +usage=just for `appfile`, not available for Cli usage
cron?: {
startAt: string
duration: string
// +usage=several workdays or weekends, like "Monday, Tuesday"
days: string
replicas: string
// +usage=timezone, like "America/Seattle"
timezone: string
}
}

View File

@@ -1,30 +0,0 @@
apiVersion: core.oam.dev/v1alpha2
kind: TraitDefinition
metadata:
annotations:
definition.oam.dev/apiVersion: core.oam.dev/v1alpha2
definition.oam.dev/kind: ManualScalerTrait
definition.oam.dev/description: "Scale replica for workload"
name: scaler
spec:
appliesToWorkloads:
- webservice
- containerizedworkloads.core.oam.dev
- deployments.apps
definitionRef:
name: manualscalertraits.core.oam.dev
workloadRefPath: spec.workloadRef
extension:
template: |-
output: {
apiVersion: "core.oam.dev/v1alpha2"
kind: "ManualScalerTrait"
spec: {
replicaCount: parameter.replica
}
}
parameter: {
//+short=r
replica: *1 | int
}

View File

@@ -1,43 +0,0 @@
apiVersion: core.oam.dev/v1alpha2
kind: TraitDefinition
metadata:
name: metric
annotations:
definition.oam.dev/apiVersion: standard.oam.dev/v1alpha1
definition.oam.dev/kind: MetricsTrait
definition.oam.dev/description: "Add metric monitoring for workload"
spec:
appliesToWorkloads:
- webservice
- backend
- task
- containerizedworkloads.core.oam.dev
- clonesetworkloads.apps.kruise.io
- deployments.apps
- statefulsets.apps
definitionRef:
name: metricstraits.standard.oam.dev
workloadRefPath: spec.workloadRef
extension:
template: |-
output: {
apiVersion: "standard.oam.dev/v1alpha1"
kind: "MetricsTrait"
spec: {
scrapeService: parameter
}
}
parameter: {
// +usage=format of the metrics, default as prometheus
// +short=f
format: *"prometheus" | string
// +usage= the metric path of the service
path: *"/metrics" | string
scheme: *"http" | string
enabled: *true | bool
// +usage= the port for metrics, will discovery automatically by default
port: *0 | >=1024 & <=65535 & int
// +usage= the label selector for the pods, will discovery automatically by default
selector?: [string]: string
}

View File

@@ -1,50 +0,0 @@
apiVersion: core.oam.dev/v1alpha2
kind: TraitDefinition
metadata:
name: rollout
spec:
appliesToWorkloads:
- podspecworkload.standard.oam.dev
- deployments.apps
definitionRef:
name: canaries.flagger.app
workloadRefPath: spec.targetRef
revisionEnabled: true
extension:
template: |-
output: {
apiVersion: "flagger.app/v1beta1"
kind: "Canary"
spec: {
provider: "smi"
progressDeadlineSeconds: 60
service: {
// Currently Traffic route is not supported, but this is required field for flagger CRD
port: 80
// Currently Traffic route is not supported, but this is required field for flagger CRD
targetPort: 8080
}
analysis: {
interval: parameter.interval
// max number of failed metric checks before rollback
threshold: 10
// max traffic percentage routed to canary
// percentage (0-100)
maxWeight: 50
// canary increment step
// percentage (0-100)
stepWeight: parameter.stepWeight
// max replicas scale up to canary
maxReplicas: parameter.replica
}
}
}
parameter: {
// +usage=total replica of the workload
replica: *5 | int
// +alias=step-weight
// +usage=weight percent of every step in rolling update
stepWeight: *20 | int
interval: *"30s" | string
}

View File

@@ -1,43 +0,0 @@
apiVersion: core.oam.dev/v1alpha2
kind: WorkloadDefinition
metadata:
name: task
annotations:
definition.oam.dev/apiVersion: "v1"
definition.oam.dev/kind: "Job"
definition.oam.dev/description: "One-time task/job"
spec:
definitionRef:
name: jobs
extension:
template: |
output: {
apiVersion: "v1"
kind: "Job"
spec: {
parallelism: parameter.count
completions: parameter.count
template: spec: {
containers: [{
name: context.name
image: parameter.image
if parameter["cmd"] != _|_ {
command: parameter.cmd
}
}]
}
}
}
parameter: {
// +usage=specify number of tasks to run in parallel
// +short=c
count: *1 | int
// +usage=specify app image
// +short=i
image: string
cmd?: [...string]
}

View File

@@ -1,91 +0,0 @@
apiVersion: core.oam.dev/v1alpha2
kind: WorkloadDefinition
metadata:
name: webservice
annotations:
definition.oam.dev/apiVersion: "apps/v1"
definition.oam.dev/kind: "Deployment"
definition.oam.dev/description: "Long running service with network routes"
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
}
if parameter["env"] != _|_ {
env: parameter.env
}
if context["config"] != _|_ {
env: [
for k, v in context.config {
name: k
value: v
},
]
}
ports: [{
containerPort: parameter.port
}]
if parameter["cpuRequests"] != _|_ {
resources: {
limits:
cpu: parameter.cpuRequests
requests:
cpu: parameter.cpuRequests
}
}
}]
}
}
}
}
parameter: {
// +usage=specify app image
// +short=i
image: string
cmd?: [...string]
// +usage=specify port for container
// +short=p
port: *6379 | int
env?: [...{
name: string
value?: string
valueFrom?: {
secretKeyRef: {
name: string
key: string
}
}
}]
// +usage=CPU core requests for the workload
// +alias=cpu-requests
cpuRequests?: string
}

View File

@@ -1,52 +0,0 @@
apiVersion: core.oam.dev/v1alpha2
kind: WorkloadDefinition
metadata:
name: worker
annotations:
definition.oam.dev/apiVersion: "apps/v1"
definition.oam.dev/kind: "Deployment"
definition.oam.dev/description: "Backend worker without ports exposed"
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
}
}]
}
}
selector:
matchLabels:
"app.oam.dev/component": context.name
}
}
parameter: {
// +usage=specify app image
// +short=i
image: string
cmd?: [...string]
}

View File

@@ -18,7 +18,7 @@ metadata:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ include "kubevela.fullname" . }}:manager-rolebinding
name: manager-rolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
@@ -33,7 +33,7 @@ subjects:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ include "kubevela.fullname" . }}:leader-election-role
name: leader-election-role
rules:
- apiGroups:
- ""
@@ -66,11 +66,11 @@ rules:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ include "kubevela.fullname" . }}:leader-election-rolebinding
name: leader-election-rolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ include "kubevela.fullname" . }}:leader-election-role
name: leader-election-role
subjects:
- kind: ServiceAccount
name: {{ include "kubevela.serviceAccountName" . }}
@@ -80,7 +80,6 @@ apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "kubevela.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "kubevela.labels" . | nindent 4 }}
spec:
@@ -111,7 +110,6 @@ spec:
- "--use-webhook=true"
- "--webhook-port={{ .Values.webhookService.port }}"
- "--webhook-cert-dir={{ .Values.certificate.mountPath }}"
- "--health-addr=:{{ .Values.healthCheck.port }}"
{{ end }}
image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
imagePullPolicy: {{ quote .Values.image.pullPolicy }}
@@ -122,21 +120,6 @@ spec:
- containerPort: {{ .Values.webhookService.port }}
name: webhook-server
protocol: TCP
- containerPort: {{ .Values.healthCheck.port }}
name: healthz
protocol: TCP
readinessProbe:
httpGet:
path: /readyz
port: healthz
initialDelaySeconds: 90
periodSeconds: 5
livenessProbe:
httpGet:
path: /healthz
port: healthz
initialDelaySeconds: 90
periodSeconds: 5
volumeMounts:
- mountPath: {{ .Values.certificate.mountPath }}
name: tls-cert-vol
@@ -158,4 +141,4 @@ spec:
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- end }}

View File

@@ -4,7 +4,7 @@ metadata:
annotations:
definition.oam.dev/apiVersion: core.oam.dev/v1alpha2
definition.oam.dev/kind: ManualScalerTrait
name: scaler
name: manualscalertraits.core.oam.dev
namespace: default
spec:
appliesToWorkloads:
@@ -12,17 +12,17 @@ spec:
- apps/v1.Deployment
definitionRef:
name: manualscalertraits.core.oam.dev
workloadRefPath: spec.workloadRef
extension:
template: |-
output: {
#Template: {
apiVersion: "core.oam.dev/v1alpha2"
kind: "ManualScalerTrait"
spec: {
replicaCount: parameter.replica
replicaCount: scale.replica
}
}
parameter: {
scale: {
//+short=r
replica: *2 | int
}
workloadRefPath: spec.workloadRef

View File

@@ -1,22 +1,17 @@
apiVersion: core.oam.dev/v1alpha2
kind: TraitDefinition
metadata:
name: metric
name: metricstraits.standard.oam.dev
namespace: default
annotations:
definition.oam.dev/apiVersion: standard.oam.dev/v1alpha1
definition.oam.dev/kind: MetricsTrait
definition.oam.dev/description: "Add metric monitoring for workload"
spec:
appliesToWorkloads:
- webservice
- backend
- task
- containerizedworkloads.core.oam.dev
- clonesetworkloads.apps.kruise.io
- deployments.apps
- statefulsets.apps
definitionRef:
name: metricstraits.standard.oam.dev
workloadRefPath: spec.workloadRef
extension:
template: |-
workloadRefPath: spec.workloadRef

View File

@@ -0,0 +1,37 @@
apiVersion: core.oam.dev/v1alpha2
kind: TraitDefinition
metadata:
name: routes.standard.oam.dev
annotations:
definition.oam.dev/apiVersion: standard.oam.dev/v1alpha1
definition.oam.dev/kind: Route
spec:
appliesToWorkloads:
- core.oam.dev/v1alpha2.ContainerizedWorkload
- standard.oam.dev/v1alpha1.Containerized
- deployments.apps
workloadRefPath: spec.workloadRef
definitionRef:
name: routes.standard.oam.dev
extension:
template: |
#Template: {
apiVersion: "standard.oam.dev/v1alpha1"
kind: "Route"
spec: {
host: route.domain
path: route.path
tls: {
issuerName: route.issuer
}
backend: {
port: route.port
}
}
}
route: {
domain: *"" | string
path: *"" | string
port: *443 | int
issuer: *"" | string
}

View File

@@ -0,0 +1,47 @@
apiVersion: core.oam.dev/v1alpha2
kind: WorkloadDefinition
metadata:
name: task
annotations:
definition.oam.dev/apiVersion: "v1"
definition.oam.dev/kind: "Job"
spec:
definitionRef:
name: jobs
extension:
defaultTraits:
- monitor
- logging
template: |
#Template: {
apiVersion: "v1"
kind: "Job"
metadata: name: task.name
spec: {
parallelism: task.count
completions: task.count
template:
spec:
containers: [{
image: task.image
name: task.name
ports: [{
containerPort: task.port
protocol: "TCP"
name: "default"
}]
}]
}
}
task: {
// +usage=specify number of tasks to run in parallel
// +short=c
count: *1 | int
name: string
// +usage=specify app image
// +short=i
image: string
// +usage=specify port for container
// +short=p
port: *6379 | int
}

View File

@@ -2,29 +2,13 @@ apiVersion: v1
kind: ConfigMap
metadata:
name: vela-config
namespace: {{ .Release.Namespace }}
namespace: default
data:
servicemonitors.monitoring.coreos.com: |
certificates.cert-manager.io: |
{
"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"
"repo": "jetstack",
"urL": "https://charts.jetstack.io",
"name": "cert-manager",
"namespace": "cert-manager",
"version": "1.0.0"
}

View File

@@ -3,8 +3,8 @@
apiVersion: admissionregistration.k8s.io/v1beta1
kind: MutatingWebhookConfiguration
metadata:
creationTimestamp: null
name: mutating-webhook-configuration
namespace: {{ .Release.Namespace }}
annotations:
cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ .Values.certificate.certificateName }}
webhooks:
@@ -31,7 +31,7 @@ webhooks:
service:
name: {{ template "kubevela.name" . }}-webhook
namespace: {{ .Release.Namespace }}
path: /mutate-standard-oam-dev-v1alpha1-podspecworkload
path: /mutate-standard-oam-dev-v1alpha1-containerized
failurePolicy: Fail
name: mcontainerized.kb.io
rules:
@@ -43,14 +43,14 @@ webhooks:
- CREATE
- UPDATE
resources:
- podspecworkloads
- Containerized
---
apiVersion: admissionregistration.k8s.io/v1beta1
kind: ValidatingWebhookConfiguration
metadata:
creationTimestamp: null
name: validating-webhook-configuration
namespace: {{ .Release.Namespace }}
annotations:
cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ .Values.certificate.certificateName }}
webhooks:
@@ -78,7 +78,7 @@ webhooks:
service:
name: {{ template "kubevela.name" . }}-webhook
namespace: {{ .Release.Namespace }}
path: /validate-standard-oam-dev-v1alpha1-podspecworkload
path: /validate-standard-oam-dev-v1alpha1-containerized
failurePolicy: Fail
name: vcontainerized.kb.io
rules:
@@ -89,15 +89,15 @@ webhooks:
operations:
- CREATE
- UPDATE
- DELETE
resources:
- podspecworkloads
- Containerized
---
apiVersion: v1
kind: Service
metadata:
name: {{ template "kubevela.name" . }}-webhook
namespace: {{ .Release.Namespace }}
labels:
{{- include "kubevela.labels" . | nindent 4 }}
spec:
@@ -113,7 +113,7 @@ spec:
---
# The following manifests contain a self-signed issuer CR and a certificate CR.
# More document can be found at https://docs.cert-manager.io
apiVersion: cert-manager.io/v1
apiVersion: cert-manager.io/v1alpha2
kind: Issuer
metadata:
name: {{ .Values.certificate.issuerName | quote }}
@@ -121,7 +121,7 @@ spec:
selfSigned: {}
---
apiVersion: cert-manager.io/v1
apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
name: {{ .Values.certificate.certificateName }}

View File

@@ -0,0 +1,46 @@
apiVersion: core.oam.dev/v1alpha2
kind: WorkloadDefinition
metadata:
name: webservice
annotations:
definition.oam.dev/apiVersion: "standard.oam.dev/v1alpha1"
definition.oam.dev/kind: "Containerized"
spec:
definitionRef:
name: containerizeds.standard.oam.dev
childResourceKinds:
- apiVersion: apps/v1
kind: Deployment
- apiVersion: v1
kind: Service
extension:
template: |
#Template: {
apiVersion: "standard.oam.dev/v1alpha1"
kind: "Containerized"
metadata:
name: webservice.name
spec: {
replicas: 1
podSpec: {
containers: [{
image: webservice.image
name: webservice.name
ports: [{
containerPort: webservice.port
protocol: "TCP"
name: "default"
}]
}]
}
}
}
webservice: {
name: string
// +usage=specify app image
// +short=i
image: string
// +usage=specify port for container
// +short=p
port: *6379 | int
}

View File

@@ -7,7 +7,7 @@ useWebhook: true
image:
repository: oamdev/vela-core
tag: latest
pullPolicy: IfNotPresent
pullPolicy: Always
imagePullSecrets: []
nameOverride: ""
@@ -63,9 +63,6 @@ webhookService:
type: ClusterIP
port: 9443
healthCheck:
port: 9440
nodeSelector: {}
tolerations: []

View File

@@ -1,30 +1,28 @@
package main
import (
"errors"
"flag"
"fmt"
"io"
"os"
"os/signal"
"path/filepath"
"strconv"
"syscall"
"time"
monitoring "github.com/coreos/prometheus-operator/pkg/apis/monitoring/v1"
"github.com/crossplane/crossplane-runtime/pkg/logging"
velacore "github.com/oam-dev/kubevela/api/v1alpha1"
velacontroller "github.com/oam-dev/kubevela/pkg/controller"
"github.com/oam-dev/kubevela/pkg/controller/dependency"
velawebhook "github.com/oam-dev/kubevela/pkg/webhook"
oamcore "github.com/crossplane/oam-kubernetes-runtime/apis/core"
oamcontroller "github.com/crossplane/oam-kubernetes-runtime/pkg/controller"
oamv1alpha2 "github.com/crossplane/oam-kubernetes-runtime/pkg/controller/v1alpha2"
oamwebhook "github.com/crossplane/oam-kubernetes-runtime/pkg/webhook/v1alpha2"
"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"
"github.com/oam-dev/trait-injector/pkg/plugin"
certmanager "github.com/wonderflow/cert-manager-api/pkg/apis/certmanager/v1"
kedav1alpha1 "github.com/wonderflow/keda-api/api/v1alpha1"
monitoring "github.com/coreos/prometheus-operator/pkg/apis/monitoring/v1"
"github.com/crossplane/crossplane-runtime/pkg/logging"
certmanager "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha2"
"go.uber.org/zap/zapcore"
"gopkg.in/natefinch/lumberjack.v2"
crdv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
@@ -32,26 +30,10 @@ import (
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"
velacoreoamdev "github.com/oam-dev/kubevela/api/core.oam.dev/v1alpha2"
velacore "github.com/oam-dev/kubevela/api/v1alpha1"
velacontroller "github.com/oam-dev/kubevela/pkg/controller"
"github.com/oam-dev/kubevela/pkg/controller/dependency"
velawebhook "github.com/oam-dev/kubevela/pkg/webhook"
)
const (
kubevelaName = "kubevela"
)
var (
setupLog = ctrl.Log.WithName(kubevelaName)
scheme = runtime.NewScheme()
waitSecretTimeout = 90 * time.Second
waitSecretInterval = 2 * time.Second
)
var scheme = runtime.NewScheme()
func init() {
_ = clientgoscheme.AddToScheme(scheme)
@@ -59,10 +41,9 @@ func init() {
_ = oamcore.AddToScheme(scheme)
_ = monitoring.AddToScheme(scheme)
_ = velacore.AddToScheme(scheme)
_ = velacoreoamdev.AddToScheme(scheme)
_ = injectorv1alpha1.AddToScheme(scheme)
_ = certmanager.AddToScheme(scheme)
_ = kedav1alpha1.AddToScheme(scheme)
// +kubebuilder:scaffold:scheme
}
@@ -74,7 +55,6 @@ func main() {
var webhookPort int
var useWebhook, useTraitInjector bool
var controllerArgs oamcontroller.Args
var healthAddr string
flag.BoolVar(&useWebhook, "use-webhook", false, "Enable Admission Webhook")
flag.BoolVar(&useTraitInjector, "use-trait-injector", false, "Enable TraitInjector")
@@ -88,7 +68,6 @@ func main() {
flag.BoolVar(&logCompress, "log-compress", true, "Enable compression on the rotated logs.")
flag.IntVar(&controllerArgs.RevisionLimit, "revision-limit", 50,
"RevisionLimit is the maximum number of revisions that will be maintained. The default value is 50.")
flag.StringVar(&healthAddr, "health-addr", ":9440", "The address the health endpoint binds to.")
flag.Parse()
// setup logging
@@ -108,44 +87,35 @@ func main() {
o.DestWritter = w
}))
// 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)
setupLog := ctrl.Log.WithName("vela-runtime")
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
Scheme: scheme,
MetricsBindAddress: metricsAddr,
LeaderElection: enableLeaderElection,
LeaderElectionID: kubevelaName,
Port: webhookPort,
CertDir: certDir,
HealthProbeBindAddress: healthAddr,
Scheme: scheme,
MetricsBindAddress: metricsAddr,
LeaderElection: enableLeaderElection,
LeaderElectionID: "vela-runtime",
Port: webhookPort,
CertDir: certDir,
})
if err != nil {
setupLog.Error(err, "unable to create a controller manager")
os.Exit(1)
}
if err := registerHealthChecks(mgr); err != nil {
setupLog.Error(err, "unable to register ready/health checks")
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)
}
if err = dependency.Install(k8sClient); err != nil {
setupLog.Error(err, "unable to install the dependency")
os.Exit(1)
}
if useWebhook {
setupLog.Info("vela webhook enabled, will serving at :" + strconv.Itoa(webhookPort))
if err = oamwebhook.Add(mgr); err != nil {
setupLog.Error(err, "unable to setup oam runtime webhook")
os.Exit(1)
}
oamwebhook.Add(mgr)
velawebhook.Register(mgr)
if err := waitWebhookSecretVolume(certDir, waitSecretTimeout, waitSecretInterval); err != nil {
setupLog.Error(err, "unable to get webhook secret")
os.Exit(1)
}
}
if err = oamv1alpha2.Setup(mgr, controllerArgs, logging.NewLogrLogger(setupLog)); err != nil {
@@ -177,84 +147,8 @@ func main() {
}
setupLog.Info("starting the vela controller manager")
if err := mgr.Start(makeSignalHandler(setupLog, k8sClient)); err != nil {
if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
setupLog.Error(err, "problem running manager")
os.Exit(1)
}
setupLog.Info("program safely stops...")
}
// registerHealthChecks is used to create readiness&liveness probes
func registerHealthChecks(mgr ctrl.Manager) error {
setupLog.Info("creating readiness/health check")
if err := mgr.AddReadyzCheck("ping", healthz.Ping); err != nil {
return err
}
if err := mgr.AddHealthzCheck("ping", healthz.Ping); err != nil {
return err
}
return nil
}
// waitWebhookSecretVolume waits for webhook secret ready to avoid mgr running crash
func waitWebhookSecretVolume(certDir string, timeout, interval time.Duration) error {
start := time.Now()
for {
time.Sleep(interval)
if time.Since(start) > timeout {
return fmt.Errorf("getting webhook secret timeout after %s", timeout.String())
}
setupLog.Info(fmt.Sprintf("waiting webhook secret, time consumed: %d/%d seconds ...",
int64(time.Since(start).Seconds()), int64(timeout.Seconds())))
if _, err := os.Stat(certDir); !os.IsNotExist(err) {
ready := func() bool {
f, _ := os.Open(certDir)
defer f.Close()
// check if dir is empty
if _, err := f.Readdir(1); err == io.EOF {
return false
}
// check if secret files are empty
err := filepath.Walk(certDir, func(path string, info os.FileInfo, err error) error {
// even Cert dir is created, cert files are still empty for a while
if info.Size() == 0 {
return errors.New("secret is not ready")
}
return nil
})
if err == nil {
setupLog.Info(fmt.Sprintf("webhook secret is ready (time consumed: %d seconds)",
int64(time.Since(start).Seconds())))
return true
}
return false
}()
if ready {
return nil
}
}
}
}
func makeSignalHandler(log logr.Logger, kubecli client.Client) (stopCh <-chan struct{}) {
stop := make(chan struct{})
c := make(chan os.Signal, 2)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
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.
<-c
os.Exit(1)
}()
return stop
}

View File

@@ -1,66 +0,0 @@
package main
import (
"io/ioutil"
"os"
"testing"
"time"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var (
testdir = "testdir"
testTimeout = 2 * time.Second
testInterval = 1 * time.Second
)
func TestGinkgo(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "test main")
}
var _ = Describe("test waitSecretVolume", func() {
BeforeEach(func() {
err := os.MkdirAll(testdir, 0755)
Expect(err).NotTo(HaveOccurred())
})
AfterEach(func() {
os.RemoveAll(testdir)
})
When("dir not exist or empty", func() {
It("return timeout error", func() {
err := waitWebhookSecretVolume(testdir, testTimeout, testInterval)
Expect(err).To(HaveOccurred())
By("remove dir")
os.RemoveAll(testdir)
err = waitWebhookSecretVolume(testdir, testTimeout, testInterval)
Expect(err).To(HaveOccurred())
})
})
When("dir contains empty file", func() {
It("return timeout error", func() {
By("add empty file")
_, err := os.Create(testdir + "/emptyFile")
Expect(err).NotTo(HaveOccurred())
err = waitWebhookSecretVolume(testdir, testTimeout, testInterval)
Expect(err).To(HaveOccurred())
})
})
When("files in dir are not empty", func() {
It("return nil", func() {
By("add non-empty file")
_, err := os.Create(testdir + "/file")
Expect(err).NotTo(HaveOccurred())
err = ioutil.WriteFile(testdir+"/file", []byte("test"), os.ModeAppend)
Expect(err).NotTo(HaveOccurred())
err = waitWebhookSecretVolume(testdir, testTimeout, testInterval)
Expect(err).NotTo(HaveOccurred())
})
})
})

View File

@@ -1,5 +0,0 @@
package fake
// ChartSource is a base64-encoded, gzipped tarball of the default Helm chart(charts/vela-core).
// Its value is initialized at build time. This whole file will be rewrite at that time, please don't change this file.
var ChartSource string

View File

@@ -1,19 +1,176 @@
package main
import (
"flag"
"fmt"
"math/rand"
"os"
"runtime"
"time"
"github.com/oam-dev/kubevela/api/types"
"github.com/oam-dev/kubevela/cmd/vela/fake"
"github.com/oam-dev/kubevela/pkg/commands"
cmdutil "github.com/oam-dev/kubevela/pkg/commands/util"
"github.com/oam-dev/kubevela/pkg/utils/system"
"github.com/oam-dev/kubevela/version"
"github.com/crossplane/oam-kubernetes-runtime/apis/core"
"github.com/gosuri/uitable"
certmanager "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha2"
"github.com/spf13/cobra"
k8sruntime "k8s.io/apimachinery/pkg/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
"k8s.io/klog"
"sigs.k8s.io/controller-runtime/pkg/client/config"
)
var (
scheme = k8sruntime.NewScheme()
)
// chartTGZSource is a base64-encoded, gzipped tarball of the default Helm chart.
// Its value is initialized at build time.
var chartTGZSource string
func init() {
_ = clientgoscheme.AddToScheme(scheme)
_ = certmanager.AddToScheme(scheme)
_ = core.AddToScheme(scheme)
// +kubebuilder:scaffold:scheme
}
func main() {
rand.Seed(time.Now().UnixNano())
command := commands.NewCommand()
command := newCommand()
if err := command.Execute(); err != nil {
os.Exit(1)
}
}
func newCommand() *cobra.Command {
ioStream := cmdutil.IOStreams{In: os.Stdin, Out: os.Stdout, ErrOut: os.Stderr}
cmds := &cobra.Command{
Use: "vela",
DisableFlagParsing: true,
Run: func(cmd *cobra.Command, args []string) {
allCommands := cmd.Commands()
cmd.Printf("✈️ A Micro App Platform for Kubernetes.\n\nUsage:\n vela [flags]\n vela [command]\n\nAvailable Commands:\n\n")
PrintHelpByTag(cmd, allCommands, types.TypeStart)
PrintHelpByTag(cmd, allCommands, types.TypeApp)
PrintHelpByTag(cmd, allCommands, types.TypeTraits)
PrintHelpByTag(cmd, allCommands, types.TypeOthers)
PrintHelpByTag(cmd, allCommands, types.TypeSystem)
cmd.Println("Flags:")
cmd.Println(" -h, --help help for vela")
cmd.Println()
cmd.Println(`Use "vela [command] --help" for more information about a command.`)
},
SilenceUsage: true,
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return nil, cobra.ShellCompDirectiveNoFileComp
},
}
cmds.PersistentFlags().StringP("env", "e", "", "specify env name for application")
restConf, err := config.GetConfig()
if err != nil {
fmt.Println("get kubeconfig err", err)
os.Exit(1)
}
commandArgs := types.Args{
Config: restConf,
Schema: scheme,
}
if err := system.InitDirs(); err != nil {
fmt.Println("InitDir err", err)
os.Exit(1)
}
cmds.AddCommand(
// Getting Start
commands.NewInstallCommand(commandArgs, chartTGZSource, ioStream),
commands.NewEnvCommand(commandArgs, ioStream),
// Getting Start
NewVersionCommand(),
// Apps
commands.NewAppsCommand(commandArgs, ioStream),
// Workloads
commands.AddCompCommands(commandArgs, ioStream),
// Capability Systems
commands.CapabilityCommandGroup(commandArgs, ioStream),
// System
commands.SystemCommandGroup(commandArgs, ioStream),
commands.NewCompletionCommand(),
commands.NewTraitsCommand(ioStream),
commands.NewWorkloadsCommand(ioStream),
commands.NewDashboardCommand(commandArgs, ioStream, fake.FrontendSource),
commands.NewLogsCommand(commandArgs, ioStream),
)
// Traits
if err = commands.AddTraitCommands(cmds, commandArgs, ioStream); err != nil {
fmt.Println("Add trait commands from traitDefinition err", err)
os.Exit(1)
}
// this is for mute klog
fset := flag.NewFlagSet("logs", flag.ContinueOnError)
klog.InitFlags(fset)
_ = fset.Set("v", "-1")
return cmds
}
func PrintHelpByTag(cmd *cobra.Command, all []*cobra.Command, tag string) {
cmd.Printf(" %s:\n\n", tag)
table := uitable.New()
for _, c := range all {
if val, ok := c.Annotations[types.TagCommandType]; ok && val == tag {
table.AddRow(" "+c.Use, c.Long)
for _, subcmd := range c.Commands() {
table.AddRow(" "+subcmd.Use, " "+subcmd.Long)
}
}
}
cmd.Println(table.String())
if tag == types.TypeTraits {
if len(table.Rows) > 0 {
cmd.Println()
}
cmd.Println(" Want more? < install more capabilities by `vela cap` >")
}
cmd.Println()
}
func NewVersionCommand() *cobra.Command {
return &cobra.Command{
Use: "version",
Short: "Prints out build version information",
Long: "Prints out build version information",
Run: func(cmd *cobra.Command, args []string) {
fmt.Printf(`Version: %v
GitRevision: %v
GolangVersion: %v
`,
version.VelaVersion,
version.GitRevision,
runtime.Version())
},
Annotations: map[string]string{
types.TagCommandType: types.TypeStart,
},
}
}

View File

@@ -1,3 +0,0 @@
coverage:
status:
patch: off

View File

@@ -74,3 +74,23 @@ rules:
- get
- patch
- update
- apiGroups:
- standard.oam.dev
resources:
- routes
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- standard.oam.dev
resources:
- routes/status
verbs:
- get
- patch
- update

View File

@@ -0,0 +1,19 @@
apiVersion: cert-manager.io/v1alpha2
kind: Issuer
metadata:
name: letsencrypt-prod
spec:
acme:
# You must replace this email address with your own.
# Let's Encrypt will use this to contact you about expiring
# certificates, and issues related to your account.
email: wonderflow@icloud.com
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
# Secret resource that will be used to store the account's private key.
name: example-issuer-account-key
# Add a single challenge solver, HTTP01 using nginx
solvers:
- http01:
ingress:
class: nginx

View File

@@ -0,0 +1,25 @@
apiVersion: core.oam.dev/v1alpha2
kind: TraitDefinition
metadata:
name: manualscalertraits.core.oam.dev
annotations:
definition.oam.dev/apiVersion: "core.oam.dev/v1alpha2"
definition.oam.dev/kind: "ManualScalerTrait"
spec:
appliesToWorkloads:
- core.oam.dev/v1alpha2.ContainerizedWorkload
definitionRef:
name: manualscalertraits.core.oam.dev
extension:
template: |
#Template: {
apiVersion: "core.oam.dev/v1alpha2"
kind: "ManualScalerTrait"
spec: {
replicaCount: scale.replica
}
}
scale: {
//+short=r
replica: *2 | int
}

View File

@@ -1,43 +1,37 @@
apiVersion: core.oam.dev/v1alpha2
kind: TraitDefinition
metadata:
name: route
name: routes.standard.oam.dev
annotations:
definition.oam.dev/apiVersion: standard.oam.dev/v1alpha1
definition.oam.dev/kind: Route
definition.oam.dev/description: "Add a route for workload"
spec:
appliesToWorkloads:
- webservice
- core.oam.dev/v1alpha2.ContainerizedWorkload
- standard.oam.dev/v1alpha1.Containerized
- deployments.apps
workloadRefPath: spec.workloadRef
definitionRef:
name: routes.standard.oam.dev
extension:
template: |
output: {
#Template: {
apiVersion: "standard.oam.dev/v1alpha1"
kind: "Route"
spec: {
host: parameter.domain
if parameter.issuer != "" {
tls: {
issuerName: parameter.issuer
}
host: route.domain
path: route.path
tls: {
issuerName: route.issuer
}
if parameter["rules"] != _|_ {
rules: parameter.rules
backend: {
port: route.port
}
}
}
parameter: {
route: {
domain: *"" | string
path: *"" | string
port: *443 | int
issuer: *"" | string
rules?: [...{
path: string
rewriteTarget: *"" | string
}]
}

View File

@@ -0,0 +1,30 @@
apiVersion: core.oam.dev/v1alpha2
kind: TraitDefinition
metadata:
name: simplerollouttraits.extend.oam.dev
annotations:
"definition.oam.dev/apiVersion": "extend.oam.dev/v1alpha2"
"definition.oam.dev/kind": "SimpleRolloutTrait"
spec:
revisionEnabled: true
appliesToWorkloads:
- core.oam.dev/v1alpha2.ContainerizedWorkload
- deployments.apps
definitionRef:
name: simplerollouttraits.extend.oam.dev
extension:
template: |
#Template: {
apiVersion: "extend.oam.dev/v1alpha2"
kind: "SimpleRolloutTrait"
spec: {
replica: rollout.replica
maxUnavailable: rollout.maxUnavailable
batch: rollout.batch
}
}
rollout: {
replica: *3 | int
maxUnavailable: *1 | int
batch: *2 | int
}

View File

@@ -0,0 +1,43 @@
apiVersion: core.oam.dev/v1alpha2
kind: WorkloadDefinition
metadata:
name: containerizedworkloads.core.oam.dev
annotations:
definition.oam.dev/apiVersion: "core.oam.dev/v1alpha2"
definition.oam.dev/kind: "ContainerizedWorkload"
spec:
definitionRef:
name: containerizedworkloads.core.oam.dev
childResourceKinds:
- apiVersion: apps/v1
kind: Deployment
- apiVersion: v1
kind: Service
extension:
template: |
#Template: {
apiVersion: "core.oam.dev/v1alpha2"
kind: "ContainerizedWorkload"
metadata: name: containerized.name
spec: {
containers: [{
image: containerized.image
name: containerized.name
ports: [{
containerPort: containerized.port
protocol: "TCP"
name: "default"
}]
}]
}
}
containerized: {
name: string
// +usage=specify app image
// +short=i
image: string
// +usage=specify port for container
// +short=p
port: *6379 | int
}

View File

@@ -0,0 +1,52 @@
apiVersion: core.oam.dev/v1alpha2
kind: WorkloadDefinition
metadata:
name: deployments.apps
annotations:
definition.oam.dev/apiVersion: "apps/v1"
definition.oam.dev/kind: "Deployment"
spec:
definitionRef:
name: deployments.apps
extension:
template: |
#Template: {
apiVersion: "apps/v1"
kind: "Deployment"
metadata: name: deployment.name
spec: {
selector:
matchLabels:
app: deployment.name
template: {
metadata:
labels:
app: deployment.name
spec: containers: [{
image: deployment.image
name: deployment.name
env: deployment.env
ports: [{
containerPort: deployment.port
protocol: "TCP"
name: "default"
}]
}]
}
}
}
deployment: {
name: string
// +usage=specify app image
// +short=i
image: string
// +usage=specify port for container
// +short=p
port: *8080 | int
env: [...{
name: string
value: string
}]
}

View File

@@ -29,9 +29,9 @@ webhooks:
service:
name: webhook-service
namespace: system
path: /mutate-standard-oam-dev-v1alpha1-podspecworkload
path: /mutate-standard-oam-dev-v1alpha1-containerized
failurePolicy: Fail
name: mpodspecworkload.kb.io
name: mcontainerized.kb.io
rules:
- apiGroups:
- standard.oam.dev
@@ -41,7 +41,7 @@ webhooks:
- CREATE
- UPDATE
resources:
- PodSpecWorkload
- Containerized
---
apiVersion: admissionregistration.k8s.io/v1beta1
@@ -74,9 +74,9 @@ webhooks:
service:
name: webhook-service
namespace: system
path: /validate-standard-oam-dev-v1alpha1-podspecworkload
path: /validate-standard-oam-dev-v1alpha1-containerized
failurePolicy: Fail
name: vpodspecworkload.kb.io
name: vcontainerized.kb.io
rules:
- apiGroups:
- standard.oam.dev
@@ -87,4 +87,4 @@ webhooks:
- UPDATE
- DELETE
resources:
- PodSpecWorkload
- Containerized

View File

@@ -42,6 +42,12 @@ export default defineConfig({
path: `/ApplicationList`,
component: './ApplicationList',
},
{
name: 'ApplicationList.ApplicationListDetail',
hideInMenu: true,
path: '/ApplicationList/ApplicationListDetail',
component: './ApplicationList/ApplicationListDetail',
},
{
name: 'ApplicationList.WorkloadDetail',
icon: 'smile',
@@ -56,6 +62,12 @@ export default defineConfig({
component: './Traits/Detail',
hideInMenu: true,
},
{
name: 'ApplicationList.CreateApplication',
hideInMenu: true,
path: '/ApplicationList/CreateApplication',
component: './ApplicationList/CreateApplication',
},
{
name: 'ApplicationList.Components',
hideInMenu: true,

View File

@@ -8,7 +8,7 @@
export default {
dev: {
'/api': {
target: 'http://127.0.0.1:38081/',
target: 'http://30.11.171.29:38081/',
changeOrigin: true,
},
},

View File

@@ -35,10 +35,6 @@ export default class CreateTraitItem extends React.PureComponent {
return this.formRefStep2.current.getFieldsValue();
};
resetFields = () => {
return this.formRefStep2.current.resetFields();
};
validateFields = () => {
return this.formRefStep2.current.validateFields();
};

View File

@@ -30,7 +30,6 @@ class Trait extends React.Component {
this.state = {
visible: false,
selectValue: null,
compList: [],
};
}
@@ -38,19 +37,6 @@ class Trait extends React.Component {
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({
@@ -85,12 +71,7 @@ class Trait extends React.Component {
};
const submitData = this.formRefStep2.current.getFieldValue();
Object.keys(submitData).forEach((currentKey) => {
if (
currentKey !== 'name' &&
currentKey !== 'appName' &&
currentKey !== 'compName' &&
submitData[currentKey]
) {
if (currentKey !== 'name' && currentKey !== 'appName' && submitData[currentKey]) {
submitObj.flags.push({
name: currentKey,
value: submitData[currentKey].toString(),
@@ -98,14 +79,13 @@ class Trait extends React.Component {
}
});
const { currentEnv: envName } = this.props;
const { appName, compName } = submitData;
if (envName && appName && compName) {
const { appName } = submitData;
if (envName && appName) {
const res = await this.props.dispatch({
type: 'trait/attachOneTraits',
payload: {
envName,
appName,
compName,
params: submitObj,
},
});
@@ -116,8 +96,11 @@ class Trait extends React.Component {
message.success(res);
const { history } = this.props.propsObj;
history.push({
pathname: `/ApplicationList/${appName}/Components`,
state: { appName, envName },
pathname: '/ApplicationList/ApplicationListDetail',
state: {
appName,
envName,
},
});
}
}
@@ -130,30 +113,10 @@ class Trait extends React.Component {
});
};
onChange = async (value) => {
onChange = (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 = () => {};
@@ -168,11 +131,7 @@ class Trait extends React.Component {
}
});
}
let appList = _.get(this.props, 'returnObj', []);
if (!appList) {
appList = [];
}
const { compList = [] } = this.state;
const appList = _.get(this.props, 'returnObj', []);
return (
<div>
<div className="breadCrumb">
@@ -253,12 +212,13 @@ class Trait extends React.Component {
initialValues={initialObj}
>
<Form.Item
label="App"
label="Target"
name="appName"
rules={[{ required: true, message: 'Please Select a Application!' }]}
>
<Select
showSearch
allowClear
value={this.state.selectValue}
style={{ width: '100%' }}
placeholder="Select a Application"
@@ -270,9 +230,9 @@ class Trait extends React.Component {
}
>
{appList.length ? (
appList.map((item, index) => {
appList.map((item) => {
return (
<Option key={index.toString()} value={item.name}>
<Option key={item.name} value={item.name}>
{item.name}
</Option>
);
@@ -282,30 +242,6 @@ class Trait extends React.Component {
)}
</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 ? (

View File

@@ -1,108 +1,12 @@
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 { Button, Row, Col, Breadcrumb } from 'antd';
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 = () => {};
export default class Workload extends React.PureComponent {
render() {
const { btnValue, title, crdInfo, settings, btnIsShow } = this.props.propsObj;
let appList = _.get(this.props, 'returnObj', []);
if (!appList) {
appList = [];
}
const { btnValue, pathname, title, crdInfo, state, settings, btnIsShow } = this.props.propsObj;
return (
<div>
<div className="breadCrumb">
@@ -152,73 +56,13 @@ export default class Workload extends React.Component {
);
})}
</div>
{/* <Link to={{ pathname, state }} style={{ display: btnIsShow ? 'block' : 'none' }}>
<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>
</Link>
</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

@@ -85,19 +85,3 @@ ol {
.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,22 +0,0 @@
import { getComponentList, getComponentDetail, deleteComponent } from '@/services/components.js';
const TestModel = {
namespace: 'components',
state: {},
effects: {
*getComponentList({ payload }, { call }) {
const res = yield call(getComponentList, payload);
return res;
},
*getComponentDetail({ payload }, { call }) {
const res = yield call(getComponentDetail, payload);
return res;
},
*deleteComponent({ payload }, { call }) {
const res = yield call(deleteComponent, payload);
return res;
},
},
reducers: {},
};
export default TestModel;

View File

@@ -0,0 +1,108 @@
import React, { useEffect } from 'react';
import G6 from '@antv/g6';
const Topology = () => {
let graph = null;
const data = {
nodes: [
{
id: 'node1',
x: 150,
y: 50,
label: 'node1',
},
{
id: 'node2',
x: 250,
y: 200,
label: 'node2',
},
{
id: 'node3',
x: 100,
y: 350,
label: 'node3',
},
],
edges: [
{
source: 'node1',
target: 'node2',
label: 'edge 1',
},
{
source: 'node2',
target: 'node3',
label: 'edge 2',
},
{
source: 'node3',
target: 'node1',
label: 'edge 3',
},
],
};
const width = 1000;
const height = 400;
useEffect(() => {
if (!graph) {
graph = new G6.Graph({
container: 'container',
width,
height,
// translate the graph to align the canvas's center, support by v3.5.1
fitCenter: true,
defaultNode: {
type: 'circle',
size: [40],
color: '#5B8FF9',
style: {
fill: '#9EC9FF',
lineWidth: 3,
},
labelCfg: {
style: {
fill: '#1890ff',
fontSize: 14,
},
position: 'bottom',
},
},
defaultEdge: {
labelCfg: {
autoRotate: true,
style: {
background: {
fill: '#ffffff',
stroke: '#9EC9FF',
padding: [2, 2, 2, 2],
radius: 2,
},
},
},
},
modes: {
default: ['drag-canvas', 'drag-node'],
},
nodeStateStyles: {
// style configurations for hover state
hover: {
fillOpacity: 0.8,
},
// style configurations for selected state
selected: {
lineWidth: 5,
},
},
});
}
graph.data(data);
graph.render();
}, []);
return <div id="container" style={{ overflow: 'auto', width: '100%', height: '400px' }} />;
};
export default Topology;

View File

@@ -0,0 +1,490 @@
import React, { Fragment } from 'react';
import { PageContainer } from '@ant-design/pro-layout';
import './index.less';
import {
Button,
Row,
Col,
Tabs,
Popconfirm,
message,
Tooltip,
Modal,
Spin,
Breadcrumb,
} from 'antd';
import { connect } from 'dva';
import _ from 'lodash';
import { Link } from 'umi';
import CreateTraitItem from '../../../components/AttachOneTrait/index.jsx';
const { TabPane } = Tabs;
@connect(({ loading, globalData }) => ({
loadingAll: loading.models.applist,
currentEnv: globalData.currentEnv,
}))
class TableList extends React.Component {
constructor(props) {
super(props);
this.state = {
appDetailData: {},
visible: false,
traitList: [],
availableTraitList: [],
envName: '',
appName: '',
};
}
componentDidMount() {
this.getInitialData();
}
getInitialData = async () => {
let appName = '';
let envName = '';
if (this.props.location.state) {
appName = _.get(this.props, 'location.state.appName', '');
envName = _.get(this.props, 'location.state.envName', '');
sessionStorage.setItem('appName', appName);
sessionStorage.setItem('envName', envName);
} else {
appName = sessionStorage.getItem('appName');
envName = sessionStorage.getItem('envName');
}
this.setState({
appName,
envName,
});
if (appName && envName) {
const res = await this.props.dispatch({
type: 'applist/getAppDetail',
payload: {
envName,
appName,
},
});
if (res) {
this.setState({
appDetailData: res,
});
}
const traits = await this.props.dispatch({
type: 'trait/getTraits',
});
if (traits) {
this.setState({
traitList: traits,
});
}
const workloadType = _.get(res, 'Workload.workload.kind', '');
if (workloadType && workloadType === 'ContainerizedWorkload') {
this.getAcceptTrait('containerized');
} else if (workloadType && workloadType === 'Deployment') {
this.getAcceptTrait('deployment');
}
}
};
getAcceptTrait = (workloadType) => {
const res = this.state.traitList.filter((item) => {
if (item.appliesTo.indexOf(workloadType) !== -1) {
return true;
}
return false;
});
this.setState(() => ({
availableTraitList: res,
}));
};
deleteApp = async (e) => {
e.stopPropagation();
const { envName } = this.state;
const { appDetailData } = this.state;
const appName = _.get(appDetailData, 'Workload.workload.metadata.name', '');
if (appName && envName) {
const res = await this.props.dispatch({
type: 'applist/deleteApp',
payload: {
appName,
envName,
},
});
if (res) {
message.success(res);
this.props.history.push({ pathname: '/ApplicationList' });
}
}
};
deleteTrait = async (e, item) => {
e.stopPropagation();
const { appName, envName } = this.state;
const traitNameObj = _.get(item, 'trait.metadata.annotations', '');
const traitName = traitNameObj['vela.oam.dev/traitDef'] || traitNameObj['trait.oam.dev/name'];
if (traitName && appName && envName) {
const res = await this.props.dispatch({
type: 'trait/deleteOneTrait',
payload: {
envName,
appName,
traitName,
},
});
if (res) {
message.success(res);
this.getInitialData(2);
}
}
};
cancel = (e) => {
e.stopPropagation();
};
createTrait = async () => {
await this.setState({
visible: true,
});
};
handleOk = async () => {
await this.child.validateFields();
const submitData = this.child.getSelectValue();
if (submitData.name) {
const submitObj = {
name: submitData.name,
flags: [],
};
Object.keys(submitData).forEach((currentKey) => {
if (currentKey !== 'name' && submitData[currentKey]) {
submitObj.flags.push({
name: currentKey,
value: submitData[currentKey].toString(),
});
}
});
const { envName, appName } = this.state;
if (envName && appName) {
const res = await this.props.dispatch({
type: 'trait/attachOneTraits',
payload: {
envName,
appName,
params: submitObj,
},
});
if (res) {
this.setState({
visible: false,
});
message.success(res);
this.getInitialData(2);
}
}
} else {
message.warning('please select a trait type');
}
};
handleCancel = () => {
this.setState({
visible: false,
});
};
hrefClick = (e) => {
e.stopPropagation();
};
gotoWorkloadDetail = (e) => {
e.stopPropagation();
};
gotoTraitDetail = (e) => {
e.stopPropagation();
};
render() {
const status = _.get(this.state.appDetailData, 'Status', '');
const Workload = _.get(this.state.appDetailData, 'Workload.workload', {});
const Traits = _.get(this.state.appDetailData, 'Traits', []);
let containers = {};
containers = _.get(Workload, 'spec.containers[0]', {});
let { loadingAll } = this.props;
loadingAll = loadingAll || false;
const colorObj = {
Deployed: '#4CAF51',
Staging: '#F44337',
UNKNOWN: '#1890ff',
};
return (
<div>
<div className="breadCrumb">
<Breadcrumb>
<Breadcrumb.Item>
<Link to="/ApplicationList">Home</Link>
</Breadcrumb.Item>
<Breadcrumb.Item>
<Link to="/ApplicationList">Applications</Link>
</Breadcrumb.Item>
<Breadcrumb.Item>ApplicationListDetail</Breadcrumb.Item>
</Breadcrumb>
</div>
<PageContainer>
<Spin spinning={loadingAll}>
<div className="card-container app-detial">
<h2>{_.get(Workload, 'metadata.name')}</h2>
<p style={{ marginBottom: '20px' }}>
{Workload.apiVersion}, Kind={Workload.kind}
</p>
<Tabs>
<TabPane tab="Summary" key="1">
<Row>
<Col span="11">
<div
className="summaryBox1"
onClick={(e) => this.gotoWorkloadDetail(e)}
style={{ background: colorObj[status] || '#1890ff' }}
>
<Row>
<Col span="22">
<p className="title">{Workload.kind}</p>
<p>{Workload.apiVersion}</p>
</Col>
<Col span="2">
<p className="title hasCursor" onClick={this.hrefClick}>
?
</p>
</Col>
</Row>
<p className="title">
Name:<span>{_.get(Workload, 'metadata.name')}</span>
</p>
<p className="title">Settings:</p>
<Row>
{Object.keys(containers).map((currentKey) => {
if (currentKey === 'ports') {
return (
<Fragment key={currentKey}>
<Col span="8">
<p>port</p>
</Col>
<Col span="16">
<p>{_.get(containers[currentKey], '[0].containerPort', '')}</p>
</Col>
</Fragment>
);
// eslint-disable-next-line no-else-return
} else if (currentKey === 'name') {
return <Fragment key={currentKey} />;
// eslint-disable-next-line no-else-return
} else if (currentKey === 'env') {
return (
<Fragment key={currentKey}>
<Col span="8">
<p>env</p>
</Col>
<Col span="16">
<p>{_.get(containers[currentKey], '[0].value', '')}</p>
</Col>
</Fragment>
);
}
return (
<Fragment key={currentKey}>
<Col span="8">
<p>{currentKey}</p>
</Col>
<Col span="16">
<p>{containers[currentKey]}</p>
</Col>
</Fragment>
);
})}
</Row>
</div>
<Popconfirm
title="Are you sure delete this app?"
onConfirm={(e) => this.deleteApp(e)}
onCancel={this.cancel}
okText="Yes"
cancelText="No"
>
<Button danger>Delete</Button>
</Popconfirm>
</Col>
<Col span="1" />
<Col span="10">
{Traits.length ? (
Traits.map((item, index) => {
const traitItem = _.get(item, 'trait', {});
const annotations = _.get(traitItem, 'metadata.annotations', {});
let traitType = 1;
const spec = _.get(traitItem, 'spec', {});
if (traitItem.kind === 'Ingress') {
traitType = 2;
}
return (
<div
className="summaryBox"
onClick={(e) => this.gotoTraitDetail(e, traitItem)}
key={index.toString()}
>
<Row>
<Col span="22">
<p className="title">{traitItem.kind}</p>
<p>{traitItem.apiVersion}</p>
</Col>
<Col span="2">
<p
className="title hasCursor"
onClick={(e) => {
e.stopPropagation();
}}
>
?
</p>
</Col>
</Row>
<Row>
{Object.keys(annotations).map((currentKey3) => {
return (
<Fragment key={currentKey3}>
<Col span="8">
<p>{currentKey3}:</p>
</Col>
<Col span="8">
<p>{annotations[currentKey3]}</p>
</Col>
</Fragment>
);
})}
</Row>
<p className="title">Properties:</p>
<Row>
{traitType === 2 ? (
<Fragment>
<Col span="8">
<p>domain</p>
</Col>
<Col span="16">
<p>{_.get(spec, 'rules[0].host', '')}</p>
</Col>
<Col span="8">
<p>service</p>
</Col>
<Col span="16">
<p>
{_.get(
spec,
'rules[0].http.paths[0].backend.serviceName',
'',
)}
</p>
</Col>
<Col span="8">
<p>port</p>
</Col>
<Col span="16">
<p>
{_.get(
spec,
'rules[0].http.paths[0].backend.servicePort',
'',
)}
</p>
</Col>
</Fragment>
) : (
Object.keys(spec).map((currentKey) => {
return (
<Fragment key={currentKey}>
<Col span="8">
<p>{currentKey}</p>
</Col>
<Col span="16">
<p>{spec[currentKey]}</p>
</Col>
</Fragment>
);
})
)}
</Row>
<div style={{ clear: 'both', height: '32px' }}>
<Popconfirm
title="Are you sure delete this trait?"
onConfirm={(e) => this.deleteTrait(e, item)}
onCancel={this.cancel}
okText="Yes"
cancelText="No"
>
<Button
danger
className="floatRight"
onClick={(e) => {
e.stopPropagation();
}}
>
Delete
</Button>
</Popconfirm>
</div>
</div>
);
})
) : (
<Fragment />
)}
<Tooltip placement="top" title="Attach Trait">
<p
className="hasCursor"
style={{
fontSize: '30px',
display: 'inline-flex',
}}
onClick={this.createTrait}
>
+
</p>
</Tooltip>
</Col>
</Row>
</TabPane>
<TabPane tab="Topology" key="2">
<p>Topology</p>
</TabPane>
</Tabs>
</div>
<Modal
title="Attach a 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}>
Confirm
</Button>,
]}
>
<CreateTraitItem
onRef={(ref) => {
this.child = ref;
}}
availableTraitList={this.state.availableTraitList}
initialValues={{}}
/>
</Modal>
</Spin>
</PageContainer>
</div>
);
}
}
export default TableList;

View File

@@ -0,0 +1,49 @@
.app-detial {
.ant-tabs {
height: 800px;
min-height: 800px;
padding: 10px 20px;
overflow: auto;
background-color: #fff;
.ant-tabs-content-holder {
background: #fff;
}
}
.summaryBox1,
.summaryBox2,
.summaryBox {
clear: both;
margin-bottom: 20px;
padding: 0 10px 10px;
.title {
font-weight: 500;
font-size: 16px;
line-height: 36px;
}
p {
margin: 0;
font-size: 12px;
line-height: 20px;
}
}
.summaryBox1 {
color: #fff;
background: #0097a7;
cursor: pointer;
}
.summaryBox2 {
color: #fff;
background: #92c47c;
}
.summaryBox {
border: 1px solid black;
cursor: pointer;
}
.hasCursor {
font-size: 20px;
cursor: pointer;
}
.floatRight {
float: right;
}
}

View File

@@ -15,14 +15,12 @@ class TableList extends React.Component {
constructor(props) {
super(props);
this.state = {
compDetailData: {},
appDetailData: {},
visible: false,
traitList: [],
availableTraitList: [],
envName: '',
appName: '',
compName: '',
compList: [],
};
}
@@ -31,144 +29,98 @@ class TableList extends React.Component {
}
UNSAFE_componentWillReceiveProps(nextProps) {
if (this.props.compName !== nextProps.compName) {
this.getInitialData(nextProps.compName);
if (this.props.appName !== nextProps.appName) {
this.getInitialData(nextProps.appName);
}
}
getInitialData = async (nextCompName) => {
const appName = _.get(this.props, 'appName', '');
getInitialData = async (nextAppName) => {
let appName = _.get(this.props, 'appName', '');
const envName = _.get(this.props, 'envName', '');
const compList = _.get(this.props, 'compList', []);
let compName = _.get(this.props, 'compName', '');
compName = nextCompName || compName;
this.setState({
compList,
});
if (appName && envName && compName) {
appName = nextAppName || appName;
if (appName && envName) {
this.setState({
envName,
appName,
compName,
});
const res = await this.props.dispatch({
type: 'components/getComponentDetail',
type: 'applist/getAppDetail',
payload: {
envName,
appName,
compName,
},
});
if (res) {
this.setState({
compDetailData: res,
appDetailData: res,
});
const traits = await this.props.dispatch({
type: 'trait/getTraits',
}
const traits = await this.props.dispatch({
type: 'trait/getTraits',
});
if (traits) {
this.setState({
traitList: traits,
});
if (traits) {
const checkedTrait = [];
if (res.traits) {
res.traits.forEach((item) => {
const traitNameObj = _.get(item, 'trait.metadata.annotations', '');
const traitName =
traitNameObj['vela.oam.dev/traitDef'] || traitNameObj['trait.oam.dev/name'];
checkedTrait.push(traitName);
});
}
const newTraits = traits.filter((item) => {
if (checkedTrait.includes(item.name)) {
return false;
}
return true;
});
this.setState({
traitList: newTraits,
});
}
const workloadType = _.get(res, 'workload.kind', '');
if (workloadType) {
this.getAcceptTrait(workloadType.toLowerCase());
}
// if (workloadType && workloadType === '') {
// this.getAcceptTrait('containerized');
// } else if (workloadType && workloadType === 'Deployment') {
// this.getAcceptTrait('deployment');
// }
}
const workloadType = _.get(res, 'Workload.workload.kind', '');
if (workloadType && workloadType === 'ContainerizedWorkload') {
this.getAcceptTrait('containerized');
} else if (workloadType && workloadType === 'Deployment') {
this.getAcceptTrait('deployment');
}
}
};
// getAcceptTrait = (workloadType) => {
// const res = this.state.traitList.filter((item) => {
// if (item.appliesTo) {
// if(item.appliesTo==='*'){
// return true;
// }
// if (item.appliesTo.indexOf(workloadType) !== -1) {
// return true;
// }
// return false;
// }
// return false;
// });
// this.setState(() => ({
// availableTraitList: res,
// }));
// };
getAcceptTrait = () => {
const res = this.state.traitList;
getAcceptTrait = (workloadType) => {
const res = this.state.traitList.filter((item) => {
if (item.appliesTo.indexOf(workloadType) !== -1) {
return true;
}
return false;
});
this.setState(() => ({
availableTraitList: res,
}));
};
deleteComp = async (e) => {
deleteApp = async (e) => {
e.stopPropagation();
const { envName, appName, compName, compList } = this.state;
if (appName && envName && compName) {
const { envName } = this.state;
const { appDetailData } = this.state;
const appName = _.get(appDetailData, 'Workload.workload.metadata.name', '');
if (appName && envName) {
const res = await this.props.dispatch({
type: 'components/deleteComponent',
type: 'applist/deleteApp',
payload: {
appName,
envName,
compName,
},
});
if (res) {
message.success(res);
if (compList.length === 1) {
// 只有一个组件时会同时删除应用
this.props.history.push({
pathname: `/ApplicationList`,
});
} else {
// 删除当前component成功后刷新当前页面
this.props.getInitCompList(compList.length);
}
this.props.history.push({ pathname: '/ApplicationList' });
}
}
};
deleteTrait = async (e, item) => {
e.stopPropagation();
const { appName, envName, compName } = this.state;
const { appName, envName } = this.state;
const traitNameObj = _.get(item, 'trait.metadata.annotations', '');
const traitName = traitNameObj['vela.oam.dev/traitDef'] || traitNameObj['trait.oam.dev/name'];
if (traitName && appName && envName && compName) {
if (traitName && appName && envName) {
const res = await this.props.dispatch({
type: 'trait/deleteOneTrait',
payload: {
envName,
appName,
traitName,
compName,
},
});
if (res) {
message.success(res);
this.getInitialData(compName);
this.getInitialData(2);
}
}
};
@@ -178,16 +130,9 @@ class TableList extends React.Component {
};
createTrait = async () => {
await this.setState(
{
visible: true,
},
() => {
if (this.child) {
this.child.resetFields();
}
},
);
await this.setState({
visible: true,
});
};
handleOk = async () => {
@@ -206,14 +151,13 @@ class TableList extends React.Component {
});
}
});
const { envName, appName, compName } = this.state;
if (envName && appName && compName) {
const { envName, appName } = this.state;
if (envName && appName) {
const res = await this.props.dispatch({
type: 'trait/attachOneTraits',
payload: {
envName,
appName,
compName,
params: submitObj,
},
});
@@ -222,7 +166,7 @@ class TableList extends React.Component {
visible: false,
});
message.success(res);
this.getInitialData(compName);
this.getInitialData(2);
}
}
} else {
@@ -249,16 +193,11 @@ class TableList extends React.Component {
};
render() {
const { compDetailData } = this.state;
const status = _.get(compDetailData, 'status', '');
const Workload = _.get(compDetailData, 'workload', {});
const Traits = _.get(compDetailData, 'traits', []);
const status = _.get(this.state.appDetailData, 'Status', '');
const Workload = _.get(this.state.appDetailData, 'Workload.workload', {});
const Traits = _.get(this.state.appDetailData, 'Traits', []);
let containers = {};
if (_.get(Workload, 'kind', '') === 'Job') {
containers = _.get(Workload, 'spec.template.spec.containers[0]', {});
} else {
containers = _.get(Workload, 'spec.podSpec.containers[0]', {});
}
containers = _.get(Workload, 'spec.containers[0]', {});
let { loadingAll } = this.props;
loadingAll = loadingAll || false;
const colorObj = {
@@ -299,21 +238,6 @@ class TableList extends React.Component {
</p>
<p className="title">Settings:</p>
<Row>
{_.get(Workload, 'kind', '') === 'Job' ? (
<Fragment>
<Col span="8">
<p>count</p>
</Col>
<Col span="16">
<p>
{_.get(Workload, 'spec.completions', '') ||
_.get(Workload, 'spec.parallelism', '')}
</p>
</Col>
</Fragment>
) : (
<Fragment />
)}
{Object.keys(containers).map((currentKey) => {
if (currentKey === 'ports') {
return (
@@ -356,17 +280,8 @@ class TableList extends React.Component {
</Row>
</div>
<Popconfirm
title={
this.state.compList.length === 1 ? (
<div>
<p>There is only one component in the current application,</p>
<p>Do you want to delete the entire application?</p>
</div>
) : (
'Are you sure delete this component?'
)
}
onConfirm={(e) => this.deleteComp(e)}
title="Are you sure delete this app?"
onConfirm={(e) => this.deleteApp(e)}
onCancel={this.cancel}
okText="Yes"
cancelText="No"
@@ -380,7 +295,11 @@ class TableList extends React.Component {
Traits.map((item, index) => {
const traitItem = _.get(item, 'trait', {});
const annotations = _.get(traitItem, 'metadata.annotations', {});
let traitType = 1;
const spec = _.get(traitItem, 'spec', {});
if (traitItem.kind === 'Ingress') {
traitType = 2;
}
return (
<div
className="summaryBox"
@@ -419,33 +338,53 @@ class TableList extends React.Component {
</Row>
<p className="title">Properties:</p>
<Row>
{Object.keys(spec).map((currentKey) => {
if (spec[currentKey].constructor === Object) {
const backend = _.get(spec, `${currentKey}`, {});
return Object.keys(backend).map((currentKey1) => {
return (
<Fragment key={currentKey1}>
<Col span="8">
<p>{currentKey1}</p>
</Col>
<Col span="16">
<p>{backend[currentKey1]}</p>
</Col>
</Fragment>
);
});
}
return (
<Fragment key={currentKey}>
<Col span="8">
<p>{currentKey}</p>
</Col>
<Col span="16">
<p>{spec[currentKey]}</p>
</Col>
</Fragment>
);
})}
{traitType === 2 ? (
<Fragment>
<Col span="8">
<p>domain</p>
</Col>
<Col span="16">
<p>{_.get(spec, 'rules[0].host', '')}</p>
</Col>
<Col span="8">
<p>service</p>
</Col>
<Col span="16">
<p>
{_.get(
spec,
'rules[0].http.paths[0].backend.serviceName',
'',
)}
</p>
</Col>
<Col span="8">
<p>port</p>
</Col>
<Col span="16">
<p>
{_.get(
spec,
'rules[0].http.paths[0].backend.servicePort',
'',
)}
</p>
</Col>
</Fragment>
) : (
Object.keys(spec).map((currentKey) => {
return (
<Fragment key={currentKey}>
<Col span="8">
<p>{currentKey}</p>
</Col>
<Col span="16">
<p>{spec[currentKey]}</p>
</Col>
</Fragment>
);
})
)}
</Row>
<div style={{ clear: 'both', height: '32px' }}>
<Popconfirm

View File

@@ -1,117 +1,73 @@
import React from 'react';
import { Link } from 'umi';
import { Breadcrumb, Button, Menu, Spin, Popconfirm, message } from 'antd';
import { Breadcrumb, Button, Menu, Spin } from 'antd';
import { connect } from 'dva';
import _ from 'lodash';
import './index.less';
import ComponentDetail from '../ComponentDetail/index.jsx';
@connect(({ loading, globalData }) => ({
@connect(({ loading }) => ({
loadingAll: loading.models.applist,
currentEnv: globalData.currentEnv,
}))
class TableList extends React.Component {
class TableList extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
envName: '',
componentName: '',
defaultSelectedKeys: '',
appName: '',
compList: [],
defaultSelectedKeys: 'a1',
};
}
componentDidMount() {
this.getInitData();
}
// shouldComponentUpdate(nextProps) {
// if (nextProps.currentEnv === this.props.currentEnv) {
// return true;
// }
// this.getInitData(nextProps.currentEnv);
// return true;
// }
getInitData = async (changeEnvName) => {
UNSAFE_componentWillMount() {
let appName = '';
let description = '';
let envName = this.props.currentEnv;
let envName = '';
if (this.props.location.state) {
appName = _.get(this.props, 'location.state.appName', '');
description = _.get(this.props, 'location.state.description', '');
envName = _.get(this.props, 'location.state.envName', this.props.currentEnv);
envName = _.get(this.props, 'location.state.envName', '');
sessionStorage.setItem('appName', appName);
sessionStorage.setItem('description', description);
sessionStorage.setItem('envName', envName);
} else {
appName = sessionStorage.getItem('appName');
description = sessionStorage.getItem('description');
envName = sessionStorage.getItem('envName');
}
this.setState({
appName,
envName,
componentName: appName,
});
const res = await this.props.dispatch({
type: 'applist/getAppDetail',
payload: {
envName: changeEnvName || envName,
appName,
},
});
if (res) {
const compData = _.get(res, 'components', []);
const compList = [];
compData.forEach((item) => {
compList.push({
compName: item.name,
});
});
if (appName === 'test33') {
this.setState({
compList,
defaultSelectedKeys: 'a1',
});
} else if (appName === 'test01') {
this.setState({
defaultSelectedKeys: 'c2',
});
} else {
this.setState({
defaultSelectedKeys: 'c3',
});
if (compList.length) {
this.changeComponent({
key: compList[0].compName,
});
}
}
};
}
changeComponent = ({ key }) => {
this.setState({
componentName: key,
defaultSelectedKeys: key,
});
};
deleteApp = async (e) => {
e.stopPropagation();
const { envName } = this.state;
const { appName } = this.state;
if (appName && envName) {
const res = await this.props.dispatch({
type: 'applist/deleteApp',
payload: {
appName,
envName,
},
if (key === 'a1') {
this.setState({
componentName: 'test33',
});
} else if (key === 'c2') {
this.setState({
componentName: 'test01',
});
} else {
this.setState({
componentName: 'testoo',
});
if (res) {
message.success(res);
this.props.history.push({ pathname: '/ApplicationList' });
}
}
};
cancel = (e) => {
e.stopPropagation();
};
render() {
const { envName, componentName, defaultSelectedKeys, appName, compList } = this.state;
const { envName, componentName, defaultSelectedKeys } = this.state;
const { loadingAll } = this.props;
return (
<div style={{ height: '100%' }}>
@@ -123,7 +79,7 @@ class TableList extends React.Component {
<Breadcrumb.Item>
<Link to="/ApplicationList">Applications</Link>
</Breadcrumb.Item>
<Breadcrumb.Item>{appName}</Breadcrumb.Item>
<Breadcrumb.Item>appname</Breadcrumb.Item>
<Breadcrumb.Item>Components</Breadcrumb.Item>
<Breadcrumb.Item>{componentName}</Breadcrumb.Item>
</Breadcrumb>
@@ -135,51 +91,31 @@ class TableList extends React.Component {
mode="inline"
onClick={this.changeComponent}
defaultSelectedKeys={[defaultSelectedKeys]}
selectedKeys={defaultSelectedKeys}
>
<Menu.ItemGroup key="g1" title="Components">
{compList.map((item) => {
return <Menu.Item key={item.compName}>{item.compName}</Menu.Item>;
})}
<Menu.Item key="a1">a1(containerized)</Menu.Item>
<Menu.Item key="c2">c2(deploy)</Menu.Item>
<Menu.Item key="c3">c3(webserver)</Menu.Item>
</Menu.ItemGroup>
</Menu>
<div className="addComp">
<Link
to={{
pathname: `/ApplicationList/${appName}/createComponent`,
state: { appName, envName, isCreate: false },
// pathname: '/ApplicationList/CreateApplication',
pathname: `/ApplicationList/${componentName}/createComponent`,
state: { appName: componentName, envName },
}}
>
add a new comp
</Link>
</div>
</div>
{defaultSelectedKeys ? (
<div className="right">
<div className="btn">
<Popconfirm
title="Are you sure delete this app?"
placement="bottom"
onConfirm={(e) => this.deleteApp(e)}
onCancel={this.cancel}
okText="Yes"
cancelText="No"
>
<Button type="primary">Delete App</Button>
</Popconfirm>
</div>
<ComponentDetail
appName={appName}
compName={componentName}
envName={envName}
getInitCompList={this.getInitData}
compList={compList}
history={this.props.history}
/>
<div className="right">
<div style={{ margin: '10px', float: 'right' }}>
<Button type="primary">Delete App</Button>
</div>
) : (
<div style={{ width: '100%', height: '100%', background: '#FFFFFF' }} />
)}
<ComponentDetail appName={componentName} envName={envName} />
</div>
</div>
</Spin>
</div>

View File

@@ -1,12 +1,6 @@
.ant-spin-nested-loading {
height: 100%;
}
.ant-spin-container {
height: 100%;
}
.appComponent {
display: flex;
height: 100%;
height: calc(100% - 46px);
.left {
width: 200px;
background: #fff;
@@ -30,19 +24,12 @@
text-decoration: underline;
background-color: #fff;
border-top: 1px solid #efefef;
border-right: 1px solid #efefef;
border-bottom: 1px solid #efefef;
cursor: pointer;
}
}
.right {
position: relative;
flex: 1;
.btn {
position: absolute;
top: 10px;
right: 10px;
z-index: 8;
}
// clear: both;
}
}

View File

@@ -0,0 +1,606 @@
import React, { Fragment } from 'react';
import { PageContainer } from '@ant-design/pro-layout';
import './index.less';
import { Button, Row, Col, Form, Input, Select, Steps, message, Breadcrumb } from 'antd';
import { connect } from 'dva';
import { Link } from 'umi';
import _ from 'lodash';
import CreateTraitItem from '../createTrait/index.jsx';
const { Option } = Select;
const { Step } = Steps;
const layout = {
labelCol: {
span: 8,
},
wrapperCol: {
span: 16,
},
};
@connect(({ loading, globalData }) => ({
loadingAll: loading.models.workload,
currentEnv: globalData.currentEnv,
}))
class TableList extends React.Component {
formRefStep1 = React.createRef();
formRefStep2All = React.createRef();
constructor(props) {
super(props);
this.state = {
current: 0,
isShowMore: false,
traitNum: [
{
refname: null,
initialData: {},
uniq: new Date().valueOf(),
},
],
traitList: [],
availableTraitList: [],
workloadList: [],
workloadSettings: [],
step1SubmitObj: {},
step1InitialValues: {
workload_type: '',
},
step1Settings: [],
};
}
componentDidMount() {
this.getInitalData();
}
getInitalData = async () => {
const res = await this.props.dispatch({
type: 'workload/getWorkload',
});
const traits = await this.props.dispatch({
type: 'trait/getTraits',
});
this.setState({
traitList: traits,
});
if (Array.isArray(res) && res.length) {
this.setState(
() => ({
workloadList: res,
}),
() => {
if (this.state.current === 0) {
let WorkloadType = '';
if (this.props.location.state) {
WorkloadType = _.get(this.props, 'location.state.WorkloadType', '');
sessionStorage.setItem('WorkloadType', WorkloadType);
} else {
WorkloadType = sessionStorage.getItem('WorkloadType');
}
this.formRefStep1.current.setFieldsValue({
workload_type: WorkloadType || this.state.workloadList[0].name,
});
this.workloadTypeChange(this.state.workloadList[0].name);
}
},
);
}
};
onFinishStep1 = (values) => {
this.setState({
current: 1,
step1InitialValues: values,
isShowMore: false,
});
};
onFinishStep2 = async () => {
const asyncValidateArray = [];
this.state.traitNum.forEach((item) => {
asyncValidateArray.push(item.refname.validateFields());
});
await Promise.all(asyncValidateArray);
const newTraitNum = this.state.traitNum.map((item) => {
// eslint-disable-next-line no-param-reassign
item.initialData = item.refname.getSelectValue();
return item;
});
// 进行trait数据整理便于第三步展示
this.setState(() => ({
traitNum: newTraitNum,
current: 2,
}));
};
gotoStep2 = () => {
this.setState({
current: 1,
isShowMore: false,
});
};
gotoStep1 = () => {
this.setState({
current: 0,
});
};
changeShowMore = () => {
this.setState({
isShowMore: true,
});
};
addMore = (e) => {
e.preventDefault();
this.setState((prev) => ({
traitNum: prev.traitNum.concat([
{
refname: null,
initialData: {},
uniq: new Date().valueOf(),
},
]),
}));
};
createApp = async () => {
const { traitNum } = this.state;
const { step1SubmitObj } = this.state;
if (step1SubmitObj.env_name !== this.props.currentEnv) {
step1SubmitObj.env_name = this.props.currentEnv;
}
const submitObj = _.cloneDeep(step1SubmitObj);
const { workload_name: workloadName } = step1SubmitObj;
submitObj.flags.push({
name: 'name',
value: workloadName.toString(),
});
// 处理数据为提交的格式
if (traitNum.length) {
const { env_name: envName } = step1SubmitObj;
const step2SubmitObj = [];
traitNum.forEach(({ initialData }) => {
if (initialData.name) {
const initialObj = {
name: initialData.name,
env_name: envName,
workload_name: workloadName,
flags: [],
};
Object.keys(initialData).forEach((key) => {
if (key !== 'name' && initialData[key]) {
initialObj.flags.push({
name: key,
value: initialData[key].toString(),
});
}
});
step2SubmitObj.push(initialObj);
}
});
submitObj.traits = step2SubmitObj;
}
const res = await this.props.dispatch({
type: 'workload/createWorkload',
payload: {
params: submitObj,
},
});
if (res) {
message.success(res);
this.props.history.push({
pathname: '/ApplicationList',
});
}
};
createWorkload = async () => {
await this.formRefStep1.current.validateFields();
const currentData = this.formRefStep1.current.getFieldsValue();
const submitObj = {
env_name: this.props.currentEnv,
workload_type: currentData.workload_type,
workload_name: currentData.workload_name,
flags: [],
};
Object.keys(currentData).forEach((key) => {
if (key !== 'workload_name' && key !== 'workload_type' && currentData[key]) {
submitObj.flags.push({
name: key,
value: currentData[key].toString(),
});
}
});
this.setState({
current: 1,
step1InitialValues: currentData,
step1Settings: submitObj.flags,
step1SubmitObj: submitObj,
});
this.getAcceptTrait(currentData.workload_type);
};
workloadTypeChange = (value) => {
const content = this.formRefStep1.current.getFieldsValue();
this.formRefStep1.current.resetFields();
const initialObj = {
workload_type: content.workload_type,
workload_name: content.workload_name,
};
this.formRefStep1.current.setFieldsValue(initialObj);
const currentWorkloadSetting = this.state.workloadList.filter((item) => {
return item.name === value;
});
if (currentWorkloadSetting.length) {
this.setState(
{
workloadSettings: currentWorkloadSetting[0].parameters,
},
() => {
this.state.workloadSettings.forEach((item) => {
if (item.default) {
initialObj[item.name] = item.default;
}
});
this.formRefStep1.current.setFieldsValue(initialObj);
},
);
}
this.setState({
traitNum: [
{
refname: null,
initialData: {},
uniq: new Date().valueOf(),
},
],
});
};
getAcceptTrait = (workloadType) => {
const res = this.state.traitList.filter((item) => {
if (item.appliesTo.indexOf(workloadType) !== -1) {
return true;
}
return false;
});
this.setState(() => ({
availableTraitList: res,
}));
};
deleteTraitItem = (uniq) => {
// 删除的时候不要依据数组的index删除,要一个唯一性的值
this.state.traitNum = this.state.traitNum.filter((item) => {
return item.uniq !== uniq;
});
this.setState((prev) => ({
traitNum: prev.traitNum,
}));
};
render() {
const { current, step1InitialValues, traitNum, workloadSettings } = this.state;
let { workloadList } = this.state;
workloadList = Array.isArray(workloadList) ? workloadList : [];
let currentDetail;
if (current === 0) {
currentDetail = (
<div>
<div className="minBox">
<Form
initialValues={step1InitialValues}
labelAlign="left"
{...layout}
ref={this.formRefStep1}
name="control-ref"
onFinish={this.onFinishStep1}
style={{ width: '60%' }}
>
<div style={{ padding: '16px 48px 0px 16px' }}>
<Form.Item
name="workload_name"
label="Name"
rules={[
{
pattern: /^[a-z0-9-_]+$/,
message:
'Names can only use digits(0-9),lowercase letters(a-z),and dashes(-),Underline.',
},
{
required: true,
message: 'Please input name!',
},
]}
>
<Input />
</Form.Item>
<Form.Item
name="workload_type"
label="Workload Type"
rules={[
{
required: true,
message: 'Please select Workload Type!',
},
]}
>
<Select
placeholder="Select a Workload Type"
allowClear
onChange={this.workloadTypeChange}
>
{workloadList.length ? (
workloadList.map((item) => {
return (
<Option value={item.name} key={item.name}>
{item.name}
</Option>
);
})
) : (
<></>
)}
</Select>
</Form.Item>
</div>
<Form.Item
label="Settings"
style={{ background: 'rgba(0, 0, 0, 0.04)', paddingLeft: '16px' }}
/>
<div className="relativeBox">
<p className="hasMore">?</p>
{Array.isArray(workloadSettings) && workloadSettings.length ? (
workloadSettings.map((item) => {
if (item.name === 'name') {
return <Fragment key={item.name} />;
}
return item.type === 4 ? (
<Form.Item
name={item.name}
label={item.name}
key={item.name}
rules={[
{
required: item.required,
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,
message: `Please input ${item.name}!`,
},
{ pattern: /^[^\s]*$/, message: 'Spaces are not allowed!' },
]}
>
<Input />
</Form.Item>
);
})
) : (
<></>
)}
</div>
<div className="buttonBox">
<Button type="primary" className="floatRightGap" onClick={this.createWorkload}>
Next
</Button>
<Link to="/ApplicationList">
<Button className="floatRightGap">Cancle</Button>
</Link>
</div>
</Form>
</div>
</div>
);
} else if (current === 1) {
currentDetail = (
<div>
<div className="minBox" style={{ width: '60%' }}>
<div style={{ padding: '0px 48px 0px 16px', width: '60%' }}>
<p style={{ fontSize: '18px', lineHeight: '32px' }}>
Name:<span>{step1InitialValues.workload_name}</span>
</p>
</div>
<div style={{ border: '1px solid #eee', padding: '16px 48px 16px 16px' }}>
<p className="title">{step1InitialValues.workload_type}</p>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<span>apps/v1</span>
<span
style={{
color: '#1890ff',
cursor: 'pointer',
display: this.state.isShowMore ? 'none' : 'black',
}}
onClick={this.changeShowMore}
>
more...
</span>
</div>
{this.state.isShowMore ? (
<div>
<p className="title" style={{ marginTop: '16px' }}>
Settings:
</p>
<Row>
{this.state.step1Settings.map((item) => {
return (
<Fragment key={item.name}>
<Col span="8">
<p>{item.name}:</p>
</Col>
<Col span="16">
<p>{item.value}</p>
</Col>
</Fragment>
);
})}
</Row>
</div>
) : (
''
)}
</div>
<div ref={this.formRefStep2All}>
{traitNum.map((item) => {
return (
<CreateTraitItem
onRef={(ref) => {
// eslint-disable-next-line no-param-reassign
item.refname = ref;
}}
key={item.uniq.toString()}
availableTraitList={this.state.availableTraitList}
uniq={item.uniq}
initialValues={item.initialData}
deleteTraitItem={this.deleteTraitItem}
/>
);
})}
</div>
<button style={{ marginTop: '16px' }} onClick={this.addMore} type="button">
Add More...
</button>
<div className="buttonBox">
<Button type="primary" className="floatRight" onClick={this.onFinishStep2}>
Next
</Button>
<Button className="floatRightGap" onClick={this.gotoStep1}>
Back
</Button>
</div>
</div>
</div>
);
} else {
currentDetail = (
<div>
<div className="minBox">
<p>
Name:<span>{step1InitialValues.workload_name}</span>
</p>
<Row>
<Col span="11">
<div className="summaryBox1">
<Row>
<Col span="22">
<p className="title">{step1InitialValues.workload_type}</p>
<p>apps/v1</p>
</Col>
</Row>
<p className="title hasMargin">Settings:</p>
<Row>
{this.state.step1Settings.map((item) => {
return (
<Fragment key={item.name}>
<Col span="8">
<p>{item.name}:</p>
</Col>
<Col span="16">
<p>{item.value}</p>
</Col>
</Fragment>
);
})}
</Row>
</div>
</Col>
<Col span="1" />
<Col span="10">
{traitNum.map(({ initialData }, index) => {
if (initialData.name) {
return (
<div className="summaryBox" key={index.toString()}>
<Row>
<Col span="22">
<p className="title">{initialData.name}</p>
<p>core.oam.dev/v1alpha2</p>
</Col>
</Row>
<p className="title hasMargin">Properties:</p>
<Row>
{Object.keys(initialData).map((currentKey) => {
if (currentKey !== 'name') {
return (
<Fragment key={currentKey}>
<Col span="8">
<p>{currentKey}:</p>
</Col>
<Col span="16">
<p>{initialData[currentKey]}</p>
</Col>
</Fragment>
);
}
return <Fragment key={currentKey} />;
})}
</Row>
</div>
);
}
return <Fragment key={index.toString()} />;
})}
</Col>
</Row>
</div>
<div className="buttonBox">
<Button
type="primary"
className="floatRight"
onClick={() => {
this.createApp();
}}
>
Confirm
</Button>
<Button className="floatRightGap" onClick={this.gotoStep2}>
Back
</Button>
</div>
</div>
);
}
return (
<div>
<div className="breadCrumb">
<Breadcrumb>
<Breadcrumb.Item>
<Link to="/ApplicationList">Home</Link>
</Breadcrumb.Item>
<Breadcrumb.Item>
<Link to="/ApplicationList">Applications</Link>
</Breadcrumb.Item>
<Breadcrumb.Item>CreateApplication</Breadcrumb.Item>
</Breadcrumb>
</div>
<PageContainer>
<div className="create-container create-app">
<Steps current={current}>
<Step title="Step 1" description="Choose Workload" />
<Step title="Step 2" description="Attach Trait" />
<Step title="Step 3" description="Review and confirm" />
</Steps>
{currentDetail}
</div>
</PageContainer>
</div>
);
}
}
export default TableList;

View File

@@ -0,0 +1,66 @@
.create-container {
padding: 10px;
background: #fff;
}
.create-app {
.minBox {
margin: 20px 10px;
padding: 10px;
border: 1px solid #eee;
.title {
font-size: 16px;
line-height: 36px;
}
}
.buttonBox {
clear: both;
height: 42px;
margin: 0 10px;
padding: 10px;
}
.floatRight {
float: right;
}
.floatRightGap {
float: right;
margin-right: 16px;
}
.relativeBox {
position: relative;
padding: 0 48px 0 16px;
.hasMore {
position: absolute;
top: 0;
right: 16px;
padding: 4px;
color: rgb(24, 144, 255);
font-size: 16px;
cursor: pointer;
}
}
.summaryBox1,
.summaryBox2,
.summaryBox {
clear: both;
margin-bottom: 20px;
padding: 0 10px 10px;
p {
margin: 0;
font-size: 12px;
line-height: 20px;
}
}
.summaryBox1 {
color: #fff;
background: rgb(24, 144, 255);
}
.summaryBox2 {
background: yellow;
}
.summaryBox {
border: 1px solid black;
}
.hasMargin {
padding: 8px 0;
}
}

View File

@@ -46,12 +46,11 @@ class TableList extends React.Component {
workloadSettings: [],
step1SubmitObj: {},
step1InitialValues: {
workloadType: '',
workload_type: '',
},
step1Settings: [],
appName: '',
envName: '',
isCreate: '',
};
}
@@ -62,23 +61,18 @@ class TableList extends React.Component {
getInitalData = async () => {
let appName = '';
let envName = '';
let isCreate = '';
if (this.props.location.state) {
appName = _.get(this.props, 'location.state.appName', '');
envName = _.get(this.props, 'location.state.envName', '');
isCreate = _.get(this.props, 'location.state.isCreate', false);
sessionStorage.setItem('appName', appName);
sessionStorage.setItem('envName', envName);
sessionStorage.setItem('isCreate', isCreate);
} else {
appName = sessionStorage.getItem('appName');
envName = sessionStorage.getItem('envName');
isCreate = sessionStorage.getItem('isCreate');
}
this.setState({
appName,
envName,
isCreate,
});
const res = await this.props.dispatch({
type: 'workload/getWorkload',
@@ -104,9 +98,9 @@ class TableList extends React.Component {
WorkloadType = sessionStorage.getItem('WorkloadType');
}
this.formRefStep1.current.setFieldsValue({
workloadType: WorkloadType || this.state.workloadList[0].name,
workload_type: WorkloadType || this.state.workloadList[0].name,
});
this.workloadTypeChange(WorkloadType || this.state.workloadList[0].name);
this.workloadTypeChange(this.state.workloadList[0].name);
}
},
);
@@ -153,9 +147,8 @@ class TableList extends React.Component {
};
changeShowMore = () => {
const isMore = this.state.isShowMore;
this.setState({
isShowMore: !isMore,
isShowMore: true,
});
};
@@ -173,31 +166,27 @@ class TableList extends React.Component {
};
createApp = async () => {
const { traitNum, isCreate } = this.state;
const { traitNum } = this.state;
const { step1SubmitObj } = this.state;
if (isCreate === true || isCreate === 'true') {
step1SubmitObj.envName = this.props.currentEnv;
} else {
step1SubmitObj.envName = this.state.envName;
if (step1SubmitObj.env_name !== this.props.currentEnv) {
step1SubmitObj.env_name = this.props.currentEnv;
}
step1SubmitObj.appName = this.state.appName;
const submitObj = _.cloneDeep(step1SubmitObj);
const { workloadName, appName } = step1SubmitObj;
const { workload_name: workloadName } = step1SubmitObj;
submitObj.flags.push({
name: 'name',
value: workloadName.toString(),
});
// 处理数据为提交的格式
if (traitNum.length) {
const { envName } = step1SubmitObj;
const { env_name: envName } = step1SubmitObj;
const step2SubmitObj = [];
traitNum.forEach(({ initialData }) => {
if (initialData.name) {
const initialObj = {
name: initialData.name,
envName,
workloadName,
appName,
env_name: envName,
workload_name: workloadName,
flags: [],
};
Object.keys(initialData).forEach((key) => {
@@ -221,9 +210,10 @@ class TableList extends React.Component {
});
if (res) {
message.success(res);
const { appName, envName } = this.state;
this.props.history.push({
pathname: `/ApplicationList/${appName}/Components`,
state: { appName, envName: step1SubmitObj.envName },
state: { appName, envName },
});
}
};
@@ -232,13 +222,13 @@ class TableList extends React.Component {
await this.formRefStep1.current.validateFields();
const currentData = this.formRefStep1.current.getFieldsValue();
const submitObj = {
envName: this.props.currentEnv,
workloadType: currentData.workloadType,
workloadName: currentData.workloadName,
env_name: this.props.currentEnv,
workload_type: currentData.workload_type,
workload_name: currentData.workload_name,
flags: [],
};
Object.keys(currentData).forEach((key) => {
if (key !== 'workloadName' && key !== 'workloadType' && currentData[key]) {
if (key !== 'workload_name' && key !== 'workload_type' && currentData[key]) {
submitObj.flags.push({
name: key,
value: currentData[key].toString(),
@@ -251,15 +241,15 @@ class TableList extends React.Component {
step1Settings: submitObj.flags,
step1SubmitObj: submitObj,
});
this.getAcceptTrait(currentData.workloadType);
this.getAcceptTrait(currentData.workload_type);
};
workloadTypeChange = (value) => {
const content = this.formRefStep1.current.getFieldsValue();
this.formRefStep1.current.resetFields();
const initialObj = {
workloadType: content.workloadType,
workloadName: content.workloadName,
workload_type: content.workload_type,
workload_name: content.workload_name,
};
this.formRefStep1.current.setFieldsValue(initialObj);
const currentWorkloadSetting = this.state.workloadList.filter((item) => {
@@ -293,14 +283,8 @@ class TableList extends React.Component {
getAcceptTrait = (workloadType) => {
const res = this.state.traitList.filter((item) => {
if (item.appliesTo) {
if (item.appliesTo === '*') {
return true;
}
if (item.appliesTo.indexOf(workloadType) !== -1) {
return true;
}
return false;
if (item.appliesTo.indexOf(workloadType) !== -1) {
return true;
}
return false;
});
@@ -321,7 +305,7 @@ class TableList extends React.Component {
render() {
const { appName, envName } = this.state;
const { current, step1InitialValues, traitNum, workloadSettings, isCreate } = this.state;
const { current, step1InitialValues, traitNum, workloadSettings } = this.state;
let { workloadList } = this.state;
workloadList = Array.isArray(workloadList) ? workloadList : [];
let currentDetail;
@@ -340,7 +324,7 @@ class TableList extends React.Component {
>
<div style={{ padding: '16px 48px 0px 16px' }}>
<Form.Item
name="workloadName"
name="workload_name"
label="Name"
rules={[
{
@@ -357,7 +341,7 @@ class TableList extends React.Component {
<Input />
</Form.Item>
<Form.Item
name="workloadType"
name="workload_type"
label="Workload Type"
rules={[
{
@@ -387,11 +371,7 @@ class TableList extends React.Component {
</div>
<Form.Item
label="Settings"
style={{
background: 'rgba(0, 0, 0, 0.04)',
paddingLeft: '16px',
marginLeft: '-10px',
}}
style={{ background: 'rgba(0, 0, 0, 0.04)', paddingLeft: '16px' }}
/>
<div className="relativeBox">
<p className="hasMore">?</p>
@@ -440,24 +420,14 @@ class TableList extends React.Component {
<Button type="primary" className="floatRightGap" onClick={this.createWorkload}>
Next
</Button>
{isCreate === true || isCreate === 'true' ? (
<Link
to={{
pathname: `/ApplicationList`,
}}
>
<Button className="floatRightGap">Cancle</Button>
</Link>
) : (
<Link
to={{
pathname: `/ApplicationList/${appName}/Components`,
state: { appName, envName },
}}
>
<Button className="floatRightGap">Cancle</Button>
</Link>
)}
<Link
to={{
pathname: `/ApplicationList/${appName}/Components`,
state: { appName, envName },
}}
>
<Button className="floatRightGap">Cancle</Button>
</Link>
</div>
</Form>
</div>
@@ -469,22 +439,22 @@ class TableList extends React.Component {
<div className="minBox" style={{ width: '60%' }}>
<div style={{ padding: '0px 48px 0px 16px', width: '60%' }}>
<p style={{ fontSize: '18px', lineHeight: '32px' }}>
Name:<span>{step1InitialValues.workloadName}</span>
Name:<span>{step1InitialValues.workload_name}</span>
</p>
</div>
<div style={{ border: '1px solid #eee', padding: '16px 48px 16px 16px' }}>
<p className="title">{step1InitialValues.workloadType}</p>
<p className="title">{step1InitialValues.workload_type}</p>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<span>apps/v1</span>
<span
style={{
color: '#1890ff',
cursor: 'pointer',
// display: this.state.isShowMore ? 'none' : 'black',
display: this.state.isShowMore ? 'none' : 'black',
}}
onClick={this.changeShowMore}
>
{this.state.isShowMore ? 'close...' : 'more...'}
more...
</span>
</div>
{this.state.isShowMore ? (
@@ -547,14 +517,14 @@ class TableList extends React.Component {
<div>
<div className="minBox">
<p>
Name:<span>{step1InitialValues.workloadName}</span>
Name:<span>{step1InitialValues.workload_name}</span>
</p>
<Row>
<Col span="11">
<div className="summaryBox1">
<Row>
<Col span="22">
<p className="title">{step1InitialValues.workloadType}</p>
<p className="title">{step1InitialValues.workload_type}</p>
<p>apps/v1</p>
</Col>
</Row>
@@ -641,18 +611,15 @@ class TableList extends React.Component {
<Link to="/ApplicationList">Applications</Link>
</Breadcrumb.Item>
<Breadcrumb.Item>
{isCreate === true || isCreate === 'true' ? (
<span>{appName}</span>
) : (
<Link
to={{
pathname: `/ApplicationList/${appName}/Components`,
state: { appName, envName },
}}
>
{appName}
</Link>
)}
<Link
to={{
pathname: `/ApplicationList/${appName}/Components`,
state: { appName, envName },
}}
>
{' '}
{appName}
</Link>
</Breadcrumb.Item>
<Breadcrumb.Item>createComponent</Breadcrumb.Item>
</Breadcrumb>

View File

@@ -99,7 +99,7 @@ export default class CreateTraitItem extends React.PureComponent {
})}
</Select>
</Form.Item>
<Form.Item label="Properties" style={{ marginLeft: '-10px' }} />
<Form.Item label="Properties" />
</div>
<div className="relativeBox">
{this.state.parameters ? (

View File

@@ -1,6 +1,7 @@
import React from 'react';
import { PageContainer } from '@ant-design/pro-layout';
import { Button, Form, Spin, Breadcrumb, Modal, Input, Table, Space, message } from 'antd';
import { BranchesOutlined, ApartmentOutlined } from '@ant-design/icons';
import { Button, Card, Row, Col, Form, Spin, Empty, Breadcrumb, Modal, Input } from 'antd';
import { connect } from 'dva';
import moment from 'moment';
import './index.less';
@@ -23,55 +24,6 @@ const layout = {
class TableList extends React.Component {
formRef = React.createRef();
columns = [
{
title: 'Name',
dataIndex: 'name',
key: 'name',
render: (text, record) => {
return (
<Link
to={{
pathname: `/ApplicationList/${record.name}/Components`,
state: { appName: record.name, envName: this.props.currentEnv },
}}
>
{text}
</Link>
);
},
},
{
title: 'Status',
dataIndex: 'status',
key: 'status',
render: (text) => {
return text;
},
},
{
title: 'Created Time',
dataIndex: 'createdTime',
key: 'createdTime',
render: (text) => {
return this.getFormatDate(text);
},
},
{
title: 'Actions',
dataIndex: 'Actions',
key: 'Actions',
render: (text, record) => {
return (
<Space>
<Button onClick={() => this.goToDetail(record)}>Details</Button>
<Button onClick={() => this.deleteApp(record)}>Delete</Button>
</Space>
);
},
},
];
constructor(props) {
super(props);
this.state = {
@@ -80,7 +32,15 @@ class TableList extends React.Component {
}
componentDidMount() {
this.getInitData();
const { currentEnv } = this.props;
if (currentEnv) {
this.props.dispatch({
type: 'applist/getList',
payload: {
url: `/api/envs/${currentEnv}/apps/`,
},
});
}
}
shouldComponentUpdate(nextProps) {
@@ -96,43 +56,6 @@ class TableList extends React.Component {
return true;
}
getInitData = () => {
const { currentEnv } = this.props;
if (currentEnv) {
this.props.dispatch({
type: 'applist/getList',
payload: {
url: `/api/envs/${currentEnv}/apps/`,
},
});
}
};
goToDetail = (record) => {
this.props.history.push({
pathname: `/ApplicationList/${record.name}/Components`,
state: { appName: record.name, envName: this.props.currentEnv },
});
};
deleteApp = async (record) => {
const appName = record.name;
const envName = this.props.currentEnv;
if (appName && envName) {
const res = await this.props.dispatch({
type: 'applist/deleteApp',
payload: {
appName,
envName,
},
});
if (res) {
message.success(res);
this.getInitData();
}
}
};
showModal = () => {
this.setState({
visible: true,
@@ -140,11 +63,8 @@ class TableList extends React.Component {
};
handleOk = async () => {
const submitData = await this.formRef.current.validateFields();
this.props.history.push({
pathname: `/ApplicationList/${submitData.appName}/createComponent`,
state: { ...submitData, isCreate: true },
});
await this.formRef.current.validateFields();
// const submitData = await this.formRef.current.validateFields();
};
handleCancel = () => {
@@ -171,8 +91,14 @@ class TableList extends React.Component {
render() {
let { loadingAll, returnObj } = this.props;
returnObj = returnObj || [];
const { currentEnv } = this.props;
loadingAll = loadingAll || false;
returnObj = returnObj || [];
const colorObj = {
Deployed: 'first1',
Staging: 'first2',
UNKNOWN: 'first3',
};
return (
<div>
<div className="breadCrumb">
@@ -188,17 +114,74 @@ class TableList extends React.Component {
<div className="applist">
<Form name="horizontal_login" layout="inline" onFinish={this.onFinish}>
<Form.Item>
<Button onClick={this.showModal} type="primary" style={{ marginBottom: 16 }}>
create
</Button>
<Link to="/ApplicationList/CreateApplication">
<Button onClick={this.handleAdd} type="primary" style={{ marginBottom: 16 }}>
create
</Button>
</Link>
</Form.Item>
</Form>
</div>
<Table
rowKey={(record) => record.name + Math.random(1, 100)}
columns={this.columns}
dataSource={returnObj}
/>
<Row gutter={16}>
{Array.isArray(returnObj) && returnObj.length ? (
returnObj.map((item, index) => {
const { traits = [] } = item;
return (
<Col span={6} onClick={this.gotoDetail} key={index.toString()}>
<Link
to={{
pathname: '/ApplicationList/ApplicationListDetail',
state: { appName: item.name, envName: currentEnv },
}}
>
<Card
title={item.name}
bordered={false}
extra={this.getFormatDate(item.created)}
>
<div className="cardContent">
<div
className="box2"
style={{ height: this.getHeight(traits.length) }}
/>
<div className="box1">
{traits.length ? (
<div className="box3" style={{ width: '30px' }} />
) : (
''
)}
<div
className={['hasPadding', colorObj[item.status] || 'first3'].join(
' ',
)}
>
<ApartmentOutlined style={{ marginRight: '4px' }} />
{item.workload}
</div>
</div>
{traits.map((item1, index1) => {
return (
<div className="box1" key={index1.toString()}>
<div className="box3" style={{ width: '50px' }} />
<div className="other hasPadding">
<BranchesOutlined style={{ marginRight: '4px' }} />
{item1}
</div>
</div>
);
})}
</div>
</Card>
</Link>
</Col>
);
})
) : (
<div style={{ width: '100%', height: '80%' }}>
<Empty />
</div>
)}
</Row>
</Spin>
<Modal
title="Create Application"
@@ -213,7 +196,7 @@ class TableList extends React.Component {
>
<Form {...layout} ref={this.formRef} name="control-ref" labelAlign="left">
<Form.Item
name="appName"
name="name"
label="Name"
rules={[
{

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