mirror of
https://github.com/kubevela/kubevela.git
synced 2026-03-02 09:40:51 +00:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
17ac119f9b | ||
|
|
829b813b1a | ||
|
|
bce8bfd40f | ||
|
|
66855265c8 | ||
|
|
63f52ea556 | ||
|
|
fa37bf0284 |
3
.github/workflows/e2e.yml
vendored
3
.github/workflows/e2e.yml
vendored
@@ -34,9 +34,6 @@ jobs:
|
||||
with:
|
||||
version: "v0.7.0"
|
||||
|
||||
- name: Load Image to kind cluster
|
||||
run: make kind-load
|
||||
|
||||
- name: install Kubebuilder
|
||||
uses: RyanSiu1995/kubebuilder-action@v1
|
||||
|
||||
|
||||
8
.github/workflows/go.yml
vendored
8
.github/workflows/go.yml
vendored
@@ -35,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
|
||||
|
||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -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,13 +36,10 @@ config/crd/bases
|
||||
tmp/
|
||||
|
||||
cmd/vela/fake/source.go
|
||||
cmd/vela/fake/chart_source.go
|
||||
charts/vela-core/crds/_.yaml
|
||||
|
||||
.vela/
|
||||
|
||||
# Dashboard
|
||||
node_modules/
|
||||
dashboard/node_modules/
|
||||
.eslintcache
|
||||
dashboard/dist/
|
||||
dashboard/package-lock.json
|
||||
|
||||
@@ -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).
|
||||
@@ -11,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
|
||||
@@ -32,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
|
||||
@@ -70,7 +50,7 @@ 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 comp deploy mycomp -t webservice --image crccheck/hello-world --port 8000
|
||||
$ vela comp run mycomp -t webservice --image crccheck/hello-world --port 8000
|
||||
Creating AppConfig appcomp
|
||||
SUCCEED
|
||||
```
|
||||
@@ -89,7 +69,7 @@ Succeeded!
|
||||
$ vela comp status abc
|
||||
Showing status of Component abc deployed in Environment t2
|
||||
Component Status:
|
||||
Name: abc PodSpecWorkload(type) UNKNOWN APIVersion standard.oam.dev/v1alpha1 Kind PodSpecWorkload workload is unknown for HealthScope
|
||||
Name: abc Containerized(type) UNKNOWN APIVersion standard.oam.dev/v1alpha1 Kind Containerized workload is unknown for HealthScope
|
||||
Traits
|
||||
└─Trait/route
|
||||
|
||||
@@ -118,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
|
||||
```
|
||||
|
||||
192
DESIGN.md
192
DESIGN.md
@@ -1,192 +0,0 @@
|
||||
# KubeVela Design
|
||||
|
||||
This document is the detailed design and architecture of the KubeVela being built in this repository.
|
||||
|
||||
> All the diagram in this documentation could be found in [this slides](https://docs.google.com/presentation/d/1Y3gnKrd7fUZGgee7Ia9vBsRIYhcZLQwMUCDkk1RJvQc/edit?usp=sharing).
|
||||
|
||||
## Overview
|
||||
|
||||
KubeVela is a simple, complete, but highly extensible cloud native application platform based on Kubernetes and Open Application Model (OAM). KubeVela intends to bring application-centric experience to its end users and democratize building cloud native application platforms for platform engineers.
|
||||
|
||||
## User Stories
|
||||
|
||||
As a end user (e.g. application developers, operators etc) of the platform, I only want to focus on coding my business logic and ship them to various environments at ease. Let's say:
|
||||
- Here's my source code.
|
||||
- Here's my application configuration (described in end user PoV).
|
||||
- Deploy it in test environment.
|
||||
- Deploy it in production environment.
|
||||
- Monitoring, debugging, rollout/rollback the application.
|
||||
- Dockerfile is fine, but please keep it simple.
|
||||
|
||||
As a platform engineer, I want to build a easy-to-use platform for my end users. In detail, the platform should be:
|
||||
- Heroku-like (_in terms of both user experience and functionality_).
|
||||
- and I prefer to build my own version with OSS tools, particularly, with Kubernetes (for obvious reason).
|
||||
- Easy to build.
|
||||
- I am too busy to reinvent any wheel, I want to reuse every capability in Kubernetes community as possible, with minimal effort. Writing some simple CRD and controllers is fine, but please, just the simple ones like copy-paste.
|
||||
- Powerful and highly extensible.
|
||||
- I don't want to lock my users with restricted abstractions and capabilities like traditional PaaS or FaaS/Serverless. I love Kubernetes and what it has enabled. So in terms of capability, I hope my platform is fully open and has unlimited possibilities like Kubernetes itself, rather than another opinionated close system like traditional PaaS.
|
||||
|
||||
|
||||
## Core Principles
|
||||
|
||||
In nutshell, the principles for KubeVela project are:
|
||||
|
||||
- For end users, it out-of-the-box ships a fully featured PaaS-like experience, nothing special.
|
||||
- For platform builders, it works like a special Kubernetes "distro" or extensible PaaS core that could be used to build something more complex. It allows platform builders to ship any existing capabilities in cloud native ecosystem to end users with minimal effort, or develop a new capability at ease in a standardized and Kubernetes-native approach.
|
||||
|
||||
## Design Details
|
||||
|
||||
### 1. Application Centric
|
||||
|
||||
The design of KubeVela intends to make users think in terms of application, not containers or infrastructure.
|
||||
|
||||
Lacking application context impacts the user experience and significantly raised the bar to adopt cloud native stack. We believe "application" is the natural mindset of developers and it's the core concept an application platform should expose.
|
||||
|
||||

|
||||
|
||||
KubeVela intends to let developers push code, define application in developer facing primitives, and make daily operations as configurations of the application.
|
||||
|
||||
Thus, KubeVela choose to:
|
||||
1. Introduce "application" as first class citizen and main API.
|
||||
2. Build the whole system around "application", i.e. model capabilities of Kubernetes as application configuration, with clarity and manageability.
|
||||
|
||||
#### Solution
|
||||
|
||||
Instead of creating a in-house "application CRD", KubeVela adopts [Open Application Model (OAM)](https://github.com/oam-dev/spec) as its application definition, since OAM:
|
||||
1. Defines micro-services application by default.
|
||||
2. Can model operations as part of the application (i.e. `Trait`).
|
||||
2. Highly extensible: every workload and trait in OAM is a independent definition, no abstraction or capability lock-in.
|
||||
|
||||
### 2. Capability Oriented Architecture
|
||||
|
||||
To enable platform builders use KubeVela as the extensible "PaaS core", KubeVela intends to make its every capability a standalone "plug-in".
|
||||
|
||||

|
||||
|
||||
For example, there are several "built-in" workload types in KubeVela such as `Web Service` or `Task`. It is by design that they are all independent CRD controllers that abstract Kubernetes built-in workloads and create Service automatically if needed. KubeVela itself is **NOT** aware of the specification or implementation of these workload types.
|
||||
|
||||
This means platform builders are free to bring their own workload types by simply install a CRD controller, or even just reference a k8s built-in resource like StatefulSet as new workload type.
|
||||
|
||||
Similarly, all the "built-in" operations such as `scaling` or `rollout` (i.e. "traits" in KubeVela) are also independent CRD controllers which are **NOT** bound with specific workload types. Platform builders are free to bring their own traits implementations by simply providing a CRD controller, reference a k8s built-in resource like `HPA` or `NetworkPolicy` as trait is also possible.
|
||||
|
||||
This loosely coupled design of KubeVela adopts the idea of Capability Oriented Architecture (COA), i.e. instead of creating a close system like traditional PaaS, KubeVela intends to become an application-centric framework to connect end users with underlying infrastructure capabilities.
|
||||
|
||||
#### Solution
|
||||
|
||||
We decide to build KubeVela core with [OAM Kubernetes runtime](https://github.com/crossplane/oam-kubernetes-runtime) which already implemented the building block features such as standalone workload type and trait controllers. Whether a given trait could work with certain workload types is also clarified as `appliesTo` field of trait definition. For platform builders, OAM Kubernetes Runtime also provided a [lightweight library](https://github.com/crossplane/oam-kubernetes-runtime/blob/2be3900a3817aed570de9ec353e6ab0b50e100f0/pkg/controller/v1alpha2/core/traits/manualscalertrait/manualscalertrait_controller.go#L42) to implement trait controller so it doesn't need to care about workload kinds.
|
||||
|
||||
##### Capability Register and Discovery
|
||||
|
||||
KubeVela leverages [OAM definition objects](https://github.com/oam-dev/spec/blob/master/4.workload_definitions.md) to register and discover workloads and traits:
|
||||
|
||||
|
||||
```console
|
||||
$ kubectl apply -f workload-definition.yaml # register a new workload type
|
||||
$ kubectl apply -f trait-definition.yaml # register a new trait
|
||||
```
|
||||
|
||||
Note that OAM definition objects only care about API resource, not including the controllers. Thus KubeVela intends to include a **CRD registry** so whenever a new API resource is installed as workload or trait, KubeVela could install its controller automatically from the registry. That of course means we envision the CRD registry could register a CRD and Helm chart (which contains the manifest of the controller). In practice, we are currently evaluating RedHat's Operator Lifecycle Manager (OLM) but no the final conclusion yet.
|
||||
|
||||
##### Cloud Services Integration
|
||||
|
||||
For capabilities like cloud services, KubeVela intends to leverage Kubernetes as the universal control plane so [Crossplane](https://github.com/crossplane/crossplane) core will be used to register cloud services as workload types.
|
||||
|
||||
|
||||
### 3. Extensible User Interface
|
||||
|
||||
KubeVela is built with Kubernetes and OAM also adopts Kubernetes API resource model. So in nutshell, **ALL** functionalities of KubeVela core are able to be consumed by simple `kubectl`, for example:
|
||||
|
||||
```yaml
|
||||
$ kubectl apply -f frontend-component.yaml # create frontend component
|
||||
$ kubectl apply -f backend-component.yaml # create backend component
|
||||
$ kubectl apply -f application-config.yaml # assign operational traits to components
|
||||
```
|
||||
|
||||
However, Kubernetes API should not be the end game. Declarative YAML objects are great to build platforms like KubeVela with but when directly exposed to end users, it creates heavy mental burden and high learning curve. For example, even with highest level abstraction, the default [containerized workload schema](https://github.com/oam-dev/spec/blob/master/core/workloads/schema/containerized_workload.md) of OAM still has dozens fields to learn with many rough edges to be aware.
|
||||
|
||||
Thus KubeVela intends to introduce a lightweight user facing layer on top of its Kubernetes API objects with following goals in mind:
|
||||
|
||||
- Shorten the learning curve of new developers. Most capabilities in KubeVela are developed by big
|
||||
companies that run very complex workloads. However, for the bigger developer community, the new user facing layer will provide a much simpler path to on-board KubeVela.
|
||||
- Developers can describe their applications and behavior of their components without making assumptions on availability of specific Kubernetes API. For instance, a developer will be able to model auto-scaling needs without referring to the CRD of auto-scaling trait.
|
||||
- Provides a single source of truth of the application description. The user facing layer allows developers to work with a single artifact to capture the application definition. This artifact is the definitive truth of how the application is supposed to look like. It simplifies administrative tasks such as change management. It also serves as an anchor for application truth to avoid configuration drifts during operation.
|
||||
- Highly extensible. For example, when a new workload type or trait is installed, the end users could access this new capability directly from user interface layer, no re-compile or re-deploy of KubeVela is required.
|
||||
|
||||
#### Solution
|
||||
|
||||
We concluded above requirements of the user interface layer as introducing a modeling language on top of the existing model objects. With this context, we decide to adopt [CUElang](https://github.com/cuelang/cue) as the modeling language of KubeVela. In detail, every workload or trait definition will inline a cue template as the contract between user and Kubernetes API object.
|
||||
|
||||
However, we don't assume users need to learn or write CUElang directly. Instead, the reason we choose CUElang is it's just perfect to help us create developer facing tools based on it. Thus, KubeVela introduced three most common tools based to CUElang for developers to use:
|
||||
|
||||
1. A command line tool.
|
||||
2. A GUI dashboard.
|
||||
3. A Docker Compose style `appfile`.
|
||||
|
||||
An example for `vela cli`:
|
||||
|
||||
```console
|
||||
$ vela comp deploy frontend -t webservice --image oamdev/testapp:v1 --port 80 --app helloworld
|
||||
```
|
||||
|
||||
The `-t webservice --image oamdev/testapp:v1 --port 80` arguments are not hard coded, they are schema defined by in-line CUE template of `WebService` workload definition.
|
||||
|
||||
The `appfile` is essentially a YAML version of command line tool so we can support more complex and serious scenarios by simply running `$ vela up hello-world.yaml`:
|
||||
|
||||
```yaml
|
||||
version: "1.0-alpha.1"
|
||||
|
||||
name: helloworld
|
||||
|
||||
services:
|
||||
express-server:
|
||||
type: webservice # workload type
|
||||
build:
|
||||
docker:
|
||||
file: Dockerfile
|
||||
context: .
|
||||
|
||||
image: oamdev/testapp:v1
|
||||
cmd: ["node", "server.js"]
|
||||
ports:
|
||||
- 8080:80
|
||||
env:
|
||||
- FOO=bar
|
||||
|
||||
scale: # scaling trait
|
||||
replica: 2
|
||||
auto:
|
||||
range: "1-10"
|
||||
cpu: 80
|
||||
qps: 1000
|
||||
|
||||
canary: # canary trait
|
||||
step: 5
|
||||
headers:
|
||||
- "foo:bar.*"
|
||||
|
||||
redis:
|
||||
image: oamdev/redis
|
||||
|
||||
secrets:
|
||||
my-secret: /local-path/my-secret # load local file into k8s secret
|
||||
```
|
||||
|
||||
The schema of above `appfile` is not hard coded, they are defined by in-line CUE templates of `WebService` workload definition, `Scaling` trait definition and `Canary` trait definition.
|
||||
|
||||
We will skip the example of dashboard, but similarly, the schema of GUI forms are defined by in-lined CUE template of definition objects.
|
||||
|
||||
## Architecture
|
||||
|
||||

|
||||
|
||||
From highest level, KubeVela is composed by only two components:
|
||||
|
||||
### 1. User interface layer
|
||||
Including: `cli`, `dashboard`, `appfile`, they are all client side tools to provide developer facing abstractions by leveraging CUElang based parametering and templating.
|
||||
### 2. KubeVela core
|
||||
Including:
|
||||
- [OAM Kubernetes runtime](https://github.com/crossplane/oam-kubernetes-runtime) to provide application level building blocks such as `Component` and `Application` etc.
|
||||
- [Built-in workload and trait controllers](https://github.com/oam-dev/kubevela/tree/master/pkg/controller/v1alpha1) to implement core capabilities such as `webservice`, `route` and `rollout` etc.
|
||||
- Capability Management: manage features of KubeVela following Capability Oriented Architecture.
|
||||
- Every feature of KubeVela is a "addon", and it is registered by Kubernetes API resource (including CRD) leveraging OAM definition objects.
|
||||
- CRD Registry: register controllers of Kubernetes add-ons and discover them by CRD. This will enable automatically install controllers/operators when CRD is missing in the cluster.
|
||||
39
Makefile
39
Makefile
@@ -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
|
||||
@@ -21,13 +21,11 @@ all: build
|
||||
|
||||
# Run tests
|
||||
test: fmt vet lint
|
||||
./hack/unit_test.sh
|
||||
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
|
||||
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 ./..
|
||||
@@ -35,16 +33,11 @@ npm-build:
|
||||
npm-install:
|
||||
cd dashboard && npm install && cd ./..
|
||||
|
||||
generate-doc:
|
||||
rm -r documentation/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:
|
||||
( \
|
||||
@@ -80,10 +73,8 @@ 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:
|
||||
@@ -97,10 +88,6 @@ e2e-api-test:
|
||||
e2e-cleanup:
|
||||
# Clean up
|
||||
|
||||
# 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
|
||||
@@ -119,22 +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/definitions/
|
||||
kubectl apply -f charts/third_party/prometheus
|
||||
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/crds/
|
||||
kubectl delete -f charts/vela-core/templates/definitions/
|
||||
kubectl delete -f charts/third_party/prometheus
|
||||
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
|
||||
rm charts/vela-core/crds/_.yaml
|
||||
|
||||
# Generate code
|
||||
generate: controller-gen
|
||||
|
||||
267
README.md
267
README.md
@@ -1,27 +1,8 @@
|
||||
# KubeVela
|
||||
|
||||
The Open Application Platform based on Kubernetes and Open Application Model (OAM).
|
||||
The Open Application Platform based on Kubernetes and OAM.
|
||||
|
||||
## Project Status
|
||||
|
||||
:rotating_light: **Warning: this project is still a work in progress with lots of rough edges, please don't look inside unless you know what you are doing.**
|
||||
|
||||
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.
|
||||
|
||||
## Purpose and Goal
|
||||
|
||||
- For developers and operators
|
||||
- KubeVela, as an out-of-box Cloud Native Application Management Platform, provides numerous workloads and operation tooling for application defining, deployment, scaling, traffic, rollout, routing, monitoring, logging, alerting, CI/CD and so on.
|
||||
- For platform builders
|
||||
- KubeVela, as a highly extensible PaaS/Serverless Core, provides pluggable capabilities, an elegant way to integrate any workloads and operational capabilities (i.e. traits).
|
||||
|
||||
## Design and Architecture
|
||||
|
||||
Read more about [KubeVela's high level design and architecture](DESIGN.md).
|
||||
|
||||
## Demo Instructions
|
||||
|
||||
See the demo instructions below get a sense of what we've accomplished and are working on.
|
||||
: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:
|
||||
|
||||
## Install
|
||||
|
||||
@@ -32,7 +13,7 @@ See the demo instructions below get a sense of what we've accomplished and are w
|
||||
|
||||
### Get the Vela CLI
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
```shell
|
||||
sudo mv ./vela /usr/local/bin/vela
|
||||
@@ -40,154 +21,159 @@ sudo mv ./vela /usr/local/bin/vela
|
||||
|
||||
### Install Vela Core
|
||||
|
||||
```console
|
||||
```shell script
|
||||
$ vela install
|
||||
```
|
||||
This command will install vela core controller into your K8s cluster, along with built-in workloads and traits.
|
||||
|
||||
## Using KubeVela
|
||||
## Demos
|
||||
|
||||
After `vela install` you will see available workloads and traits.
|
||||
After `vela install` you will have workloads and traits locally, and available to use by vela cli.
|
||||
|
||||
```console
|
||||
```shell script
|
||||
$ vela workloads
|
||||
NAME DEFINITION
|
||||
backend podspecworkloads.standard.oam.dev
|
||||
task jobs.batch.k8s.io
|
||||
webservice podspecworkloads.standard.oam.dev
|
||||
backend containerizeds.standard.oam.dev
|
||||
containerized containerizedworkloads.core.oam.dev
|
||||
task jobs
|
||||
webservice containerizeds.standard.oam.dev
|
||||
```
|
||||
|
||||
```console
|
||||
```shell script
|
||||
$ vela traits
|
||||
NAME DEFINITION APPLIES TO
|
||||
route routes.standard.oam.dev webservice,backend
|
||||
scale manualscalertraits.core.oam.dev webservice,backend
|
||||
route routes.standard.oam.dev webservice
|
||||
backend
|
||||
scale manualscalertraits.core.oam.dev webservice
|
||||
backend
|
||||
```
|
||||
|
||||
### Create environment
|
||||
### Create ENV
|
||||
|
||||
Before working with your application, you should prepare an deploy environment for it (e.g. test, staging, prod etc).
|
||||
Before working with your application, you should create an env for it.
|
||||
|
||||
```console
|
||||
$ vela env init demo --namespace demo --email my@email.com --domain kubevela.io
|
||||
ENVIROMENT demo CREATED, Namespace: demo, Email: my@email.com.
|
||||
```shell script
|
||||
$ vela env init myenv --namespace myenv --email my@email.com --domain kubevela.io
|
||||
ENV myenv CREATED, Namespace: myenv, Email: my@email.com.
|
||||
```
|
||||
|
||||
Vela will create a Kubernetes namespace called `demo` , with namespace level issuer for certificate generation using the email you provided.
|
||||
It will create a namespace called myenv
|
||||
|
||||
You could check the environment metadata in your local:
|
||||
```shell script
|
||||
$ kubectl get ns
|
||||
NAME STATUS AGE
|
||||
myenv Active 40s
|
||||
```
|
||||
|
||||
```console
|
||||
$ cat ~/.vela/envs/demo/config.json
|
||||
{"name":"demo","namespace":"demo","email":"my@email.com","domain":"kubevela.io","issuer":"oam-env-demo"}
|
||||
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 simple component
|
||||
### Create Component
|
||||
|
||||
Then let's create application, we will use the `demo` environment.
|
||||
Then let's create application, we will use our env created by default.
|
||||
|
||||
```console
|
||||
$ vela comp deploy mycomp -t webservice --image crccheck/hello-world --port 8000 --app myapp
|
||||
```shell script
|
||||
$ vela comp run mycomp -t webservice --image crccheck/hello-world --port 8000 --app myapp
|
||||
Creating AppConfig appcomp
|
||||
SUCCEED
|
||||
```
|
||||
|
||||
### Create micro-services application
|
||||
It will create component named `mycomp`.
|
||||
|
||||
Vela supports micro-services application by default thanks to Open Application Model.
|
||||
```shell script
|
||||
$ kubectl get components -n myenv
|
||||
NAME WORKLOAD-KIND AGE
|
||||
mycomp Containerized 10s
|
||||
```
|
||||
|
||||
```console
|
||||
$ vela comp deploy db -t backend --image crccheck/hello-world --app myapp
|
||||
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
|
||||
```
|
||||
|
||||
```console
|
||||
```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
|
||||
```
|
||||
|
||||
#### Under the hood
|
||||
Now we can see the application deployed, let's add route trait for visiting.
|
||||
|
||||
In Kubernetes, vela creates an OAM application configuration named `myapp` to manage all related components.
|
||||
### Add Trait
|
||||
|
||||
```console
|
||||
$ kubectl get appconfig -n demo
|
||||
NAME AGE
|
||||
myapp 24s
|
||||
```
|
||||
|
||||
```console
|
||||
$ kubectl get components -n demo
|
||||
NAME AGE
|
||||
mycomp 24s
|
||||
db 10s
|
||||
```
|
||||
|
||||
Vela Core is responsible for managing the underlying Kubernetes resources linked with the components and application configuration above.
|
||||
|
||||
```console
|
||||
$ kubectl get deployment -n demo
|
||||
NAME READY UP-TO-DATE AVAILABLE AGE
|
||||
mycomp 1/1 1 1 38s
|
||||
db 1/1 1 1 20s
|
||||
```
|
||||
|
||||
```console
|
||||
$ kubectl get svc -n demo
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
mycomp ClusterIP 172.21.4.228 <none> 8080/TCP 49s
|
||||
```
|
||||
|
||||
### Manage operational configurations of the application
|
||||
|
||||
Vela leverages OAM trait system to manage operational configurations such as `scale`, `route`, `canary`, `autocale`etc in application centric approach.
|
||||
|
||||
Let's take `route` as example.
|
||||
|
||||
### `route`
|
||||
|
||||
If you want to use `route`, please make sure you have [nginx-ingress controller[https://kubernetes.github.io/ingress-nginx/deploy/] in your cluster.
|
||||
|
||||
```console
|
||||
```shell script
|
||||
$ vela route mycomp --app myapp
|
||||
Adding route for app mycomp
|
||||
Succeeded!
|
||||
```
|
||||
|
||||
For now you have to check the public address manually (this will be fixed soon so `vela route` will return visiting URL as result):
|
||||
It will create route trait for this component.
|
||||
|
||||
```console
|
||||
$ kubectl get ingress -n demo
|
||||
NAME HOSTS ADDRESS PORTS AGE
|
||||
mycomp-trait-5b576c4fc mycomp.kubevela.io 123.57.10.233 80, 443 73s
|
||||
```
|
||||
|
||||
And after you configure the `kubevela.io` domain pointing to the public address above.
|
||||
|
||||
Your application will be reached by `https://mycomp.kubevela.io` with `mTLS` automatically enabled.
|
||||
|
||||
### Under the hood
|
||||
|
||||
Vela will manage the underlying Kubernetes resource which implements the `route` trait.
|
||||
|
||||
```console
|
||||
$ kubectl get routes.standard.oam.dev -n demo
|
||||
```shell script
|
||||
$ kubeclt get routes.standard.oam.dev -n myenv
|
||||
NAME AGE
|
||||
mycomp-trait-5b576c4fc 18s
|
||||
```
|
||||
|
||||
`routes.standard.oam.dev` is a CRD controller which will manage ingress, domain, certificate etc for your application.
|
||||
Controller of route trait which is part of vela core will create an ingress for it.
|
||||
|
||||
### Check status
|
||||
```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 the application:
|
||||
### Check Status
|
||||
|
||||
```console
|
||||
|
||||
App level:
|
||||
|
||||
```shell script
|
||||
$ vela app show myapp
|
||||
About:
|
||||
|
||||
@@ -198,7 +184,7 @@ $ vela app show myapp
|
||||
|
||||
Environment:
|
||||
|
||||
Namespace: demo
|
||||
Namespace: myenv
|
||||
|
||||
Components:
|
||||
|
||||
@@ -207,9 +193,9 @@ $ vela app show myapp
|
||||
mycomp webservice route
|
||||
```
|
||||
|
||||
Check specific component:
|
||||
Component Level:
|
||||
|
||||
```console
|
||||
```shell script
|
||||
$ vela comp show mycomp
|
||||
About:
|
||||
|
||||
@@ -219,7 +205,7 @@ $ vela comp show mycomp
|
||||
|
||||
Environment:
|
||||
|
||||
Namespace: demo
|
||||
Namespace: myenv
|
||||
|
||||
Arguments:
|
||||
|
||||
@@ -232,15 +218,15 @@ $ vela comp show mycomp
|
||||
|
||||
route:
|
||||
domain: mycomp.kubevela.io
|
||||
issuer: oam-env-demo
|
||||
issuer: oam-env-myenv
|
||||
name: route
|
||||
```
|
||||
|
||||
```
|
||||
$ vela comp status mycomp
|
||||
Showing status of Component mycomp deployed in Environment demo
|
||||
Showing status of Component mycomp deployed in Environment myenv
|
||||
Component Status:
|
||||
Name: mycomp PodSpecWorkload(type) UNKNOWN APIVersion standard.oam.dev/v1alpha1 Kind PodSpecWorkload workload is unknown for HealthScope
|
||||
Name: mycomp Containerized(type) UNKNOWN APIVersion standard.oam.dev/v1alpha1 Kind Containerized workload is unknown for HealthScope
|
||||
Traits
|
||||
└─Trait/route
|
||||
|
||||
@@ -249,50 +235,50 @@ $ vela comp status mycomp
|
||||
Updated at: 2020-09-18T22:51:11+08:00
|
||||
```
|
||||
|
||||
### Delete application or component
|
||||
### Delete App or Component
|
||||
|
||||
```console
|
||||
```shell script
|
||||
$ vela app ls
|
||||
myapp
|
||||
```
|
||||
|
||||
```console
|
||||
```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
|
||||
```
|
||||
|
||||
```console
|
||||
```shell script
|
||||
$ vela comp delete db
|
||||
Deleting Component 'db' from Application 'db'
|
||||
```
|
||||
|
||||
```console
|
||||
```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
|
||||
```
|
||||
|
||||
```console
|
||||
```shell script
|
||||
$ vela app delete myapp
|
||||
Deleting Application "myapp"
|
||||
delete apps succeed myapp from demo
|
||||
delete apps succeed myapp from myenv
|
||||
```
|
||||
|
||||
## Dashboard
|
||||
|
||||
Vela has a simple client side dashboard for you to interact with (note it's still under development). The functionality is equivalent to the vela cli.
|
||||
We also prepared a dashboard for you, but it's still in heavily development.
|
||||
|
||||
```console
|
||||
```shell script
|
||||
$ vela dashboard
|
||||
```
|
||||
|
||||
#### Auto-completion
|
||||
#### Auto-Completion
|
||||
|
||||
##### bash
|
||||
|
||||
```console
|
||||
```shell script
|
||||
To load completions in your current shell session:
|
||||
$ source <(vela completion bash)
|
||||
|
||||
@@ -305,7 +291,7 @@ MacOS:
|
||||
|
||||
##### zsh
|
||||
|
||||
```console
|
||||
```shell script
|
||||
To load completions in your current shell session:
|
||||
$ source <(vela completion zsh)
|
||||
|
||||
@@ -315,24 +301,21 @@ $ vela completion zsh > "${fpath[1]}/_vela"
|
||||
|
||||
### Clean your environment
|
||||
|
||||
```console
|
||||
$ helm uninstall kubevela -n vela-system
|
||||
release "kubevela" uninstalled
|
||||
```shell script
|
||||
$ helm uninstall vela-core -n oam-system
|
||||
release "vela-core" uninstalled
|
||||
```
|
||||
|
||||
```console
|
||||
$ kubectl delete crd workloaddefinitions.core.oam.dev traitdefinitions.core.oam.dev scopedefinitions.core.oam.dev
|
||||
```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
|
||||
```
|
||||
|
||||
```console
|
||||
```shell script
|
||||
$ rm -r ~/.vela
|
||||
```
|
||||
|
||||
## Contributing
|
||||
## 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.md](CODE_OF_CONDUCT.md) for further details.
|
||||
|
||||
|
||||
@@ -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{})
|
||||
}
|
||||
@@ -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
|
||||
)
|
||||
@@ -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
|
||||
}
|
||||
@@ -46,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"`
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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"`
|
||||
|
||||
// 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,36 +45,36 @@ type PodSpecWorkloadStatus struct {
|
||||
|
||||
// +kubebuilder:object:root=true
|
||||
|
||||
// PodSpecWorkload is the Schema for the PodSpec API
|
||||
// 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)
|
||||
}
|
||||
@@ -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,30 +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"`
|
||||
Ingress *runtimev1alpha1.TypedReference `json:"ingress,omitempty"`
|
||||
Service *runtimev1alpha1.TypedReference `json:"service,omitempty"`
|
||||
runtimev1alpha1.ConditionedStatus `json:",inline"`
|
||||
}
|
||||
|
||||
|
||||
@@ -22,16 +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 *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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,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
|
||||
}
|
||||
@@ -158,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
|
||||
@@ -327,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.
|
||||
@@ -349,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
|
||||
@@ -372,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
|
||||
|
||||
44
charts/third_party/cert-manager/download-cert-manager.sh
vendored
Normal file
44
charts/third_party/cert-manager/download-cert-manager.sh
vendored
Normal 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
|
||||
4
charts/third_party/grafana/download-grafana.sh
vendored
Normal file
4
charts/third_party/grafana/download-grafana.sh
vendored
Normal 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
|
||||
24
charts/third_party/grafana/grafana-operator.yaml
vendored
Normal file
24
charts/third_party/grafana/grafana-operator.yaml
vendored
Normal 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
|
||||
6
charts/third_party/prometheus/monitoring-namespace.yaml
vendored
Normal file
6
charts/third_party/prometheus/monitoring-namespace.yaml
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
labels:
|
||||
mornitoring: oam
|
||||
name: monitoring
|
||||
4620
charts/third_party/prometheus/prometheus-operator-0alertmanagerCustomResourceDefinition.yaml
vendored
Normal file
4620
charts/third_party/prometheus/prometheus-operator-0alertmanagerCustomResourceDefinition.yaml
vendored
Normal file
File diff suppressed because it is too large
Load Diff
265
charts/third_party/prometheus/prometheus-operator-0podmonitorCustomResourceDefinition.yaml
vendored
Normal file
265
charts/third_party/prometheus/prometheus-operator-0podmonitorCustomResourceDefinition.yaml
vendored
Normal 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: []
|
||||
212
charts/third_party/prometheus/prometheus-operator-0probeCustomResourceDefinition.yaml
vendored
Normal file
212
charts/third_party/prometheus/prometheus-operator-0probeCustomResourceDefinition.yaml
vendored
Normal 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: []
|
||||
6315
charts/third_party/prometheus/prometheus-operator-0prometheusCustomResourceDefinition.yaml
vendored
Normal file
6315
charts/third_party/prometheus/prometheus-operator-0prometheusCustomResourceDefinition.yaml
vendored
Normal file
File diff suppressed because it is too large
Load Diff
94
charts/third_party/prometheus/prometheus-operator-0prometheusruleCustomResourceDefinition.yaml
vendored
Normal file
94
charts/third_party/prometheus/prometheus-operator-0prometheusruleCustomResourceDefinition.yaml
vendored
Normal 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: []
|
||||
4859
charts/third_party/prometheus/prometheus-operator-0thanosrulerCustomResourceDefinition.yaml
vendored
Normal file
4859
charts/third_party/prometheus/prometheus-operator-0thanosrulerCustomResourceDefinition.yaml
vendored
Normal file
File diff suppressed because it is too large
Load Diff
82
charts/third_party/prometheus/prometheus-operator-clusterRole.yaml
vendored
Normal file
82
charts/third_party/prometheus/prometheus-operator-clusterRole.yaml
vendored
Normal 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
|
||||
34
charts/third_party/prometheus/prometheus-operator-clusterRoleBinding.yaml
vendored
Normal file
34
charts/third_party/prometheus/prometheus-operator-clusterRoleBinding.yaml
vendored
Normal 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
|
||||
60
charts/third_party/prometheus/prometheus-operator-deployment.yaml
vendored
Normal file
60
charts/third_party/prometheus/prometheus-operator-deployment.yaml
vendored
Normal 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
|
||||
18
charts/third_party/prometheus/prometheus-operator-service.yaml
vendored
Normal file
18
charts/third_party/prometheus/prometheus-operator-service.yaml
vendored
Normal 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
|
||||
9
charts/third_party/prometheus/prometheus-operator-serviceAccount.yaml
vendored
Normal file
9
charts/third_party/prometheus/prometheus-operator-serviceAccount.yaml
vendored
Normal 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
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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: []
|
||||
@@ -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
|
||||
|
||||
@@ -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: ""
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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: []
|
||||
@@ -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
|
||||
@@ -5694,7 +5694,7 @@ spec:
|
||||
- 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.
|
||||
@@ -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
|
||||
|
||||
37
charts/vela-core/templates/backend.yaml
Normal file
37
charts/vela-core/templates/backend.yaml
Normal 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
@@ -1,13 +1,13 @@
|
||||
apiVersion: core.oam.dev/v1alpha2
|
||||
kind: WorkloadDefinition
|
||||
metadata:
|
||||
name: podspecworkloads.standard.oam.dev
|
||||
name: containerizeds.standard.oam.dev
|
||||
annotations:
|
||||
definition.oam.dev/apiVersion: "standard.oam.dev/v1alpha1"
|
||||
definition.oam.dev/kind: "PodSpecWorkload"
|
||||
definition.oam.dev/kind: "Containerized"
|
||||
spec:
|
||||
definitionRef:
|
||||
name: podspecworkloads.standard.oam.dev
|
||||
name: containerizeds.standard.oam.dev
|
||||
childResourceKinds:
|
||||
- apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
@@ -15,19 +15,19 @@ spec:
|
||||
kind: Service
|
||||
extension:
|
||||
template: |
|
||||
output: {
|
||||
#Template: {
|
||||
apiVersion: "standard.oam.dev/v1alpha1"
|
||||
kind: "PodSpecWorkload"
|
||||
kind: "Containerized"
|
||||
metadata:
|
||||
name: parameter.name
|
||||
name: webservice.name
|
||||
spec: {
|
||||
replicas: 1
|
||||
podSpec: {
|
||||
containers: [{
|
||||
image: parameter.image
|
||||
name: parameter.name
|
||||
image: webservice.image
|
||||
name: webservice.name
|
||||
ports: [{
|
||||
containerPort: parameter.port
|
||||
containerPort: webservice.port
|
||||
protocol: "TCP"
|
||||
name: "default"
|
||||
}]
|
||||
@@ -35,7 +35,7 @@ spec:
|
||||
}
|
||||
}
|
||||
}
|
||||
#webservice: {
|
||||
webservice: {
|
||||
name: string
|
||||
// +usage=specify app image
|
||||
// +short=i
|
||||
@@ -44,5 +44,3 @@ spec:
|
||||
// +short=p
|
||||
port: *6379 | int
|
||||
}
|
||||
parameter: #webservice
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
apiVersion: core.oam.dev/v1alpha2
|
||||
kind: WorkloadDefinition
|
||||
metadata:
|
||||
name: backend
|
||||
annotations:
|
||||
definition.oam.dev/apiVersion: "standard.oam.dev/v1alpha1"
|
||||
definition.oam.dev/kind: "PodSpecWorkload"
|
||||
definition.oam.dev/description: "Backend worker without ports exposed"
|
||||
spec:
|
||||
definitionRef:
|
||||
name: podspecworkload.standard.oam.dev
|
||||
childResourceKinds:
|
||||
- apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
extension:
|
||||
template: |
|
||||
output: {
|
||||
apiVersion: "standard.oam.dev/v1alpha1"
|
||||
kind: "PodSpecWorkload"
|
||||
metadata:
|
||||
name: parameter.name
|
||||
spec: {
|
||||
replicas: 1
|
||||
podSpec: {
|
||||
containers: [{
|
||||
image: parameter.image
|
||||
name: parameter.name
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
#backend: {
|
||||
name: string
|
||||
// +usage=specify app image
|
||||
// +short=i
|
||||
image: string
|
||||
}
|
||||
parameter: #backend
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
labels:
|
||||
mornitoring: oam
|
||||
name: monitoring
|
||||
|
||||
---
|
||||
apiVersion: core.oam.dev/v1alpha2
|
||||
kind: TraitDefinition
|
||||
metadata:
|
||||
name: metric
|
||||
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: |-
|
||||
#metrics: {
|
||||
// +usage=format of the metrics, default as prometheus
|
||||
// +short=f
|
||||
format: *"prometheus" | string
|
||||
path: *"/metrics" | string
|
||||
scheme: *"http" | string
|
||||
enabled: *true | bool
|
||||
port: *8080 | >=1024 & uint16
|
||||
// +usage= the label selector for the pods, default is the workload labels
|
||||
selector?: [string]: string
|
||||
}
|
||||
spec: {
|
||||
apiVersion: "standard.oam.dev/v1alpha1"
|
||||
kind: "MetricsTrait"
|
||||
spec: {
|
||||
scrapeService: parameter
|
||||
}
|
||||
}
|
||||
parameter: #metrics
|
||||
output: {}
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
apiVersion: core.oam.dev/v1alpha2
|
||||
kind: TraitDefinition
|
||||
metadata:
|
||||
name: route
|
||||
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:
|
||||
- core.oam.dev/v1alpha2.ContainerizedWorkload
|
||||
- standard.oam.dev/v1alpha1.PodSpecWorkload
|
||||
- deployments.apps
|
||||
- webservice
|
||||
workloadRefPath: spec.workloadRef
|
||||
definitionRef:
|
||||
name: routes.standard.oam.dev
|
||||
extension:
|
||||
template: |
|
||||
output: {
|
||||
apiVersion: "standard.oam.dev/v1alpha1"
|
||||
kind: "Route"
|
||||
spec: {
|
||||
host: parameter.domain
|
||||
tls: {
|
||||
issuerName: parameter.issuer
|
||||
}
|
||||
}
|
||||
}
|
||||
#route: {
|
||||
domain: *"" | string
|
||||
issuer: *"" | string
|
||||
}
|
||||
parameter: #route
|
||||
|
||||
@@ -1,49 +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 off task or job"
|
||||
spec:
|
||||
definitionRef:
|
||||
name: jobs
|
||||
extension:
|
||||
defaultTraits:
|
||||
- monitor
|
||||
- logging
|
||||
template: |
|
||||
output: {
|
||||
apiVersion: "v1"
|
||||
kind: "Job"
|
||||
metadata: name: parameter.name
|
||||
spec: {
|
||||
parallelism: parameter.count
|
||||
completions: parameter.count
|
||||
template:
|
||||
spec:
|
||||
containers: [{
|
||||
image: parameter.image
|
||||
name: parameter.name
|
||||
ports: [{
|
||||
containerPort: parameter.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
|
||||
}
|
||||
parameter: #task
|
||||
@@ -1,48 +0,0 @@
|
||||
apiVersion: core.oam.dev/v1alpha2
|
||||
kind: WorkloadDefinition
|
||||
metadata:
|
||||
name: webservice
|
||||
annotations:
|
||||
definition.oam.dev/apiVersion: "standard.oam.dev/v1alpha1"
|
||||
definition.oam.dev/kind: "PodSpecWorkload"
|
||||
definition.oam.dev/description: "Long running service with ports exposed"
|
||||
spec:
|
||||
definitionRef:
|
||||
name: podspecworkloads.standard.oam.dev
|
||||
childResourceKinds:
|
||||
- apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
- apiVersion: v1
|
||||
kind: Service
|
||||
extension:
|
||||
template: |
|
||||
output: {
|
||||
apiVersion: "standard.oam.dev/v1alpha1"
|
||||
kind: "PodSpecWorkload"
|
||||
metadata:
|
||||
name: parameter.name
|
||||
spec: {
|
||||
replicas: 1
|
||||
podSpec: {
|
||||
containers: [{
|
||||
image: parameter.image
|
||||
name: parameter.name
|
||||
ports: [{
|
||||
containerPort: parameter.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
|
||||
}
|
||||
parameter: #webservice
|
||||
@@ -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 }}
|
||||
@@ -12,18 +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
|
||||
}
|
||||
}
|
||||
#scale: {
|
||||
scale: {
|
||||
//+short=r
|
||||
replica: *2 | int
|
||||
}
|
||||
parameter: #scale
|
||||
workloadRefPath: spec.workloadRef
|
||||
17
charts/vela-core/templates/metricstraits.yaml
Normal file
17
charts/vela-core/templates/metricstraits.yaml
Normal file
@@ -0,0 +1,17 @@
|
||||
apiVersion: core.oam.dev/v1alpha2
|
||||
kind: TraitDefinition
|
||||
metadata:
|
||||
name: metricstraits.standard.oam.dev
|
||||
namespace: default
|
||||
annotations:
|
||||
definition.oam.dev/apiVersion: standard.oam.dev/v1alpha1
|
||||
definition.oam.dev/kind: MetricsTrait
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- containerizedworkloads.core.oam.dev
|
||||
- clonesetworkloads.apps.kruise.io
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
definitionRef:
|
||||
name: metricstraits.standard.oam.dev
|
||||
workloadRefPath: spec.workloadRef
|
||||
37
charts/vela-core/templates/routetrait.yaml
Normal file
37
charts/vela-core/templates/routetrait.yaml
Normal 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
|
||||
}
|
||||
47
charts/vela-core/templates/tasks.yaml
Normal file
47
charts/vela-core/templates/tasks.yaml
Normal 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
|
||||
}
|
||||
@@ -2,7 +2,7 @@ apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: vela-config
|
||||
namespace: {{ .Release.Namespace }}
|
||||
namespace: default
|
||||
data:
|
||||
certificates.cert-manager.io: |
|
||||
{
|
||||
@@ -10,13 +10,5 @@ data:
|
||||
"urL": "https://charts.jetstack.io",
|
||||
"name": "cert-manager",
|
||||
"namespace": "cert-manager",
|
||||
"version": "1.0.3"
|
||||
}
|
||||
servicemonitors.monitoring.coreos.com: |
|
||||
{
|
||||
"repo": "prometheus-community",
|
||||
"urL": "https://prometheus-community.github.io/helm-charts",
|
||||
"name": "kube-prometheus-stack",
|
||||
"namespace": "monitoring",
|
||||
"version": "9.4.4"
|
||||
"version": "1.0.0"
|
||||
}
|
||||
@@ -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 }}
|
||||
|
||||
46
charts/vela-core/templates/webservices.yaml
Normal file
46
charts/vela-core/templates/webservices.yaml
Normal 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
|
||||
}
|
||||
@@ -63,9 +63,6 @@ webhookService:
|
||||
type: ClusterIP
|
||||
port: 9443
|
||||
|
||||
healthCheck:
|
||||
port: 9440
|
||||
|
||||
nodeSelector: {}
|
||||
|
||||
tolerations: []
|
||||
|
||||
123
cmd/core/main.go
123
cmd/core/main.go
@@ -1,17 +1,16 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"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"
|
||||
@@ -20,7 +19,10 @@ import (
|
||||
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"
|
||||
|
||||
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"
|
||||
@@ -28,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)
|
||||
@@ -55,7 +41,6 @@ func init() {
|
||||
_ = oamcore.AddToScheme(scheme)
|
||||
_ = monitoring.AddToScheme(scheme)
|
||||
_ = velacore.AddToScheme(scheme)
|
||||
_ = velacoreoamdev.AddToScheme(scheme)
|
||||
_ = injectorv1alpha1.AddToScheme(scheme)
|
||||
_ = certmanager.AddToScheme(scheme)
|
||||
|
||||
@@ -70,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")
|
||||
@@ -84,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
|
||||
@@ -104,33 +87,28 @@ 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)
|
||||
}
|
||||
if err = dependency.Install(k8sClient); err != nil {
|
||||
setupLog.Error(err, "unable to install the dependency")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -138,10 +116,6 @@ func main() {
|
||||
setupLog.Info("vela webhook enabled, will serving at :" + strconv.Itoa(webhookPort))
|
||||
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 {
|
||||
@@ -178,50 +152,3 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
f, _ := os.Open(certDir)
|
||||
defer f.Close()
|
||||
// check if dir is empty
|
||||
if _, err := f.Readdir(1); err == io.EOF {
|
||||
continue
|
||||
}
|
||||
// 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 nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
@@ -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
|
||||
159
cmd/vela/main.go
159
cmd/vela/main.go
@@ -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,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
19
config/samples/issuer.yaml
Normal file
19
config/samples/issuer.yaml
Normal 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
|
||||
@@ -1,31 +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
|
||||
definition.oam.dev/description: "Scale replica for workload"
|
||||
name: scaler
|
||||
namespace: default
|
||||
definition.oam.dev/apiVersion: "core.oam.dev/v1alpha2"
|
||||
definition.oam.dev/kind: "ManualScalerTrait"
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- core.oam.dev/v1alpha2.ContainerizedWorkload
|
||||
- apps/v1.Deployment
|
||||
- webservice
|
||||
definitionRef:
|
||||
name: manualscalertraits.core.oam.dev
|
||||
workloadRefPath: spec.workloadRef
|
||||
extension:
|
||||
template: |-
|
||||
output: {
|
||||
template: |
|
||||
#Template: {
|
||||
apiVersion: "core.oam.dev/v1alpha2"
|
||||
kind: "ManualScalerTrait"
|
||||
spec: {
|
||||
replicaCount: parameter.replica
|
||||
replicaCount: scale.replica
|
||||
}
|
||||
}
|
||||
#scale: {
|
||||
scale: {
|
||||
//+short=r
|
||||
replica: *2 | int
|
||||
}
|
||||
parameter: #scale
|
||||
37
config/samples/traits/route.yaml
Normal file
37
config/samples/traits/route.yaml
Normal 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
|
||||
}
|
||||
30
config/samples/traits/simplerollouttrait_definition.yaml
Normal file
30
config/samples/traits/simplerollouttrait_definition.yaml
Normal 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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
52
config/samples/workloads/deployment_definition.yaml
Normal file
52
config/samples/workloads/deployment_definition.yaml
Normal 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
|
||||
}]
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
export default {
|
||||
dev: {
|
||||
'/api': {
|
||||
target: 'http://127.0.0.1:38081/',
|
||||
target: 'http://30.11.171.29:38081/',
|
||||
changeOrigin: true,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
@@ -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 ? (
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
606
dashboard/src/pages/ApplicationList/CreateApplication/index.jsx
Normal file
606
dashboard/src/pages/ApplicationList/CreateApplication/index.jsx
Normal 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;
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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 ? (
|
||||
|
||||
@@ -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={[
|
||||
{
|
||||
|
||||
@@ -58,7 +58,6 @@ class TableList extends React.PureComponent {
|
||||
btnValue: 'Create',
|
||||
hrefAddress: '#',
|
||||
btnIsShow: true,
|
||||
history: this.props.history,
|
||||
};
|
||||
this.setState({
|
||||
propsObj,
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
import request from '@/utils/request';
|
||||
/*
|
||||
* GET /api/envs/:envName/apps/:appName/components/ (component list)
|
||||
* Same as GET /api/envs/:envName/apps/:appName (app description).
|
||||
*/
|
||||
export async function getComponentList({ envName, appName }) {
|
||||
return request(`/api/envs/${envName}/apps/${appName}/components/`);
|
||||
}
|
||||
/*
|
||||
* GET /api/envs/:envName/apps/:appName/components/:compName (component details)
|
||||
*/
|
||||
export async function getComponentDetail({ envName, appName, compName }) {
|
||||
return request(`/api/envs/${envName}/apps/${appName}/components/${compName}`);
|
||||
}
|
||||
/*
|
||||
* DELETE /api/envs/:envName/apps/:appName/components/:compName (component delete)
|
||||
*/
|
||||
export async function deleteComponent({ envName, appName, compName }) {
|
||||
return request(`/api/envs/${envName}/apps/${appName}/components/${compName}`, {
|
||||
method: 'delete',
|
||||
});
|
||||
}
|
||||
@@ -12,10 +12,10 @@ export async function getTraits() {
|
||||
return request('/api/traits/');
|
||||
}
|
||||
/*
|
||||
* POST /api/envs/:envName/apps/:appName/components/:compName/traits/ (attach a trait)
|
||||
* POST /api/envs/:envName/apps/:appName/traits/ (attach 单个 trait)
|
||||
*/
|
||||
export async function attachOneTraits({ envName, appName, compName, params }) {
|
||||
return request(`/api/envs/${envName}/apps/${appName}/components/${compName}/traits/`, {
|
||||
export async function attachOneTraits({ envName, appName, params }) {
|
||||
return request(`/api/envs/${envName}/apps/${appName}/traits/`, {
|
||||
method: 'post',
|
||||
data: {
|
||||
...params,
|
||||
@@ -26,13 +26,10 @@ export async function attachOneTraits({ envName, appName, compName, params }) {
|
||||
});
|
||||
}
|
||||
/*
|
||||
* DELETE /api/envs/:envName/apps/:appName/components/:compName/traits/:traitName (detach a trait)
|
||||
* DELETE /api/envs/:envName/apps/:appName/traits/:traitName (detach 单个 trait)
|
||||
*/
|
||||
export async function deleteOneTrait({ envName, appName, compName, traitName }) {
|
||||
return request(
|
||||
`/api/envs/${envName}/apps/${appName}/components/${compName}/traits/${traitName}`,
|
||||
{
|
||||
method: 'delete',
|
||||
},
|
||||
);
|
||||
export async function deleteOneTrait({ envName, appName, traitName }) {
|
||||
return request(`/api/envs/${envName}/apps/${appName}/traits/${traitName}`, {
|
||||
method: 'delete',
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,362 +0,0 @@
|
||||
# Appfile: Extensible, User-friendly Application Config Format
|
||||
|
||||
- Owner: Hongchao Deng (@hongchaodeng)
|
||||
- Date: 10/14/2020
|
||||
- Status: Implemented
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Intro](#intro)
|
||||
- [Goals](#goals)
|
||||
- [Proposal](#proposal)
|
||||
- [Registration via Definition/Capability](#registration-via-definitioncapability)
|
||||
- [Templating](#templating)
|
||||
- [CLI/UI interoperability](#cliui-interoperability)
|
||||
- [vela up](#vela-up)
|
||||
- [Examples](#examples)
|
||||
|
||||
## Intro
|
||||
|
||||
Vela supports a user-friendly `docker-compose` style config format called `Appfile`. It allows you to define an application's workloads and traits with an opinionated, simplified API interface.
|
||||
|
||||
Here's an example to deploy a NodeJS express service:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
express-server:
|
||||
# this image will be used in both build and deploy config
|
||||
image: oamdev/testapp:v1
|
||||
|
||||
build:
|
||||
# Here more runtime specific build templates will be supported, like NodeJS, Go, Python, Ruby.
|
||||
docker:
|
||||
file: Dockerfile
|
||||
context: .
|
||||
|
||||
cmd: ["node", "server.js"]
|
||||
|
||||
route:
|
||||
domain: example.com
|
||||
http: # match the longest prefix
|
||||
"/": 8080
|
||||
|
||||
env:
|
||||
- FOO=bar
|
||||
- FOO2=sec:my-secret # map the key same as the env name (`FOO2`) from my-secret to env var
|
||||
- FOO3=sec:my-secret:key # map specific key from my-secret to env var
|
||||
- sec:my-secret # map all KV pairs from my-secret to env var
|
||||
|
||||
files: # Mount secret as a file
|
||||
- /mnt/path=sec:my-secret
|
||||
|
||||
scale:
|
||||
replica: 2
|
||||
auto: # automatic scale up and down based on given metrics
|
||||
range: "1-10"
|
||||
cpu: 80 # if cpu utilization is above 80%, scale up
|
||||
qps: 1000 # if qps is higher than 1k, scale up
|
||||
|
||||
canary: # Auto-create canary deployment. Only upgrade after verify successfully.
|
||||
replica: 1 # canary deployment size
|
||||
headers:
|
||||
- "foo:bar.*"
|
||||
```
|
||||
|
||||
Save this file to project root dir, and run:
|
||||
|
||||
```bash
|
||||
vela up
|
||||
```
|
||||
|
||||
It will build container image, render deployment manifests in yaml, and apply them to the server.
|
||||
|
||||
### Extensible Design
|
||||
|
||||
The Appfile could be extended with more configurations by adding more capabilities to the OAM system. The config fields in Appfile are strongly correlated to the [capabilities system of OAM](https://github.com/oam-dev/kubevela/blob/master/DESIGN.md#capability-register-and-discovery) – Config fields are registered in the capabilities system and exposed via a [CUE template](https://cuelang.org/).
|
||||
|
||||
Here is an example of a capability definition that platform builders register:
|
||||
|
||||
```yaml
|
||||
apiVersion: core.oam.dev/v1alpha2
|
||||
kind: WorkloadDefinition
|
||||
metadata:
|
||||
name: webservice
|
||||
spec:
|
||||
definitionRef:
|
||||
name: deployments.apps
|
||||
extension:
|
||||
template: |
|
||||
parameter: #webservice
|
||||
#webservice: {
|
||||
// +vela:cli:enabled=true
|
||||
// +vela:cli:usage=specify commands to run in container
|
||||
// +vela:cli:short=c
|
||||
cmd: [...string]
|
||||
|
||||
env: [...string]
|
||||
|
||||
files: [...string]
|
||||
|
||||
image: string
|
||||
}
|
||||
|
||||
output: {
|
||||
apiVersion: "apps/v1"
|
||||
kind: "Deployment"
|
||||
metadata:
|
||||
name: context.name
|
||||
spec: {
|
||||
selector: {
|
||||
matchLabels:
|
||||
app: context.name
|
||||
}
|
||||
template: {
|
||||
metadata:
|
||||
labels:
|
||||
app: context.name
|
||||
spec: {
|
||||
containers: [{
|
||||
name: context.name
|
||||
image: parameter.image
|
||||
command: parameter.cmd
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Apply the file to APIServer, and the fields will be extended into Appfile. Note that there are some conventions that differs Workloads and Traits, and around CLI flags. We will cover that more detailedly below.
|
||||
|
||||
## Goals
|
||||
|
||||
The Appfile design has the following goals:
|
||||
|
||||
1. Provide a user friendly, `docker-compose` style config format to developers.
|
||||
2. Configuration fields can be extended by registering more capabilities into OAM runtime.
|
||||
|
||||
In the following, we will discuss technical details of the proposed design.
|
||||
|
||||
## Proposal
|
||||
|
||||
### Registration via Definition/Capability
|
||||
|
||||
Vela allows platform builders to extend Appfile config fields by registering them via [capabilities system of OAM](https://github.com/oam-dev/kubevela/blob/master/DESIGN.md#capability-register-and-discovery).
|
||||
|
||||
The entire template should be put under `spec.extension.template` as raw string:
|
||||
|
||||
```yaml
|
||||
apiVersion: core.oam.dev/v1alpha2
|
||||
kind: WorkloadDefinition | TraitDefinition
|
||||
...
|
||||
spec:
|
||||
extension:
|
||||
template: |
|
||||
parameter: #webservice
|
||||
...
|
||||
```
|
||||
|
||||
By running `vela system update` or other similar commands, vela cli will read all definitions from APIServer and sink necessary information locally including templates. The templates will be further used to render final deploy manifests.
|
||||
|
||||
### Templating
|
||||
|
||||
Vela allows platform builders to write bespoke templates to extend Appfile configs.
|
||||
|
||||
#### Exposing Parameters
|
||||
|
||||
A template starts with `parameter` and its definition:
|
||||
|
||||
```yaml
|
||||
parameter: #webservice
|
||||
#webservice: {
|
||||
// +vela:cli:enabled=true
|
||||
// +vela:cli:usage=specify commands to run in container
|
||||
// +vela:cli:short=c
|
||||
cmd: [...string]
|
||||
}
|
||||
```
|
||||
|
||||
Here is the takeout:
|
||||
* The `parameter` defines the user input fields and is used to render final output with user input values. These fields will be exposed to users in Appfile.
|
||||
* The definition `#webservice` is used to tell the name of the template. This name is used to correlate workload and trait types to fields in Appfile.
|
||||
|
||||
Note that there is difference in how Workload and Trait expose parameters.
|
||||
|
||||
For Workload, each service will have a reserved field called `type` which is *webservice* by default.
|
||||
Then all parameters are exposed as first level field under the service.
|
||||
|
||||
```yaml
|
||||
services:
|
||||
express-server:
|
||||
# type: webservice (default) | task
|
||||
cmd: ["node", "server.js"]
|
||||
```
|
||||
|
||||
For Trait, its type will be used as the name to contain its parameters. There is a restriction that the trait type should not conflict any of the Workload parameters' first level name.
|
||||
|
||||
```yaml
|
||||
services:
|
||||
express-server:
|
||||
route: # trait type
|
||||
domain: example.com
|
||||
http: # match the longest prefix
|
||||
"/": 8080
|
||||
|
||||
# Workload parameters. The first level names do not conflict with trait type.
|
||||
cmd: ...
|
||||
env: ...
|
||||
```
|
||||
|
||||
|
||||
#### Rendering Outputs
|
||||
|
||||
A template should also have an `output` block:
|
||||
|
||||
```yaml
|
||||
output: {
|
||||
apiVersion: "apps/v1"
|
||||
kind: "Deployment"
|
||||
metadata:
|
||||
name: context.name
|
||||
spec: {
|
||||
...
|
||||
containers: [{
|
||||
name: context.name
|
||||
image: parameter.image
|
||||
command: parameter.cmd
|
||||
}]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Here is the takeout:
|
||||
* The object defined within `output` block will be the final manifest which is to `kubectl apply`.
|
||||
* `parameter` is used here to render user config values in.
|
||||
* A new object called `context` is used to render output. This is defined within vela-cli and vela-cli will fill its values based on each service dynamically. In above example, here is the value of the `context`:
|
||||
```yaml
|
||||
context:
|
||||
name: express-server
|
||||
```
|
||||
You can check the definition of `context` block via `vela template context`.
|
||||
|
||||
Note that a TraitDefinition can have multiple outputs. In such case, just dismiss the `output` block and provide `outputs` block:
|
||||
|
||||
```yaml
|
||||
outputs: service: {
|
||||
...
|
||||
}
|
||||
|
||||
outputs: ingress: {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Under the hood, vela-cli will iterate over all services and generate one AppConfig to contain them, and for each service generate one Component and multiple traits.
|
||||
|
||||
### CLI/UI Interoperability
|
||||
|
||||
For UI, The definition in a template will be used to generate v3 OpenAPI Schema and the UI will use that to render forms.
|
||||
|
||||
For CLI, a one level parameter can be exposed via CLI by adding the following "tags" in the comment:
|
||||
|
||||
```yaml
|
||||
parameter: #webservice
|
||||
#webservice: {
|
||||
// +vela:cli:enabled=true
|
||||
// +vela:cli:usage=specify commands to run in container
|
||||
// +vela:cli:short=c
|
||||
cmd: [...string]
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Here is the takeout:
|
||||
- The name of the parameter will be added as a flag, i.e. `--cmd`
|
||||
- "enabled" indicates whether this parameter should be exposed
|
||||
- "usage" is shown in help info
|
||||
- "short" is the short flag, i.e. `-c`
|
||||
|
||||
### `vela up`
|
||||
|
||||
The vela-cli will have an `up` command to provide seamless workflow experience. Provide an `vela.yml` Appfile in the same directory that you will run `vela up` and it is good to go. There is an example under `examples/testapp/` .
|
||||
|
||||
## Examples
|
||||
|
||||
## Multiple Services
|
||||
|
||||
```yaml
|
||||
services:
|
||||
frontend:
|
||||
build:
|
||||
image: oamdev/frontend:v1
|
||||
docker:
|
||||
file: ./frontend/Dockerfile
|
||||
context: ./frontend
|
||||
cmd: ["node", "server.js"]
|
||||
|
||||
backend:
|
||||
build:
|
||||
image: oamdev/backend:v1
|
||||
docker:
|
||||
file: ./backend/Dockerfile
|
||||
context: ./backend
|
||||
cmd: ["node", "server.js"]
|
||||
```
|
||||
|
||||
### Multiple Outputs in TraitDefinition
|
||||
|
||||
```yaml
|
||||
apiVersion: core.oam.dev/v1alpha2
|
||||
kind: TraitDefinition
|
||||
metadata:
|
||||
name: route
|
||||
spec:
|
||||
definitionRef:
|
||||
name: routes.standard.oam.dev
|
||||
extension:
|
||||
template: |
|
||||
parameter: #route
|
||||
#route: {
|
||||
domain: string
|
||||
http: [string]: int
|
||||
}
|
||||
|
||||
// trait template can have multiple outputs and they are all traits
|
||||
outputs: service: {
|
||||
apiVersion: "v1"
|
||||
kind: "Service"
|
||||
metadata:
|
||||
name: context.name
|
||||
spec: {
|
||||
selector:
|
||||
app: context.name
|
||||
ports: [
|
||||
for k, v in parameter.http {
|
||||
port: v
|
||||
targetPort: v
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
outputs: ingress: {
|
||||
apiVersion: "networking.k8s.io/v1beta1"
|
||||
kind: "Ingress"
|
||||
spec: {
|
||||
rules: [{
|
||||
host: parameter.domain
|
||||
http: {
|
||||
paths: [
|
||||
for k, v in parameter.http {
|
||||
path: k
|
||||
backend: {
|
||||
serviceName: context.name
|
||||
servicePort: v
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
```
|
||||
126
design/route.md
126
design/route.md
@@ -1,126 +0,0 @@
|
||||
# Route Trait Design
|
||||
|
||||
The main idea of route trait is to let users have an entrypoint to visit their App.
|
||||
|
||||
In k8s world, if you want to do so, you have to understand K8s [Serivce](https://kubernetes.io/docs/concepts/services-networking/service/)
|
||||
, [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/), [Ingress Controllers](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/).
|
||||
It's not easy to get all of these things work well.
|
||||
|
||||
The route trait will help you setup service, ingress automatically according your workload, along with the mTLS enabled.
|
||||
|
||||
The schema is also clean and easy to understand.
|
||||
|
||||
```go
|
||||
|
||||
// RouteSpec defines the desired state of Route
|
||||
type RouteSpec struct {
|
||||
// WorkloadReference to the workload whose metrics needs to be exposed
|
||||
WorkloadReference runtimev1alpha1.TypedReference `json:"workloadRef,omitempty"`
|
||||
|
||||
// Host is the host of the route
|
||||
Host string `json:"host"`
|
||||
|
||||
// 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"`
|
||||
|
||||
// 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 {
|
||||
// Path is location Path, default for "/"
|
||||
Path string `json:"path,omitempty"`
|
||||
|
||||
|
||||
// RewriteTarget will rewrite request from Path to RewriteTarget path.
|
||||
RewriteTarget string `json:"rewriteTarget,omitempty"`
|
||||
|
||||
// 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"`
|
||||
}
|
||||
|
||||
type TLS struct {
|
||||
IssuerName string `json:"issuerName,omitempty"`
|
||||
|
||||
// Type indicate the issuer is ClusterIssuer or NamespaceIssuer
|
||||
Type IssuerType `json:"type,omitempty"`
|
||||
}
|
||||
|
||||
type IssuerType string
|
||||
|
||||
const (
|
||||
ClusterIssuer IssuerType = "ClusterIssuer"
|
||||
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.
|
||||
type Backend struct {
|
||||
// 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
|
||||
BackendService *BackendServiceRef `json:"backendService,omitempty"`
|
||||
}
|
||||
|
||||
type BackendServiceRef struct {
|
||||
// Port allow you direct specify backend service port.
|
||||
Port intstr.IntOrString `json:"port,omitempty"`
|
||||
// ServiceName allow you direct specify K8s service for backend service.
|
||||
ServiceName string `json:"serviceName,omitempty"`
|
||||
}
|
||||
```
|
||||
|
||||
Route Trait specifies a target workload by using `workloadRef`, in OAM system, this field will be filled automatically
|
||||
by OAM runtime.
|
||||
|
||||
Besides `workloadRef`, one Route will have only one `host` and many rules. `host` is actually your app's visiting URL.
|
||||
It's required and will be used to generate mTLS secrets.
|
||||
|
||||
Route Trait designed to be compatible with different ingress controller implementations, the `provider` field will allow
|
||||
you to give a specified ingress controller type. Currently, only nginx-ingress is supported.
|
||||
|
||||
The `tls` field allow you to specify a TLS for this route with an IssuerName, the IssuerName pointing to an Issuer Object
|
||||
created by cert-manager. Cert-manager and ingress controller will handle certificate creation and binding.
|
||||
If not specified, a selfsigned issuer will be created.
|
||||
|
||||
If no rule specified, route trait will create one rule automatically and match with the port.
|
||||
|
||||
For every rule, we will create an ingress. In the rule, you could specify `path`, `rewriteTarget`, `customHeaders`
|
||||
and `defaultBackend`. All rules will using the same `tls`, `host` and `provider`.
|
||||
|
||||
`defaultBackend` will become the ingress default backend with K8s Object(apiVersion/kind/name).
|
||||
|
||||
`backend` of the rule is completely optional.
|
||||
|
||||
If backendService is specified, it will use it as backend of this rule. If not,
|
||||
the route trait can automatically discovery backend settings from workload.
|
||||
|
||||
## Discovery mechanism
|
||||
|
||||
1. Check ChildResource of the workload, if there already has an existing K8s service match the Backend port, use it.
|
||||
2. If there's no k8s service, this means we need to create one. In order to create K8s service, we need two information
|
||||
`Container Port` and `Pod SelectorLabels`.
|
||||
- 2.1 Use [`PodSpecable` mechanism](https://github.com/crossplane/oam-kubernetes-runtime/blob/master/design/one-pager-podspecable-workload.md),
|
||||
route trait will check `WorkloadDefinition` for podSpec field, with the `podSpec` field, we can easily find the container port.
|
||||
* If podSpecPath` is specified, we will use the workload labels as `Pod SelectorLabels`.
|
||||
* If `workload.oam.dev/podspecable: true` but no `podSpecPath`, will use `spec.Template` as `PodTemplate`, which means
|
||||
we can get `Pod SelectorLabels` from `spec.Template.Labels`.
|
||||
- 2.2 Use ChildResource: If No `PodSpecable` mechanism found in workload, we will continue discovery child resources of workload. If there
|
||||
is a valid `PodTemplate` structure in child resource, we will regard it as discovery target, use the same strategy like
|
||||
`workload.oam.dev/podspecable: true` but no `podSpecPath`.
|
||||
|
||||
@@ -32,17 +32,15 @@ the successful message.
|
||||
|
||||
sample request:
|
||||
```json
|
||||
{
|
||||
"envName": "e2",
|
||||
"namespace": "e2",
|
||||
"email": "e@gmail.com",
|
||||
"domain": "d.com"
|
||||
}
|
||||
{"envName":"ccc","namespace":"ccc"}
|
||||
```
|
||||
|
||||
sample response:
|
||||
```json
|
||||
{"code":200,"data":"environment e2 created, Namespace: e2, Email: e@gmail.com."}
|
||||
{
|
||||
"code": 200,
|
||||
"data": "Create env succeed"
|
||||
}
|
||||
```
|
||||
|
||||
### GET /api/envs/ (env list)
|
||||
@@ -109,7 +107,7 @@ sample response
|
||||
- example
|
||||
sample response
|
||||
```json
|
||||
{"code":200,"data":"Set environment succeed"}
|
||||
{"code":200,"data":"Set env succeed"}
|
||||
```
|
||||
|
||||
```json
|
||||
@@ -173,93 +171,44 @@ sample response
|
||||
sample response
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"data": {
|
||||
"Status": "True",
|
||||
"Components": [
|
||||
{
|
||||
"name": "web-comp",
|
||||
"Status": "True",
|
||||
"workload": {
|
||||
"apiVersion": "standard.oam.dev/v1alpha1",
|
||||
"kind": "PodSpecWorkload",
|
||||
"metadata": {
|
||||
"name": "web-comp"
|
||||
},
|
||||
"spec": {
|
||||
"podSpec": {
|
||||
"containers": [
|
||||
{
|
||||
"image": "nginx:1.9.4",
|
||||
"name": "web-comp",
|
||||
"ports": [
|
||||
{
|
||||
"containerPort": 80,
|
||||
"name": "default",
|
||||
"protocol": "TCP"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"replicas": 1
|
||||
}
|
||||
},
|
||||
"Traits": [
|
||||
{
|
||||
"trait": {
|
||||
"apiVersion": "standard.oam.dev/v1alpha1",
|
||||
"kind": "Route",
|
||||
"metadata": {
|
||||
"annotations": {
|
||||
"trait.oam.dev/name": "route"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"backend": {
|
||||
"port": 0
|
||||
},
|
||||
"host": "web-comp.poc.oam.dev",
|
||||
"path": "",
|
||||
"tls": {
|
||||
"issuerName": "oam-env-default"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "comp1",
|
||||
"Status": "True",
|
||||
"workload": {
|
||||
"apiVersion": "standard.oam.dev/v1alpha1",
|
||||
"kind": "PodSpecWorkload",
|
||||
"metadata": {
|
||||
"name": "comp1"
|
||||
},
|
||||
"spec": {
|
||||
"podSpec": {
|
||||
"containers": [
|
||||
{
|
||||
"image": "nginx:1.9.4",
|
||||
"name": "comp1",
|
||||
"ports": [
|
||||
{
|
||||
"containerPort": 6379,
|
||||
"name": "default",
|
||||
"protocol": "TCP"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"replicas": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
"code": 200,
|
||||
"data": {
|
||||
"Status": "UNKNOWN",
|
||||
"Workload": {
|
||||
"workload": {
|
||||
"apiVersion": "core.oam.dev/v1alpha2",
|
||||
"kind": "ContainerizedWorkload",
|
||||
"metadata": {
|
||||
"name": "poc5"
|
||||
},
|
||||
"spec": {
|
||||
"containers": [{
|
||||
"image": "nginx:1.9.4",
|
||||
"name": "poc5",
|
||||
"ports": [{
|
||||
"containerPort": 80,
|
||||
"name": "default",
|
||||
"protocol": "TCP"
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
},
|
||||
"Traits": [{
|
||||
"trait": {
|
||||
"apiVersion": "core.oam.dev/v1alpha2",
|
||||
"kind": "ManualScalerTrait",
|
||||
"metadata": {
|
||||
"annotations": {
|
||||
"vela.oam.dev/traitDef": "scale"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"replicaCount": 2
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
```
|
||||
### DELETE /api/envs/:envName/apps/:appName (app delete)
|
||||
@@ -272,84 +221,8 @@ sample response
|
||||
}
|
||||
```
|
||||
|
||||
## Components
|
||||
### GET /api/envs/:envName/apps/:appName/components/:compName (component details)
|
||||
- example
|
||||
sample response
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"data": {
|
||||
"name": "web-comp",
|
||||
"Status": "True",
|
||||
"workload": {
|
||||
"apiVersion": "standard.oam.dev/v1alpha1",
|
||||
"kind": "PodSpecWorkload",
|
||||
"metadata": {
|
||||
"name": "web-comp"
|
||||
},
|
||||
"spec": {
|
||||
"podSpec": {
|
||||
"containers": [
|
||||
{
|
||||
"image": "nginx:1.9.4",
|
||||
"name": "web-comp",
|
||||
"ports": [
|
||||
{
|
||||
"containerPort": 80,
|
||||
"name": "default",
|
||||
"protocol": "TCP"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"replicas": 1
|
||||
}
|
||||
},
|
||||
"Traits": [
|
||||
{
|
||||
"trait": {
|
||||
"apiVersion": "standard.oam.dev/v1alpha1",
|
||||
"kind": "Route",
|
||||
"metadata": {
|
||||
"annotations": {
|
||||
"trait.oam.dev/name": "route"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"backend": {
|
||||
"port": 0
|
||||
},
|
||||
"host": "web-comp.poc.oam.dev",
|
||||
"path": "",
|
||||
"tls": {
|
||||
"issuerName": "oam-env-default"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### GET /api/envs/:envName/apps/:appName/components/ (component list)
|
||||
Same as `GET /api/envs/:envName/apps/:appName (app description)`.
|
||||
|
||||
### DELETE /api/envs/:envName/apps/:appName/components/:compName (component delete)
|
||||
- example
|
||||
sample response
|
||||
```
|
||||
{
|
||||
"code": 200,
|
||||
"data": "delete apps succeed a1 from default"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Workloads
|
||||
### POST /api/workloads/ (workload create, component create)
|
||||
### POST /api/workloads/ (workload create)
|
||||
- parameters
|
||||
```go
|
||||
type WorkloadRunBody struct {
|
||||
@@ -379,7 +252,7 @@ sample request
|
||||
```json
|
||||
{
|
||||
"env_name": "default",
|
||||
"workload_type": "podspecworkload",
|
||||
"workload_type": "containerized",
|
||||
"workload_name": "poc2",
|
||||
"flags": [
|
||||
{
|
||||
@@ -405,7 +278,7 @@ Please also specify `traits` values if need to attach a trait to several traits
|
||||
```json
|
||||
{
|
||||
"env_name": "default",
|
||||
"workload_type": "podspecworkload",
|
||||
"workload_type": "containerized",
|
||||
"workload_name": "poc5",
|
||||
"app_group": "",
|
||||
"flags": [
|
||||
@@ -442,9 +315,9 @@ sample response
|
||||
{
|
||||
"code": 200,
|
||||
"data": {
|
||||
"name": "podspecworkload",
|
||||
"name": "containerized",
|
||||
"type": "workload",
|
||||
"template": "#Template: {\n\tapiVersion: \"core.oam.dev/v1alpha2\"\n\tkind: \"PodSpecWorkload\"\n\tmetadata: name: podspecworkload.name\n\tspec: {\n\t\tcontainers: [{\n\t\t\timage: containerized.image\n\t\t\tname: containerized.name\n\t\t\tports: [{\n\t\t\t\tcontainerPort: containerized.port\n\t\t\t\tprotocol: \"TCP\"\n\t\t\t\tname: \"default\"\n\t\t\t}]\n\t\t}]\n\t}\n}\ncontainerized: {\n\tname: string\n\t// +usage=specify app image\n\t// +short=i\n\timage: string\n\t// +usage=specify port for container\n\t// +short=p\n\tport: *6379 | int\n}\n",
|
||||
"template": "#Template: {\n\tapiVersion: \"core.oam.dev/v1alpha2\"\n\tkind: \"ContainerizedWorkload\"\n\tmetadata: name: containerized.name\n\tspec: {\n\t\tcontainers: [{\n\t\t\timage: containerized.image\n\t\t\tname: containerized.name\n\t\t\tports: [{\n\t\t\t\tcontainerPort: containerized.port\n\t\t\t\tprotocol: \"TCP\"\n\t\t\t\tname: \"default\"\n\t\t\t}]\n\t\t}]\n\t}\n}\ncontainerized: {\n\tname: string\n\t// +usage=specify app image\n\t// +short=i\n\timage: string\n\t// +usage=specify port for container\n\t// +short=p\n\tport: *6379 | int\n}\n",
|
||||
"parameters": [{
|
||||
"name": "name",
|
||||
"required": true,
|
||||
@@ -481,7 +354,7 @@ sample response
|
||||
{
|
||||
"code": 200,
|
||||
"data": [{
|
||||
"name": "podspecworkload",
|
||||
"name": "containerized",
|
||||
"parameters": [{
|
||||
"name": "name",
|
||||
"required": true,
|
||||
@@ -526,7 +399,7 @@ sample response
|
||||
```
|
||||
|
||||
## Trait
|
||||
### POST /envs/:envName/apps/:appName/components/:compName/traits/ (attach a trait)
|
||||
### POST /envs/:envName/apps/:appName/traits/ (attach a trait)
|
||||
- example
|
||||
sample request
|
||||
```json
|
||||
@@ -565,7 +438,7 @@ sample response
|
||||
}],
|
||||
"definition": "/Users/zhouzhengxi/.vela/capabilities/manualscalertraits.core.oam.dev.cue",
|
||||
"crdName": "manualscalertraits.core.oam.dev",
|
||||
"appliesTo": ["containerizedworkload"],
|
||||
"appliesTo": ["containerized"],
|
||||
"crdInfo": {
|
||||
"apiVersion": "core.oam.dev/v1alpha2",
|
||||
"kind": "ManualScalerTrait"
|
||||
@@ -586,20 +459,20 @@ sample response
|
||||
"data": [{
|
||||
"name": "manualscaler",
|
||||
"definition": "manualscalertraits.core.oam.dev",
|
||||
"applies_to": ["podspecworkload"]
|
||||
"applies_to": ["containerized"]
|
||||
}, {
|
||||
"name": "rollout",
|
||||
"definition": "simplerollouttraits.extend.oam.dev",
|
||||
"applies_to": ["podspecworkload", "deployment"]
|
||||
"applies_to": ["containerized", "deployment"]
|
||||
}, {
|
||||
"name": "scale",
|
||||
"definition": "manualscalertraits.core.oam.dev",
|
||||
"applies_to": ["podspecworkload", "deployment"]
|
||||
"applies_to": ["containerized", "deployment"]
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
### DELETE /envs/:envName/apps/:appName/components/:compName/traits/:traitName (detach a trait)
|
||||
### DELETE /envs/:envName/apps/:appName/traits/:traitName (detach a trait)
|
||||
- example
|
||||
sample response
|
||||
```json
|
||||
@@ -663,7 +536,7 @@ sample response
|
||||
- example
|
||||
sample response
|
||||
```json
|
||||
{"code":200,"data":"podspecworkload removed successfully"}
|
||||
{"code":200,"data":"containerized removed successfully"}
|
||||
```
|
||||
|
||||
### GET /api/capabilities/ (capability list)
|
||||
@@ -673,9 +546,9 @@ sample response
|
||||
{
|
||||
"code": 200,
|
||||
"data": [{
|
||||
"name": "podspecworkload",
|
||||
"name": "containerized",
|
||||
"type": "workload",
|
||||
"template": "#Template: {\n\tapiVersion: \"core.oam.dev/v1alpha2\"\n\tkind: \"ContainerizedWorkload\"\n\tmetadata: name: podspecworkload.name\n\tspec: {\n\t\tcontainers: [{\n\t\t\timage: containerized.image\n\t\t\tname: containerized.name\n\t\t\tports: [{\n\t\t\t\tcontainerPort: containerized.port\n\t\t\t\tprotocol: \"TCP\"\n\t\t\t\tname: \"default\"\n\t\t\t}]\n\t\t}]\n\t}\n}\ncontainerized: {\n\tname: string\n\t// +usage=specify app image\n\t// +short=i\n\timage: string\n\t// +usage=specify port for container\n\t// +short=p\n\tport: *6379 | int\n}\n",
|
||||
"template": "#Template: {\n\tapiVersion: \"core.oam.dev/v1alpha2\"\n\tkind: \"ContainerizedWorkload\"\n\tmetadata: name: containerized.name\n\tspec: {\n\t\tcontainers: [{\n\t\t\timage: containerized.image\n\t\t\tname: containerized.name\n\t\t\tports: [{\n\t\t\t\tcontainerPort: containerized.port\n\t\t\t\tprotocol: \"TCP\"\n\t\t\t\tname: \"default\"\n\t\t\t}]\n\t\t}]\n\t}\n}\ncontainerized: {\n\tname: string\n\t// +usage=specify app image\n\t// +short=i\n\timage: string\n\t// +usage=specify port for container\n\t// +short=p\n\tport: *6379 | int\n}\n",
|
||||
"parameters": [{
|
||||
"name": "name",
|
||||
"required": true,
|
||||
@@ -719,7 +592,7 @@ sample response
|
||||
"definition": "/Users/zhouzhengxi/.vela/centers/poc/.tmp/simplerollouttraits.extend.oam.dev.cue",
|
||||
"crdName": "simplerollouttraits.extend.oam.dev",
|
||||
"center": "poc",
|
||||
"appliesTo": ["podspecworkload", "deployment"],
|
||||
"appliesTo": ["containerized", "deployment"],
|
||||
"status": "uninstalled"
|
||||
}]
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
## vela
|
||||
|
||||
|
||||
✈️ A Micro App Platform for Kubernetes.
|
||||
|
||||
### Synopsis
|
||||
|
||||
|
||||
✈️ A Micro App Platform for Kubernetes.
|
||||
|
||||
```
|
||||
vela [flags]
|
||||
@@ -13,7 +13,7 @@ vela [flags]
|
||||
### Options
|
||||
|
||||
```
|
||||
-e, --env string specify environment name for application
|
||||
-e, --env string specify env name for application
|
||||
-h, --help help for vela
|
||||
```
|
||||
|
||||
@@ -25,17 +25,14 @@ vela [flags]
|
||||
* [vela completion](vela_completion.md) - Output shell completion code for the specified shell (bash or zsh)
|
||||
* [vela dashboard](vela_dashboard.md) - Setup API Server and launch Dashboard
|
||||
* [vela env](vela_env.md) - Manage application environments
|
||||
* [vela init](vela_init.md) - Init an OAM Application
|
||||
* [vela install](vela_install.md) - Initialize vela on both client and server
|
||||
* [vela logs](vela_logs.md) - Tail pods logs of an application
|
||||
* [vela metrics](vela_metrics.md) - Attach metrics trait to an app
|
||||
* [vela route](vela_route.md) - Attach route trait to an app
|
||||
* [vela manualscaler](vela_manualscaler.md) - Attach manualscaler trait to an app
|
||||
* [vela rollout](vela_rollout.md) - Attach rollout trait to an app
|
||||
* [vela scale](vela_scale.md) - Attach scale trait to an app
|
||||
* [vela system](vela_system.md) - system management utilities
|
||||
* [vela template](vela_template.md) - Manage templates
|
||||
* [vela traits](vela_traits.md) - List traits
|
||||
* [vela up](vela_up.md) - Apply an appfile
|
||||
* [vela version](vela_version.md) - Prints out build version information
|
||||
* [vela workloads](vela_workloads.md) - List workloads
|
||||
|
||||
###### Auto generated by spf13/cobra on 20-Oct-2020
|
||||
###### Auto generated by spf13/cobra on 11-Sep-2020
|
||||
|
||||
@@ -21,7 +21,7 @@ vela app <command>
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
-e, --env string specify environment name for application
|
||||
-e, --env string specify env name for application
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
@@ -33,4 +33,4 @@ vela app <command>
|
||||
* [vela app show](vela_app_show.md) - get details of your app
|
||||
* [vela app status](vela_app_status.md) - get status of an application
|
||||
|
||||
###### Auto generated by spf13/cobra on 20-Oct-2020
|
||||
###### Auto generated by spf13/cobra on 11-Sep-2020
|
||||
|
||||
@@ -25,11 +25,11 @@ vela app delete frontend
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
-e, --env string specify environment name for application
|
||||
-e, --env string specify env name for application
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
|
||||
* [vela app](vela_app.md) - Manage applications
|
||||
|
||||
###### Auto generated by spf13/cobra on 20-Oct-2020
|
||||
###### Auto generated by spf13/cobra on 11-Sep-2020
|
||||
|
||||
@@ -26,11 +26,11 @@ vela app ls
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
-e, --env string specify environment name for application
|
||||
-e, --env string specify env name for application
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
|
||||
* [vela app](vela_app.md) - Manage applications
|
||||
|
||||
###### Auto generated by spf13/cobra on 20-Oct-2020
|
||||
###### Auto generated by spf13/cobra on 11-Sep-2020
|
||||
|
||||
@@ -26,11 +26,11 @@ vela app run myAppBundle
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
-e, --env string specify environment name for application
|
||||
-e, --env string specify env name for application
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
|
||||
* [vela app](vela_app.md) - Manage applications
|
||||
|
||||
###### Auto generated by spf13/cobra on 20-Oct-2020
|
||||
###### Auto generated by spf13/cobra on 11-Sep-2020
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user