mirror of
https://github.com/kubevela/kubevela.git
synced 2026-03-02 01:30:47 +00:00
Compare commits
113 Commits
v1.3.0-alp
...
v1.3.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
825f1aaa22 | ||
|
|
82075427e6 | ||
|
|
f89cf673c0 | ||
|
|
ce53f6922f | ||
|
|
b6f70d9a3c | ||
|
|
64d063ccfe | ||
|
|
a98278fb7a | ||
|
|
0553d603e6 | ||
|
|
a36e99308f | ||
|
|
947bac2d35 | ||
|
|
7644cc59cb | ||
|
|
89a441b8ce | ||
|
|
780572c68f | ||
|
|
a13cab65b2 | ||
|
|
e26104adcc | ||
|
|
26ac584655 | ||
|
|
482976990d | ||
|
|
bc4812a12e | ||
|
|
58c2208e2a | ||
|
|
f83d88cfb0 | ||
|
|
8af3dec0df | ||
|
|
edebcc6c59 | ||
|
|
32382ba6be | ||
|
|
46ef6f9df4 | ||
|
|
aea98ff5bf | ||
|
|
c093676575 | ||
|
|
ed05b4b035 | ||
|
|
3aa4412a0f | ||
|
|
ef4b9816e1 | ||
|
|
1c5aab1852 | ||
|
|
966dbc1c74 | ||
|
|
4eafb46c87 | ||
|
|
a97a4d0ed7 | ||
|
|
77c02f9eec | ||
|
|
3157efd421 | ||
|
|
8ff93b33e2 | ||
|
|
c6b9abe4c4 | ||
|
|
150ef6e99e | ||
|
|
0ada407fbe | ||
|
|
c4af1ba643 | ||
|
|
de84421487 | ||
|
|
38a8a7f88a | ||
|
|
b4ddf0e4c3 | ||
|
|
47050c90b6 | ||
|
|
685d73a20c | ||
|
|
dde8a8e4c0 | ||
|
|
943af3ddf6 | ||
|
|
a5c2edf777 | ||
|
|
83d8022ce9 | ||
|
|
6d63014c6f | ||
|
|
d3fbd5fd45 | ||
|
|
b0202ebf14 | ||
|
|
295164229d | ||
|
|
ba09cf5c2e | ||
|
|
099e25a552 | ||
|
|
b2f5b69380 | ||
|
|
5d61cee3f6 | ||
|
|
2af198bda7 | ||
|
|
161d2646cb | ||
|
|
4f8e7506f9 | ||
|
|
160ef64855 | ||
|
|
905c49eb81 | ||
|
|
c4a8fcf29c | ||
|
|
e72690bade | ||
|
|
044c4bf73c | ||
|
|
795231ceb5 | ||
|
|
3f621e57b2 | ||
|
|
9fc992ea3e | ||
|
|
c2f5175fd1 | ||
|
|
a7d3cd5d1a | ||
|
|
ccfab6ce7f | ||
|
|
03cd0d144a | ||
|
|
741544c00c | ||
|
|
723a5d83ca | ||
|
|
8af5afa5dc | ||
|
|
aaa1db8760 | ||
|
|
c5baa1cae9 | ||
|
|
eda7e6c5a0 | ||
|
|
e5fd150cd5 | ||
|
|
d041d8c35d | ||
|
|
345e4c8144 | ||
|
|
9a8ec5d797 | ||
|
|
d9a676a688 | ||
|
|
9a3ad7ef84 | ||
|
|
9671e3b232 | ||
|
|
0c97f8311c | ||
|
|
a6460d67b6 | ||
|
|
3ea2ac6d0f | ||
|
|
13c420dada | ||
|
|
6354912bba | ||
|
|
5209be6da9 | ||
|
|
8f9908e723 | ||
|
|
296c82344b | ||
|
|
2d19454a35 | ||
|
|
f67d2db0d1 | ||
|
|
3634ad6f18 | ||
|
|
6c5a40d768 | ||
|
|
c91a7ac273 | ||
|
|
b437cf4310 | ||
|
|
040d5e1776 | ||
|
|
7bec3506f5 | ||
|
|
efc1597317 | ||
|
|
38665e319d | ||
|
|
1e0f329304 | ||
|
|
1300a980f0 | ||
|
|
b6b81c336e | ||
|
|
e2275efe56 | ||
|
|
c054ee32b1 | ||
|
|
19424cfaa4 | ||
|
|
a5fb09814e | ||
|
|
c1b116b360 | ||
|
|
3af893950e | ||
|
|
20583e089a |
4
.github/CODEOWNERS
vendored
4
.github/CODEOWNERS
vendored
@@ -1,7 +1,7 @@
|
||||
# This file is a github code protect rule follow the codeowners https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/creating-a-repository-on-github/about-code-owners#example-of-a-codeowners-file
|
||||
|
||||
* @hongchaodeng @wonderflow @leejanee
|
||||
design/ @hongchaodeng @resouer @wonderflow
|
||||
* @barnettZQG @wonderflow @leejanee
|
||||
design/ @barnettZQG @leejanee @wonderflow
|
||||
|
||||
# Owner of CUE
|
||||
pkg/cue @leejanee @FogDong
|
||||
|
||||
8
.github/workflows/apiserver-test.yaml
vendored
8
.github/workflows/apiserver-test.yaml
vendored
@@ -65,7 +65,7 @@ jobs:
|
||||
- name: Setup Kind Cluster (Worker)
|
||||
run: |
|
||||
kind delete cluster --name worker
|
||||
kind create cluster --image kindest/node:v1.18.15@sha256:5c1b980c4d0e0e8e7eb9f36f7df525d079a96169c8a8f20d8bd108c0d0889cc4 --name worker
|
||||
kind create cluster --image kindest/node:v1.20.7@sha256:688fba5ce6b825be62a7c7fe1415b35da2bdfbb5a69227c499ea4cc0008661ca --name worker
|
||||
kubectl version
|
||||
kubectl cluster-info
|
||||
kind get kubeconfig --name worker --internal > /tmp/worker.kubeconfig
|
||||
@@ -74,7 +74,7 @@ jobs:
|
||||
- name: Setup Kind Cluster (Hub)
|
||||
run: |
|
||||
kind delete cluster
|
||||
kind create cluster --image kindest/node:v1.18.15@sha256:5c1b980c4d0e0e8e7eb9f36f7df525d079a96169c8a8f20d8bd108c0d0889cc4
|
||||
kind create cluster --image kindest/node:v1.20.7@sha256:688fba5ce6b825be62a7c7fe1415b35da2bdfbb5a69227c499ea4cc0008661ca
|
||||
kubectl version
|
||||
kubectl cluster-info
|
||||
|
||||
@@ -92,10 +92,10 @@ jobs:
|
||||
kubectl wait --for=condition=Ready pod -l app=source-controller -n flux-system --timeout=600s
|
||||
kubectl wait --for=condition=Ready pod -l app=helm-controller -n flux-system --timeout=600s
|
||||
|
||||
- name: Run apiserver unit test
|
||||
- name: Run api server unit test
|
||||
run: make unit-test-apiserver
|
||||
|
||||
- name: Run apiserver e2e test
|
||||
- name: Run api server e2e test
|
||||
run: |
|
||||
export ALIYUN_ACCESS_KEY_ID=${{ secrets.ALIYUN_ACCESS_KEY_ID }}
|
||||
export ALIYUN_ACCESS_KEY_SECRET=${{ secrets.ALIYUN_ACCESS_KEY_SECRET }}
|
||||
|
||||
6
.github/workflows/e2e-multicluster-test.yml
vendored
6
.github/workflows/e2e-multicluster-test.yml
vendored
@@ -60,7 +60,7 @@ jobs:
|
||||
- name: Setup Kind Cluster (Worker)
|
||||
run: |
|
||||
kind delete cluster --name worker
|
||||
kind create cluster --image kindest/node:v1.18.15@sha256:5c1b980c4d0e0e8e7eb9f36f7df525d079a96169c8a8f20d8bd108c0d0889cc4 --name worker
|
||||
kind create cluster --image kindest/node:v1.20.7@sha256:688fba5ce6b825be62a7c7fe1415b35da2bdfbb5a69227c499ea4cc0008661ca --name worker
|
||||
kubectl version
|
||||
kubectl cluster-info
|
||||
kind get kubeconfig --name worker --internal > /tmp/worker.kubeconfig
|
||||
@@ -69,7 +69,7 @@ jobs:
|
||||
- name: Setup Kind Cluster (Hub)
|
||||
run: |
|
||||
kind delete cluster
|
||||
kind create cluster --image kindest/node:v1.18.15@sha256:5c1b980c4d0e0e8e7eb9f36f7df525d079a96169c8a8f20d8bd108c0d0889cc4
|
||||
kind create cluster --image kindest/node:v1.20.7@sha256:688fba5ce6b825be62a7c7fe1415b35da2bdfbb5a69227c499ea4cc0008661ca
|
||||
kubectl version
|
||||
kubectl cluster-info
|
||||
|
||||
@@ -96,7 +96,7 @@ jobs:
|
||||
uses: codecov/codecov-action@v1
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
files: /tmp/e2e-profile.out
|
||||
files: /tmp/e2e-profile.out,/tmp/e2e_multicluster_test.out
|
||||
flags: e2e-multicluster-test
|
||||
name: codecov-umbrella
|
||||
|
||||
|
||||
2
.github/workflows/e2e-rollout-test.yml
vendored
2
.github/workflows/e2e-rollout-test.yml
vendored
@@ -60,7 +60,7 @@ jobs:
|
||||
- name: Setup Kind Cluster
|
||||
run: |
|
||||
kind delete cluster
|
||||
kind create cluster --image kindest/node:v1.18.15@sha256:5c1b980c4d0e0e8e7eb9f36f7df525d079a96169c8a8f20d8bd108c0d0889cc4
|
||||
kind create cluster --image kindest/node:v1.20.7@sha256:688fba5ce6b825be62a7c7fe1415b35da2bdfbb5a69227c499ea4cc0008661ca
|
||||
kubectl version
|
||||
kubectl cluster-info
|
||||
|
||||
|
||||
2
.github/workflows/e2e-test.yml
vendored
2
.github/workflows/e2e-test.yml
vendored
@@ -60,7 +60,7 @@ jobs:
|
||||
- name: Setup Kind Cluster
|
||||
run: |
|
||||
kind delete cluster
|
||||
kind create cluster --image kindest/node:v1.18.15@sha256:5c1b980c4d0e0e8e7eb9f36f7df525d079a96169c8a8f20d8bd108c0d0889cc4
|
||||
kind create cluster --image kindest/node:v1.20.7@sha256:688fba5ce6b825be62a7c7fe1415b35da2bdfbb5a69227c499ea4cc0008661ca
|
||||
kubectl version
|
||||
kubectl cluster-info
|
||||
|
||||
|
||||
7
.github/workflows/go.yml
vendored
7
.github/workflows/go.yml
vendored
@@ -71,6 +71,11 @@ jobs:
|
||||
if: needs.detect-noop.outputs.noop != 'true'
|
||||
|
||||
steps:
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
@@ -88,7 +93,7 @@ jobs:
|
||||
# version, but we prefer this action because it leaves 'annotations' (i.e.
|
||||
# it comments on PRs to point out linter violations).
|
||||
- name: Lint
|
||||
uses: golangci/golangci-lint-action@v2
|
||||
uses: golangci/golangci-lint-action@v3
|
||||
with:
|
||||
version: ${{ env.GOLANGCI_VERSION }}
|
||||
|
||||
|
||||
6
.github/workflows/issue-commands.yml
vendored
6
.github/workflows/issue-commands.yml
vendored
@@ -14,9 +14,9 @@ jobs:
|
||||
with:
|
||||
repository: "oam-dev/kubevela-github-actions"
|
||||
path: ./actions
|
||||
ref: v0.4.1
|
||||
ref: v0.4.2
|
||||
- name: Install Actions
|
||||
run: npm install --production --prefix ./actions
|
||||
run: npm ci --production --prefix ./actions
|
||||
- name: Run Commands
|
||||
uses: ./actions/commands
|
||||
with:
|
||||
@@ -66,4 +66,4 @@ jobs:
|
||||
uses: zeebe-io/backport-action@v0.0.6
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
github_workspace: ${{ github.workspace }}
|
||||
github_workspace: ${{ github.workspace }}
|
||||
|
||||
3
Makefile
3
Makefile
@@ -19,7 +19,7 @@ unit-test-core:
|
||||
go test -coverprofile=coverage.txt $(shell go list ./pkg/... ./cmd/... ./apis/... | grep -v apiserver)
|
||||
go test $(shell go list ./references/... | grep -v apiserver)
|
||||
unit-test-apiserver:
|
||||
go test -coverprofile=coverage.txt $(shell go list ./pkg/... ./cmd/... | grep -E 'apiserver|velaql')
|
||||
go test -gcflags=all=-l -coverprofile=coverage.txt $(shell go list ./pkg/... ./cmd/... | grep -E 'apiserver|velaql')
|
||||
|
||||
# Build vela cli binary
|
||||
build: fmt vet lint staticcheck vela-cli kubectl-vela
|
||||
@@ -132,5 +132,4 @@ def-install:
|
||||
|
||||
helm-doc-gen: helmdoc
|
||||
readme-generator -v charts/vela-core/values.yaml -r charts/vela-core/README.md
|
||||
cat charts/vela-core/README.md
|
||||
readme-generator -v charts/vela-minimal/values.yaml -r charts/vela-minimal/README.md
|
||||
@@ -7,6 +7,9 @@ Reviewers:
|
||||
- reetasingh
|
||||
- wangwang
|
||||
- evanli18
|
||||
- devholic
|
||||
- fourierr
|
||||
- JooKS-me
|
||||
|
||||
Approvers:
|
||||
- Somefive (Multi-Cluster)
|
||||
@@ -26,6 +29,7 @@ Maintainers:
|
||||
- leejanee
|
||||
- zzxwill
|
||||
- BinaryHB0916
|
||||
- dhiguero
|
||||
|
||||
Emeritus Members:
|
||||
- ryanzhang-oss
|
||||
|
||||
@@ -51,7 +51,8 @@ Full documentation is available on the [KubeVela website](https://kubevela.io/).
|
||||
- Wechat Group (*Chinese*): Broker wechat to add you into the user group.
|
||||
|
||||
<img src="https://static.kubevela.net/images/barnett-wechat.jpg" width="200" />
|
||||
- Bi-weekly Community Call: [Meeting Notes](https://docs.google.com/document/d/1nqdFEyULekyksFHtFvgvFAYE-0AMHKoS3RMnaKsarjs)
|
||||
- Bi-weekly Community Call: [Meeting Notes](https://docs.google.com/document/d/1nqdFEyULekyksFHtFvgvFAYE-0AMHKoS3RMnaKsarjs).
|
||||
- Bi-weekly Chinese Community Call: [Video Records](https://space.bilibili.com/180074935/channel/seriesdetail?sid=1842207).
|
||||
|
||||
## Talks and Conferences
|
||||
|
||||
|
||||
@@ -322,6 +322,23 @@ type PolicyStatus struct {
|
||||
Status *runtime.RawExtension `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// WorkflowStep defines how to execute a workflow step.
|
||||
type WorkflowStep struct {
|
||||
// Name is the unique name of the workflow step.
|
||||
Name string `json:"name"`
|
||||
|
||||
Type string `json:"type"`
|
||||
|
||||
// +kubebuilder:pruning:PreserveUnknownFields
|
||||
Properties *runtime.RawExtension `json:"properties,omitempty"`
|
||||
|
||||
DependsOn []string `json:"dependsOn,omitempty"`
|
||||
|
||||
Inputs StepInputs `json:"inputs,omitempty"`
|
||||
|
||||
Outputs StepOutputs `json:"outputs,omitempty"`
|
||||
}
|
||||
|
||||
// WorkflowStatus record the status of workflow
|
||||
type WorkflowStatus struct {
|
||||
AppRevision string `json:"appRevision,omitempty"`
|
||||
@@ -605,3 +622,17 @@ func ParseApplicationConditionType(s string) (ApplicationConditionType, error) {
|
||||
}
|
||||
return -1, errors.New("unknown condition type")
|
||||
}
|
||||
|
||||
// ReferredObject the referred Kubernetes object
|
||||
type ReferredObject struct {
|
||||
// +kubebuilder:validation:EmbeddedResource
|
||||
// +kubebuilder:pruning:PreserveUnknownFields
|
||||
runtime.RawExtension `json:",inline"`
|
||||
}
|
||||
|
||||
// ReferredObjectList a list of referred Kubernetes objects
|
||||
type ReferredObjectList struct {
|
||||
// Objects a list of Kubernetes objects.
|
||||
// +optional
|
||||
Objects []ReferredObject `json:"objects,omitempty"`
|
||||
}
|
||||
|
||||
@@ -469,6 +469,44 @@ func (in *RawExtensionPointer) DeepCopy() *RawExtensionPointer {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ReferredObject) DeepCopyInto(out *ReferredObject) {
|
||||
*out = *in
|
||||
in.RawExtension.DeepCopyInto(&out.RawExtension)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReferredObject.
|
||||
func (in *ReferredObject) DeepCopy() *ReferredObject {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ReferredObject)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ReferredObjectList) DeepCopyInto(out *ReferredObjectList) {
|
||||
*out = *in
|
||||
if in.Objects != nil {
|
||||
in, out := &in.Objects, &out.Objects
|
||||
*out = make([]ReferredObject, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReferredObjectList.
|
||||
func (in *ReferredObjectList) DeepCopy() *ReferredObjectList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ReferredObjectList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Revision) DeepCopyInto(out *Revision) {
|
||||
*out = *in
|
||||
@@ -636,6 +674,41 @@ func (in *WorkflowStatus) DeepCopy() *WorkflowStatus {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *WorkflowStep) DeepCopyInto(out *WorkflowStep) {
|
||||
*out = *in
|
||||
if in.Properties != nil {
|
||||
in, out := &in.Properties, &out.Properties
|
||||
*out = new(runtime.RawExtension)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.DependsOn != nil {
|
||||
in, out := &in.DependsOn, &out.DependsOn
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Inputs != nil {
|
||||
in, out := &in.Inputs, &out.Inputs
|
||||
*out = make(StepInputs, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Outputs != nil {
|
||||
in, out := &in.Outputs, &out.Outputs
|
||||
*out = make(StepOutputs, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkflowStep.
|
||||
func (in *WorkflowStep) DeepCopy() *WorkflowStep {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(WorkflowStep)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *WorkflowStepStatus) DeepCopyInto(out *WorkflowStepStatus) {
|
||||
*out = *in
|
||||
|
||||
74
apis/core.oam.dev/v1alpha1/component_types.go
Normal file
74
apis/core.oam.dev/v1alpha1/component_types.go
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
Copyright 2021 The KubeVela Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1alpha1
|
||||
|
||||
const (
|
||||
// RefObjectsComponentType refers to the type of ref-objects
|
||||
RefObjectsComponentType = "ref-objects"
|
||||
)
|
||||
|
||||
// RefObjectsComponentSpec defines the spec of ref-objects component
|
||||
type RefObjectsComponentSpec struct {
|
||||
// Objects the referrers to the Kubernetes objects
|
||||
Objects []ObjectReferrer `json:"objects,omitempty"`
|
||||
}
|
||||
|
||||
// ObjectReferrer selects Kubernetes objects
|
||||
type ObjectReferrer struct {
|
||||
// ObjectTypeIdentifier identifies the type of referred objects
|
||||
ObjectTypeIdentifier `json:",inline"`
|
||||
// ObjectSelector select object by name or labelSelector
|
||||
ObjectSelector `json:",inline"`
|
||||
}
|
||||
|
||||
// ObjectTypeIdentifier identifies the scheme of Kubernetes object
|
||||
type ObjectTypeIdentifier struct {
|
||||
// Resource is the resource name of the Kubernetes object.
|
||||
Resource string `json:"resource"`
|
||||
// Group is the API Group of the Kubernetes object.
|
||||
Group string `json:"group"`
|
||||
// LegacyObjectTypeIdentifier is the legacy identifier
|
||||
// Deprecated: use resource/group instead
|
||||
LegacyObjectTypeIdentifier `json:",inline"`
|
||||
}
|
||||
|
||||
// LegacyObjectTypeIdentifier legacy object type identifier
|
||||
type LegacyObjectTypeIdentifier struct {
|
||||
// APIVersion is the APIVersion of the Kubernetes object.
|
||||
APIVersion string `json:"apiVersion"`
|
||||
// APIVersion is the Kind of the Kubernetes object.
|
||||
Kind string `json:"kind"`
|
||||
}
|
||||
|
||||
// ObjectSelector selector for Kubernetes object
|
||||
type ObjectSelector struct {
|
||||
// Name is the name of the Kubernetes object.
|
||||
// If empty, it will inherit the application component's name.
|
||||
Name string `json:"name,omitempty"`
|
||||
// Namespace is the namespace for selecting Kubernetes objects.
|
||||
// If empty, it will inherit the application's namespace.
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
// Cluster is the cluster for selecting Kubernetes objects.
|
||||
// If empty, it will use the local cluster
|
||||
Cluster string `json:"cluster,omitempty"`
|
||||
// LabelSelector selects Kubernetes objects by labels
|
||||
// Exclusive to "name"
|
||||
LabelSelector map[string]string `json:"labelSelector,omitempty"`
|
||||
// DeprecatedLabelSelector a deprecated alias to LabelSelector
|
||||
// Deprecated: use labelSelector instead.
|
||||
DeprecatedLabelSelector map[string]string `json:"selector,omitempty"`
|
||||
}
|
||||
@@ -20,7 +20,7 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
|
||||
)
|
||||
|
||||
// +kubebuilder:object:root=true
|
||||
@@ -61,7 +61,7 @@ type Workflow struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
Steps []v1beta1.WorkflowStep `json:"steps,omitempty"`
|
||||
Steps []common.WorkflowStep `json:"steps,omitempty"`
|
||||
}
|
||||
|
||||
// +kubebuilder:object:root=true
|
||||
|
||||
@@ -46,10 +46,11 @@ type GarbageCollectPolicyRule struct {
|
||||
|
||||
// GarbageCollectPolicyRuleSelector select the targets of the rule
|
||||
// if both traitTypes and componentTypes are specified, combination logic is OR
|
||||
// if one resources are specified with conflict strategy, strategy as component go first.
|
||||
// if one resource is specified with conflict strategies, strategy as component go first.
|
||||
type GarbageCollectPolicyRuleSelector struct {
|
||||
TraitTypes []string `json:"traitTypes"`
|
||||
CompNames []string `json:"componentNames"`
|
||||
CompTypes []string `json:"componentTypes"`
|
||||
TraitTypes []string `json:"traitTypes"`
|
||||
}
|
||||
|
||||
// GarbageCollectStrategy the strategy for target resource to recycle
|
||||
@@ -68,27 +69,22 @@ const (
|
||||
// FindStrategy find gc strategy for target resource
|
||||
func (in GarbageCollectPolicySpec) FindStrategy(manifest *unstructured.Unstructured) *GarbageCollectStrategy {
|
||||
for _, rule := range in.Rules {
|
||||
var (
|
||||
compType string
|
||||
traitType string
|
||||
)
|
||||
if manifest.GetLabels() != nil {
|
||||
traitType = manifest.GetLabels()[oam.TraitTypeLabel]
|
||||
compType = manifest.GetLabels()[oam.WorkloadTypeLabel]
|
||||
var compName, compType, traitType string
|
||||
if labels := manifest.GetLabels(); labels != nil {
|
||||
compName = labels[oam.LabelAppComponent]
|
||||
compType = labels[oam.WorkloadTypeLabel]
|
||||
traitType = labels[oam.TraitTypeLabel]
|
||||
}
|
||||
if compType != "" {
|
||||
for _, _compType := range rule.Selector.CompTypes {
|
||||
if _compType == compType {
|
||||
return &rule.Strategy
|
||||
}
|
||||
match := func(src []string, val string) (found bool) {
|
||||
for _, _val := range src {
|
||||
found = found || _val == val
|
||||
}
|
||||
return val != "" && found
|
||||
}
|
||||
if traitType != "" {
|
||||
for _, _traitType := range rule.Selector.TraitTypes {
|
||||
if _traitType == traitType {
|
||||
return &rule.Strategy
|
||||
}
|
||||
}
|
||||
if match(rule.Selector.CompNames, compName) ||
|
||||
match(rule.Selector.CompTypes, compType) ||
|
||||
match(rule.Selector.TraitTypes, traitType) {
|
||||
return &rule.Strategy
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -32,7 +32,7 @@ func TestGarbageCollectPolicySpec_FindStrategy(t *testing.T) {
|
||||
notFound bool
|
||||
expectStrategy GarbageCollectStrategy
|
||||
}{
|
||||
"trait rule match": {
|
||||
"trait type rule match": {
|
||||
rules: []GarbageCollectPolicyRule{{
|
||||
Selector: GarbageCollectPolicyRuleSelector{TraitTypes: []string{"a"}},
|
||||
Strategy: GarbageCollectStrategyNever,
|
||||
@@ -44,7 +44,7 @@ func TestGarbageCollectPolicySpec_FindStrategy(t *testing.T) {
|
||||
}},
|
||||
expectStrategy: GarbageCollectStrategyNever,
|
||||
},
|
||||
"trait rule mismatch": {
|
||||
"trait type rule mismatch": {
|
||||
rules: []GarbageCollectPolicyRule{{
|
||||
Selector: GarbageCollectPolicyRuleSelector{TraitTypes: []string{"a"}},
|
||||
Strategy: GarbageCollectStrategyNever,
|
||||
@@ -52,7 +52,7 @@ func TestGarbageCollectPolicySpec_FindStrategy(t *testing.T) {
|
||||
input: &unstructured.Unstructured{Object: map[string]interface{}{}},
|
||||
notFound: true,
|
||||
},
|
||||
"trait rule multiple match": {
|
||||
"trait type rule multiple match": {
|
||||
rules: []GarbageCollectPolicyRule{{
|
||||
Selector: GarbageCollectPolicyRuleSelector{TraitTypes: []string{"a"}},
|
||||
Strategy: GarbageCollectStrategyOnAppDelete,
|
||||
@@ -67,7 +67,7 @@ func TestGarbageCollectPolicySpec_FindStrategy(t *testing.T) {
|
||||
}},
|
||||
expectStrategy: GarbageCollectStrategyOnAppDelete,
|
||||
},
|
||||
"component rule match": {
|
||||
"component type rule match": {
|
||||
rules: []GarbageCollectPolicyRule{{
|
||||
Selector: GarbageCollectPolicyRuleSelector{CompTypes: []string{"comp"}},
|
||||
Strategy: GarbageCollectStrategyNever,
|
||||
@@ -79,7 +79,7 @@ func TestGarbageCollectPolicySpec_FindStrategy(t *testing.T) {
|
||||
}},
|
||||
expectStrategy: GarbageCollectStrategyNever,
|
||||
},
|
||||
"rule match both component and trait, component first": {
|
||||
"rule match both component type and trait type, component type first": {
|
||||
rules: []GarbageCollectPolicyRule{
|
||||
{
|
||||
Selector: GarbageCollectPolicyRuleSelector{CompTypes: []string{"comp"}},
|
||||
@@ -97,6 +97,18 @@ func TestGarbageCollectPolicySpec_FindStrategy(t *testing.T) {
|
||||
}},
|
||||
expectStrategy: GarbageCollectStrategyNever,
|
||||
},
|
||||
"component name rule match": {
|
||||
rules: []GarbageCollectPolicyRule{{
|
||||
Selector: GarbageCollectPolicyRuleSelector{CompNames: []string{"comp-name"}},
|
||||
Strategy: GarbageCollectStrategyNever,
|
||||
}},
|
||||
input: &unstructured.Unstructured{Object: map[string]interface{}{
|
||||
"metadata": map[string]interface{}{
|
||||
"labels": map[string]interface{}{oam.LabelAppComponent: "comp-name"},
|
||||
},
|
||||
}},
|
||||
expectStrategy: GarbageCollectStrategyNever,
|
||||
},
|
||||
}
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
|
||||
@@ -25,8 +25,25 @@ const (
|
||||
|
||||
// TopologyPolicySpec defines the spec of topology policy
|
||||
type TopologyPolicySpec struct {
|
||||
Clusters []string `json:"clusters,omitempty"`
|
||||
ClusterSelector map[string]string `json:"clusterSelector,omitempty"`
|
||||
// Placement embeds the selectors for choosing cluster
|
||||
Placement `json:",inline"`
|
||||
// Namespace is the target namespace to deploy in the selected clusters.
|
||||
// +optional
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
}
|
||||
|
||||
// Placement describes which clusters to be selected in this topology
|
||||
type Placement struct {
|
||||
// Clusters is the names of the clusters to select.
|
||||
Clusters []string `json:"clusters,omitempty"`
|
||||
|
||||
// ClusterLabelSelector is the label selector for clusters.
|
||||
// Exclusive to "clusters"
|
||||
ClusterLabelSelector map[string]string `json:"clusterLabelSelector,omitempty"`
|
||||
|
||||
// DeprecatedClusterSelector is a depreciated alias for ClusterLabelSelector.
|
||||
// Deprecated: Use clusterLabelSelector instead.
|
||||
DeprecatedClusterSelector map[string]string `json:"clusterSelector,omitempty"`
|
||||
}
|
||||
|
||||
// OverridePolicySpec defines the spec of override policy
|
||||
|
||||
@@ -38,6 +38,18 @@ var (
|
||||
AddToScheme = SchemeBuilder.AddToScheme
|
||||
)
|
||||
|
||||
// Policy meta
|
||||
var (
|
||||
PolicyKind = "Policy"
|
||||
PolicyGroupVersionKind = SchemeGroupVersion.WithKind(PolicyKind)
|
||||
)
|
||||
|
||||
// Workflow meta
|
||||
var (
|
||||
WorkflowKind = "Workflow"
|
||||
WorkflowGroupVersionKind = SchemeGroupVersion.WithKind(WorkflowKind)
|
||||
)
|
||||
|
||||
func init() {
|
||||
SchemeBuilder.Register(&Policy{}, &PolicyList{})
|
||||
SchemeBuilder.Register(&Workflow{}, &WorkflowList{})
|
||||
|
||||
@@ -25,7 +25,6 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
@@ -282,8 +281,8 @@ func (in *GarbageCollectPolicyRule) DeepCopy() *GarbageCollectPolicyRule {
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *GarbageCollectPolicyRuleSelector) DeepCopyInto(out *GarbageCollectPolicyRuleSelector) {
|
||||
*out = *in
|
||||
if in.TraitTypes != nil {
|
||||
in, out := &in.TraitTypes, &out.TraitTypes
|
||||
if in.CompNames != nil {
|
||||
in, out := &in.CompNames, &out.CompNames
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
@@ -292,6 +291,11 @@ func (in *GarbageCollectPolicyRuleSelector) DeepCopyInto(out *GarbageCollectPoli
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.TraitTypes != nil {
|
||||
in, out := &in.TraitTypes, &out.TraitTypes
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GarbageCollectPolicyRuleSelector.
|
||||
@@ -326,6 +330,21 @@ func (in *GarbageCollectPolicySpec) DeepCopy() *GarbageCollectPolicySpec {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *LegacyObjectTypeIdentifier) DeepCopyInto(out *LegacyObjectTypeIdentifier) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LegacyObjectTypeIdentifier.
|
||||
func (in *LegacyObjectTypeIdentifier) DeepCopy() *LegacyObjectTypeIdentifier {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(LegacyObjectTypeIdentifier)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *NamespaceSelector) DeepCopyInto(out *NamespaceSelector) {
|
||||
*out = *in
|
||||
@@ -348,6 +367,68 @@ func (in *NamespaceSelector) DeepCopy() *NamespaceSelector {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ObjectReferrer) DeepCopyInto(out *ObjectReferrer) {
|
||||
*out = *in
|
||||
out.ObjectTypeIdentifier = in.ObjectTypeIdentifier
|
||||
in.ObjectSelector.DeepCopyInto(&out.ObjectSelector)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectReferrer.
|
||||
func (in *ObjectReferrer) DeepCopy() *ObjectReferrer {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ObjectReferrer)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ObjectSelector) DeepCopyInto(out *ObjectSelector) {
|
||||
*out = *in
|
||||
if in.LabelSelector != nil {
|
||||
in, out := &in.LabelSelector, &out.LabelSelector
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
if in.DeprecatedLabelSelector != nil {
|
||||
in, out := &in.DeprecatedLabelSelector, &out.DeprecatedLabelSelector
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectSelector.
|
||||
func (in *ObjectSelector) DeepCopy() *ObjectSelector {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ObjectSelector)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ObjectTypeIdentifier) DeepCopyInto(out *ObjectTypeIdentifier) {
|
||||
*out = *in
|
||||
out.LegacyObjectTypeIdentifier = in.LegacyObjectTypeIdentifier
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectTypeIdentifier.
|
||||
func (in *ObjectTypeIdentifier) DeepCopy() *ObjectTypeIdentifier {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ObjectTypeIdentifier)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *OverridePolicySpec) DeepCopyInto(out *OverridePolicySpec) {
|
||||
*out = *in
|
||||
@@ -375,6 +456,40 @@ func (in *OverridePolicySpec) DeepCopy() *OverridePolicySpec {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Placement) DeepCopyInto(out *Placement) {
|
||||
*out = *in
|
||||
if in.Clusters != nil {
|
||||
in, out := &in.Clusters, &out.Clusters
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.ClusterLabelSelector != nil {
|
||||
in, out := &in.ClusterLabelSelector, &out.ClusterLabelSelector
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
if in.DeprecatedClusterSelector != nil {
|
||||
in, out := &in.DeprecatedClusterSelector, &out.DeprecatedClusterSelector
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Placement.
|
||||
func (in *Placement) DeepCopy() *Placement {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Placement)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *PlacementDecision) DeepCopyInto(out *PlacementDecision) {
|
||||
*out = *in
|
||||
@@ -453,22 +568,33 @@ func (in *PolicyList) DeepCopyObject() runtime.Object {
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TopologyPolicySpec) DeepCopyInto(out *TopologyPolicySpec) {
|
||||
func (in *RefObjectsComponentSpec) DeepCopyInto(out *RefObjectsComponentSpec) {
|
||||
*out = *in
|
||||
if in.Clusters != nil {
|
||||
in, out := &in.Clusters, &out.Clusters
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.ClusterSelector != nil {
|
||||
in, out := &in.ClusterSelector, &out.ClusterSelector
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
if in.Objects != nil {
|
||||
in, out := &in.Objects, &out.Objects
|
||||
*out = make([]ObjectReferrer, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RefObjectsComponentSpec.
|
||||
func (in *RefObjectsComponentSpec) DeepCopy() *RefObjectsComponentSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(RefObjectsComponentSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TopologyPolicySpec) DeepCopyInto(out *TopologyPolicySpec) {
|
||||
*out = *in
|
||||
in.Placement.DeepCopyInto(&out.Placement)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TopologyPolicySpec.
|
||||
func (in *TopologyPolicySpec) DeepCopy() *TopologyPolicySpec {
|
||||
if in == nil {
|
||||
@@ -486,7 +612,7 @@ func (in *Workflow) DeepCopyInto(out *Workflow) {
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
if in.Steps != nil {
|
||||
in, out := &in.Steps, &out.Steps
|
||||
*out = make([]v1beta1.WorkflowStep, len(*in))
|
||||
*out = make([]common.WorkflowStep, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
|
||||
@@ -50,21 +50,7 @@ type AppPolicy struct {
|
||||
}
|
||||
|
||||
// WorkflowStep defines how to execute a workflow step.
|
||||
type WorkflowStep struct {
|
||||
// Name is the unique name of the workflow step.
|
||||
Name string `json:"name"`
|
||||
|
||||
Type string `json:"type"`
|
||||
|
||||
// +kubebuilder:pruning:PreserveUnknownFields
|
||||
Properties *runtime.RawExtension `json:"properties,omitempty"`
|
||||
|
||||
DependsOn []string `json:"dependsOn,omitempty"`
|
||||
|
||||
Inputs common.StepInputs `json:"inputs,omitempty"`
|
||||
|
||||
Outputs common.StepOutputs `json:"outputs,omitempty"`
|
||||
}
|
||||
type WorkflowStep common.WorkflowStep
|
||||
|
||||
// Workflow defines workflow steps and other attributes
|
||||
type Workflow struct {
|
||||
|
||||
@@ -17,11 +17,10 @@
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha1"
|
||||
)
|
||||
|
||||
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
|
||||
@@ -52,19 +51,23 @@ type ApplicationRevisionSpec struct {
|
||||
// ScopeGVK records the apiVersion to GVK mapping
|
||||
ScopeGVK map[string]metav1.GroupVersionKind `json:"scopeGVK,omitempty"`
|
||||
|
||||
// Components records the rendered components from Application, it will contains the whole K8s CR of workload in it.
|
||||
// +deprecated
|
||||
Components []common.RawComponent `json:"components,omitempty"`
|
||||
// Policies records the external policies
|
||||
Policies map[string]v1alpha1.Policy `json:"policies,omitempty"`
|
||||
|
||||
// ApplicationConfiguration records the rendered applicationConfiguration from Application,
|
||||
// it will contains the whole K8s CR of trait and the reference component in it.
|
||||
// +kubebuilder:validation:EmbeddedResource
|
||||
// Workflow records the external workflow
|
||||
Workflow *v1alpha1.Workflow `json:"workflow,omitempty"`
|
||||
|
||||
// ReferredObjects records the referred objects used in the ref-object typed components
|
||||
// +kubebuilder:pruning:PreserveUnknownFields
|
||||
// +deprecated
|
||||
ApplicationConfiguration runtime.RawExtension `json:"applicationConfiguration,omitempty"`
|
||||
ReferredObjects []common.ReferredObject `json:"referredObjects,omitempty"`
|
||||
}
|
||||
|
||||
// ResourcesConfigMap references the ConfigMap that's generated to contain all final rendered resources.
|
||||
ResourcesConfigMap corev1.LocalObjectReference `json:"resourcesConfigMap,omitempty"`
|
||||
// ApplicationRevisionStatus is the status of ApplicationRevision
|
||||
type ApplicationRevisionStatus struct {
|
||||
// Succeeded records if the workflow finished running with success
|
||||
Succeeded bool `json:"succeeded"`
|
||||
// Workflow the running status of the workflow
|
||||
Workflow *common.WorkflowStatus `json:"workflow,omitempty"`
|
||||
}
|
||||
|
||||
// +kubebuilder:object:root=true
|
||||
@@ -72,14 +75,18 @@ type ApplicationRevisionSpec struct {
|
||||
// ApplicationRevision is the Schema for the ApplicationRevision API
|
||||
// +kubebuilder:storageversion
|
||||
// +kubebuilder:resource:categories={oam},shortName=apprev
|
||||
// +kubebuilder:subresource:status
|
||||
// +kubebuilder:printcolumn:name="AGE",type=date,JSONPath=".metadata.creationTimestamp"
|
||||
// +kubebuilder:printcolumn:name="PUBLISH_VERSION",type=string,JSONPath=`.metadata.annotations['app\.oam\.dev\/publishVersion']`
|
||||
// +kubebuilder:printcolumn:name="SUCCEEDED",type=string,JSONPath=`.status.succeeded`
|
||||
// +genclient
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
type ApplicationRevision struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
Spec ApplicationRevisionSpec `json:"spec,omitempty"`
|
||||
Spec ApplicationRevisionSpec `json:"spec,omitempty"`
|
||||
Status ApplicationRevisionStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// +kubebuilder:object:root=true
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha1"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
@@ -113,6 +114,7 @@ func (in *ApplicationRevision) DeepCopyInto(out *ApplicationRevision) {
|
||||
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 ApplicationRevision.
|
||||
@@ -218,15 +220,25 @@ func (in *ApplicationRevisionSpec) DeepCopyInto(out *ApplicationRevisionSpec) {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
if in.Components != nil {
|
||||
in, out := &in.Components, &out.Components
|
||||
*out = make([]common.RawComponent, len(*in))
|
||||
if in.Policies != nil {
|
||||
in, out := &in.Policies, &out.Policies
|
||||
*out = make(map[string]v1alpha1.Policy, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = *val.DeepCopy()
|
||||
}
|
||||
}
|
||||
if in.Workflow != nil {
|
||||
in, out := &in.Workflow, &out.Workflow
|
||||
*out = new(v1alpha1.Workflow)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.ReferredObjects != nil {
|
||||
in, out := &in.ReferredObjects, &out.ReferredObjects
|
||||
*out = make([]common.ReferredObject, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
in.ApplicationConfiguration.DeepCopyInto(&out.ApplicationConfiguration)
|
||||
out.ResourcesConfigMap = in.ResourcesConfigMap
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationRevisionSpec.
|
||||
@@ -239,6 +251,26 @@ func (in *ApplicationRevisionSpec) DeepCopy() *ApplicationRevisionSpec {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ApplicationRevisionStatus) DeepCopyInto(out *ApplicationRevisionStatus) {
|
||||
*out = *in
|
||||
if in.Workflow != nil {
|
||||
in, out := &in.Workflow, &out.Workflow
|
||||
*out = new(common.WorkflowStatus)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationRevisionStatus.
|
||||
func (in *ApplicationRevisionStatus) DeepCopy() *ApplicationRevisionStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ApplicationRevisionStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ApplicationSpec) DeepCopyInto(out *ApplicationSpec) {
|
||||
*out = *in
|
||||
|
||||
39
apis/types/multicluster.go
Normal file
39
apis/types/multicluster.go
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
Copyright 2021 The KubeVela Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package types
|
||||
|
||||
import (
|
||||
"github.com/oam-dev/cluster-gateway/pkg/apis/cluster/v1alpha1"
|
||||
"github.com/oam-dev/cluster-gateway/pkg/config"
|
||||
)
|
||||
|
||||
const (
|
||||
// CredentialTypeInternal identifies the virtual cluster from internal kubevela system
|
||||
CredentialTypeInternal v1alpha1.CredentialType = "Internal"
|
||||
// CredentialTypeOCMManagedCluster identifies the virtual cluster from ocm
|
||||
CredentialTypeOCMManagedCluster v1alpha1.CredentialType = "ManagedCluster"
|
||||
// ClusterBlankEndpoint identifies the endpoint of a cluster as blank (not available)
|
||||
ClusterBlankEndpoint = "-"
|
||||
|
||||
// ClustersArg indicates the argument for specific clusters to install addon
|
||||
ClustersArg = "clusters"
|
||||
)
|
||||
|
||||
var (
|
||||
// AnnotationClusterAlias the annotation key for cluster alias
|
||||
AnnotationClusterAlias = config.MetaApiGroupName + "/cluster-alias"
|
||||
)
|
||||
@@ -41,6 +41,8 @@ var DefaultKubeVelaNS = "vela-system"
|
||||
const (
|
||||
// AnnoDefinitionDescription is the annotation which describe what is the capability used for in a WorkloadDefinition/TraitDefinition Object
|
||||
AnnoDefinitionDescription = "definition.oam.dev/description"
|
||||
// AnnoDefinitionIcon is the annotation which describe the icon url
|
||||
AnnoDefinitionIcon = "definition.oam.dev/icon"
|
||||
// AnnoDefinitionAppliedWorkloads is the annotation which describe what is the workloads used for in a TraitDefinition Object
|
||||
AnnoDefinitionAppliedWorkloads = "definition.oam.dev/appliedWorkloads"
|
||||
// LabelDefinition is the label for definition
|
||||
@@ -59,6 +61,22 @@ const (
|
||||
AnnoIngressControllerHTTPSPort = "ingress.controller/https-port"
|
||||
// AnnoIngressControllerHTTPPort define ingress controller listen port for http
|
||||
AnnoIngressControllerHTTPPort = "ingress.controller/http-port"
|
||||
// LabelConfigType is the label for config type
|
||||
LabelConfigType = "config.oam.dev/type"
|
||||
// LabelConfigCatalog is the label for config catalog
|
||||
LabelConfigCatalog = "config.oam.dev/catalog"
|
||||
// LabelConfigSubType is the sub-type for a config type
|
||||
LabelConfigSubType = "config.oam.dev/sub-type"
|
||||
// LabelConfigProject is the label for config project
|
||||
LabelConfigProject = "config.oam.dev/project"
|
||||
// LabelConfigSyncToMultiCluster is the label to decide whether a config will be synchronized to multi-cluster
|
||||
LabelConfigSyncToMultiCluster = "config.oam.dev/multi-cluster"
|
||||
// LabelConfigIdentifier is the label for config identifier
|
||||
LabelConfigIdentifier = "config.oam.dev/identifier"
|
||||
// LabelConfigDescription is the label for config description
|
||||
LabelConfigDescription = "config.oam.dev/description"
|
||||
// AnnotationConfigAlias is the annotation for config alias
|
||||
AnnotationConfigAlias = "config.oam.dev/alias"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -116,3 +134,17 @@ var DefaultFilterAnnots = []string{
|
||||
oam.AnnotationFilterAnnotationKeys,
|
||||
oam.AnnotationLastAppliedConfiguration,
|
||||
}
|
||||
|
||||
// ConfigType is the type of config
|
||||
type ConfigType string
|
||||
|
||||
const (
|
||||
// TerraformProvider is the config type for terraform provider
|
||||
TerraformProvider = "terraform-provider"
|
||||
// DexConnector is the config type for dex connector
|
||||
DexConnector = "config-dex-connector"
|
||||
// ImageRegistry is the config type for image registry
|
||||
ImageRegistry = "config-image-registry"
|
||||
// HelmRepository is the config type for Helm chart repository
|
||||
HelmRepository = "config-helm-repository"
|
||||
)
|
||||
|
||||
@@ -86,7 +86,7 @@ helm install --create-namespace -n vela-system kubevela kubevela/vela-core --wai
|
||||
| `multicluster.clusterGateway.replicaCount` | ClusterGateway replica count | `1` |
|
||||
| `multicluster.clusterGateway.port` | ClusterGateway port | `9443` |
|
||||
| `multicluster.clusterGateway.image.repository` | ClusterGateway image repository | `oamdev/cluster-gateway` |
|
||||
| `multicluster.clusterGateway.image.tag` | ClusterGateway image tag | `v1.1.7` |
|
||||
| `multicluster.clusterGateway.image.tag` | ClusterGateway image tag | `v1.3.2` |
|
||||
| `multicluster.clusterGateway.image.pullPolicy` | ClusterGateway image pull policy | `IfNotPresent` |
|
||||
| `multicluster.clusterGateway.resources.limits.cpu` | ClusterGateway cpu limit | `100m` |
|
||||
| `multicluster.clusterGateway.resources.limits.memory` | ClusterGateway memory limit | `200Mi` |
|
||||
@@ -125,18 +125,20 @@ helm install --create-namespace -n vela-system kubevela kubevela/vela-core --wai
|
||||
| `kubeClient.burst` | The burst for reconcile clients, default is 100 | `100` |
|
||||
|
||||
|
||||
## Uninstalling the Chart
|
||||
## Uninstallation
|
||||
|
||||
To uninstall/delete the KubeVela helm release
|
||||
### Vela CLI
|
||||
|
||||
To uninstall KubeVela, you can just run the following command by vela CLI:
|
||||
|
||||
```shell
|
||||
$ helm uninstall -n vela-system kubevela
|
||||
vela uninstall --force
|
||||
```
|
||||
|
||||
The command removes all the Kubernetes components associated with kubevela and deletes the release.
|
||||
### Helm CLI
|
||||
|
||||
**Notice**: You must disable all the addons before uninstallation, this is a script for convenience.
|
||||
|
||||
**Notice**: If you enable fluxcd addon when install the chart by set `enableFluxcdAddon=true` .Uninstall wouldn't disable the fluxcd addon ,and it will be kept in the cluster.Please guarantee there is no application in cluster use this addon and disable it firstly before uninstall the helm chart.
|
||||
You can use this script to disable all addons.
|
||||
```shell
|
||||
#! /bin/sh
|
||||
addon=$(vela addon list|grep enabled|awk {'print $1'})
|
||||
@@ -156,6 +158,15 @@ if [ $fluxcd ]; then
|
||||
fi
|
||||
```
|
||||
|
||||
To uninstall the KubeVela helm release:
|
||||
|
||||
```shell
|
||||
$ helm uninstall -n vela-system kubevela
|
||||
```
|
||||
|
||||
Finally, this command will remove all the Kubernetes resources associated with KubeVela and remove this chart release.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2025,6 +2025,12 @@ spec:
|
||||
- jsonPath: .metadata.creationTimestamp
|
||||
name: AGE
|
||||
type: date
|
||||
- jsonPath: .metadata.annotations['app\.oam\.dev\/publishVersion']
|
||||
name: PUBLISH_VERSION
|
||||
type: string
|
||||
- jsonPath: .status.succeeded
|
||||
name: SUCCEEDED
|
||||
type: string
|
||||
name: v1beta1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
@@ -2747,13 +2753,6 @@ spec:
|
||||
type: object
|
||||
type: object
|
||||
type: object
|
||||
applicationConfiguration:
|
||||
description: ApplicationConfiguration records the rendered applicationConfiguration
|
||||
from Application, it will contains the whole K8s CR of trait and
|
||||
the reference component in it.
|
||||
type: object
|
||||
x-kubernetes-embedded-resource: true
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
componentDefinitions:
|
||||
additionalProperties:
|
||||
description: ComponentDefinition is the Schema for the componentdefinitions
|
||||
@@ -3087,20 +3086,51 @@ spec:
|
||||
description: ComponentDefinitions records the snapshot of the componentDefinitions
|
||||
related with the created/modified Application
|
||||
type: object
|
||||
components:
|
||||
description: Components records the rendered components from Application,
|
||||
it will contains the whole K8s CR of workload in it.
|
||||
items:
|
||||
description: RawComponent record raw component
|
||||
policies:
|
||||
additionalProperties:
|
||||
description: Policy is the Schema for the policy API
|
||||
properties:
|
||||
raw:
|
||||
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:
|
||||
properties:
|
||||
annotations:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
finalizers:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
labels:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
name:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
type: object
|
||||
properties:
|
||||
type: object
|
||||
x-kubernetes-embedded-resource: true
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
type:
|
||||
type: string
|
||||
required:
|
||||
- raw
|
||||
- type
|
||||
type: object
|
||||
type: array
|
||||
description: Policies records the external policies
|
||||
type: object
|
||||
policyDefinitions:
|
||||
additionalProperties:
|
||||
description: PolicyDefinition is the Schema for the policydefinitions
|
||||
@@ -3377,15 +3407,16 @@ spec:
|
||||
description: PolicyDefinitions records the snapshot of the PolicyDefinitions
|
||||
related with the created/modified Application
|
||||
type: object
|
||||
resourcesConfigMap:
|
||||
description: ResourcesConfigMap references the ConfigMap that's generated
|
||||
to contain all final rendered resources.
|
||||
properties:
|
||||
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
|
||||
type: object
|
||||
referredObjects:
|
||||
description: ReferredObjects records the referred objects used in
|
||||
the ref-object typed components
|
||||
items:
|
||||
description: ReferredObject the referred Kubernetes object
|
||||
type: object
|
||||
x-kubernetes-embedded-resource: true
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: array
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
scopeDefinitions:
|
||||
additionalProperties:
|
||||
description: A ScopeDefinition registers a kind of Kubernetes custom
|
||||
@@ -3819,6 +3850,89 @@ spec:
|
||||
description: TraitDefinitions records the snapshot of the traitDefinitions
|
||||
related with the created/modified Application
|
||||
type: object
|
||||
workflow:
|
||||
description: Workflow records the external workflow
|
||||
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:
|
||||
properties:
|
||||
annotations:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
finalizers:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
labels:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
name:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
type: object
|
||||
steps:
|
||||
items:
|
||||
description: WorkflowStep defines how to execute a workflow
|
||||
step.
|
||||
properties:
|
||||
dependsOn:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
inputs:
|
||||
description: StepInputs defines variable input of WorkflowStep
|
||||
items:
|
||||
properties:
|
||||
from:
|
||||
type: string
|
||||
parameterKey:
|
||||
type: string
|
||||
required:
|
||||
- from
|
||||
- parameterKey
|
||||
type: object
|
||||
type: array
|
||||
name:
|
||||
description: Name is the unique name of the workflow step.
|
||||
type: string
|
||||
outputs:
|
||||
description: StepOutputs defines output variable of WorkflowStep
|
||||
items:
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
valueFrom:
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
- valueFrom
|
||||
type: object
|
||||
type: array
|
||||
properties:
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
type:
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
- type
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
workflowStepDefinitions:
|
||||
additionalProperties:
|
||||
description: WorkflowStepDefinition is the Schema for the workflowstepdefinitions
|
||||
@@ -4408,10 +4522,182 @@ spec:
|
||||
required:
|
||||
- application
|
||||
type: object
|
||||
status:
|
||||
description: ApplicationRevisionStatus is the status of ApplicationRevision
|
||||
properties:
|
||||
succeeded:
|
||||
description: Succeeded records if the workflow finished running with
|
||||
success
|
||||
type: boolean
|
||||
workflow:
|
||||
description: Workflow the running status of the workflow
|
||||
properties:
|
||||
appRevision:
|
||||
type: string
|
||||
contextBackend:
|
||||
description: 'ObjectReference contains enough information to let
|
||||
you inspect or modify the referred object. --- New uses of this
|
||||
type are discouraged because of difficulty describing its usage
|
||||
when embedded in APIs. 1. Ignored fields. It includes many
|
||||
fields which are not generally honored. For instance, ResourceVersion
|
||||
and FieldPath are both very rarely valid in actual usage. 2.
|
||||
Invalid usage help. It is impossible to add specific help for
|
||||
individual usage. In most embedded usages, there are particular restrictions
|
||||
like, "must refer only to types A and B" or "UID not honored"
|
||||
or "name must be restricted". Those cannot be well described
|
||||
when embedded. 3. Inconsistent validation. Because the usages
|
||||
are different, the validation rules are different by usage,
|
||||
which makes it hard for users to predict what will happen. 4.
|
||||
The fields are both imprecise and overly precise. Kind is not
|
||||
a precise mapping to a URL. This can produce ambiguity during
|
||||
interpretation and require a REST mapping. In most cases, the
|
||||
dependency is on the group,resource tuple and the version
|
||||
of the actual struct is irrelevant. 5. We cannot easily change
|
||||
it. Because this type is embedded in many locations, updates
|
||||
to this type will affect numerous schemas. Don''t make
|
||||
new APIs embed an underspecified API type they do not control.
|
||||
Instead of using this type, create a locally provided and used
|
||||
type that is well-focused on your reference. For example, ServiceReferences
|
||||
for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533
|
||||
.'
|
||||
properties:
|
||||
apiVersion:
|
||||
description: API version of the referent.
|
||||
type: string
|
||||
fieldPath:
|
||||
description: 'If referring to a piece of an object instead
|
||||
of an entire object, this string should contain a valid
|
||||
JSON/Go field access statement, such as desiredState.manifest.containers[2].
|
||||
For example, if the object reference is to a container within
|
||||
a pod, this would take on a value like: "spec.containers{name}"
|
||||
(where "name" refers to the name of the container that triggered
|
||||
the event) or if no container name is specified "spec.containers[2]"
|
||||
(container with index 2 in this pod). This syntax is chosen
|
||||
only to have some well-defined way of referencing a part
|
||||
of an object. TODO: this design is not final and this field
|
||||
is subject to change in the future.'
|
||||
type: string
|
||||
kind:
|
||||
description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
name:
|
||||
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
|
||||
type: string
|
||||
namespace:
|
||||
description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
|
||||
type: string
|
||||
resourceVersion:
|
||||
description: 'Specific resourceVersion to which this reference
|
||||
is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
|
||||
type: string
|
||||
uid:
|
||||
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
|
||||
type: string
|
||||
type: object
|
||||
finished:
|
||||
type: boolean
|
||||
message:
|
||||
type: string
|
||||
mode:
|
||||
description: WorkflowMode describes the mode of workflow
|
||||
type: string
|
||||
startTime:
|
||||
format: date-time
|
||||
type: string
|
||||
steps:
|
||||
items:
|
||||
description: WorkflowStepStatus record the status of a workflow
|
||||
step
|
||||
properties:
|
||||
firstExecuteTime:
|
||||
description: FirstExecuteTime is the first time this step
|
||||
execution.
|
||||
format: date-time
|
||||
type: string
|
||||
id:
|
||||
type: string
|
||||
lastExecuteTime:
|
||||
description: LastExecuteTime is the last time this step
|
||||
execution.
|
||||
format: date-time
|
||||
type: string
|
||||
message:
|
||||
description: A human readable message indicating details
|
||||
about why the workflowStep is in this state.
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
phase:
|
||||
description: WorkflowStepPhase describes the phase of a
|
||||
workflow step.
|
||||
type: string
|
||||
reason:
|
||||
description: A brief CamelCase message indicating details
|
||||
about why the workflowStep is in this state.
|
||||
type: string
|
||||
subSteps:
|
||||
description: SubStepsStatus record the status of workflow
|
||||
steps.
|
||||
properties:
|
||||
mode:
|
||||
description: WorkflowMode describes the mode of workflow
|
||||
type: string
|
||||
stepIndex:
|
||||
type: integer
|
||||
steps:
|
||||
items:
|
||||
description: WorkflowSubStepStatus record the status
|
||||
of a workflow step
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
message:
|
||||
description: A human readable message indicating
|
||||
details about why the workflowStep is in this
|
||||
state.
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
phase:
|
||||
description: WorkflowStepPhase describes the phase
|
||||
of a workflow step.
|
||||
type: string
|
||||
reason:
|
||||
description: A brief CamelCase message indicating
|
||||
details about why the workflowStep is in this
|
||||
state.
|
||||
type: string
|
||||
type:
|
||||
type: string
|
||||
required:
|
||||
- id
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
type:
|
||||
type: string
|
||||
required:
|
||||
- id
|
||||
type: object
|
||||
type: array
|
||||
suspend:
|
||||
type: boolean
|
||||
terminated:
|
||||
type: boolean
|
||||
required:
|
||||
- finished
|
||||
- mode
|
||||
- suspend
|
||||
- terminated
|
||||
type: object
|
||||
required:
|
||||
- succeeded
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
subresources: {}
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
|
||||
@@ -27,9 +27,5 @@ Welcome to use the KubeVela! Enjoy your shipping application journey!
|
||||
| . \| |_| || |_) || __/ \ V /| __/| || (_| |
|
||||
|_|\_\\__,_||_.__/ \___| \_/ \___||_| \__,_|
|
||||
|
||||
** Please note before uninstalling **
|
||||
|
||||
If you enable fluxcd addon when install the chart by set `enableFluxcdAddon=true` .
|
||||
Uninstall wouldn't disable the fluxcd addon ,and it will be kept in the cluster.
|
||||
Please guarantee there is no application in cluster using this addon and disable it firstly before uninstall the helm chart.
|
||||
And you can find the script of one-short disable all addons from the uninstalling section of https://github.com/oam-dev/kubevela/blob/master/charts/vela-core/README.md.
|
||||
You can refer to https://kubevela.io for more details.
|
||||
|
||||
@@ -7,10 +7,8 @@ data:
|
||||
registries: '{
|
||||
"KubeVela":{
|
||||
"name": "KubeVela",
|
||||
"oss": {
|
||||
"end_point": "https://addons.kubevela.net",
|
||||
"bucket": "",
|
||||
"path": ""
|
||||
"helm": {
|
||||
"url": "https://addons.kubevela.net"
|
||||
}
|
||||
}
|
||||
}'
|
||||
|
||||
@@ -89,9 +89,19 @@ spec:
|
||||
{{ end }}
|
||||
---
|
||||
{{ if .Values.multicluster.enabled }}
|
||||
# 1. Check whether APIService ""v1alpha1.cluster.core.oam.dev" is already present in the cluster
|
||||
# 2.a If the APIService doesn't exist, create it.
|
||||
# 2.b If the APIService exists without helm-chart related annotation, skip creating it to the
|
||||
# cluster because the APIService can be managed by an external controller.
|
||||
# 2.c If the APIService exists with valid helm-chart annotations, which means that the APIService
|
||||
# is previously managed by helm commands, hence update the APIService consistently.
|
||||
{{ $apiSvc := (lookup "apiregistration.k8s.io/v1" "APIService" "" "v1alpha1.cluster.core.oam.dev") }}
|
||||
{{ $shouldAdopt := (not $apiSvc) }}
|
||||
{{ if not $shouldAdopt }}{{ $shouldAdopt = (index ($apiSvc).metadata.annotations "meta.helm.sh/release-name") }}{{ end }}
|
||||
{{ if not $shouldAdopt }}
|
||||
{{ if $apiSvc.metadata.annotations }}
|
||||
{{ $shouldAdopt = (index ($apiSvc).metadata.annotations "meta.helm.sh/release-name") }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ if $shouldAdopt }}
|
||||
apiVersion: apiregistration.k8s.io/v1
|
||||
kind: APIService
|
||||
|
||||
@@ -16,17 +16,20 @@ spec:
|
||||
schematic:
|
||||
cue:
|
||||
template: |
|
||||
// +patchStrategy=jsonMergePatch
|
||||
patch: {
|
||||
metadata: annotations: {
|
||||
for k, v in parameter {
|
||||
"\(k)": v
|
||||
}
|
||||
}
|
||||
spec: template: metadata: annotations: {
|
||||
for k, v in parameter {
|
||||
"\(k)": v
|
||||
if context.output.spec != _|_ && context.output.spec.template != _|_ {
|
||||
spec: template: metadata: annotations: {
|
||||
for k, v in parameter {
|
||||
"\(k)": v
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
parameter: [string]: string
|
||||
parameter: [string]: string | null
|
||||
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
# Code generated by KubeVela templates. DO NOT EDIT. Please edit the original cue file.
|
||||
# Definition source cue file: vela-templates/definitions/internal/config-image-registry.cue
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: ComponentDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
custom.definition.oam.dev/alias.config.oam.dev: Image Registry
|
||||
definition.oam.dev/description: Config information to authenticate image registry
|
||||
labels:
|
||||
custom.definition.oam.dev/catalog.config.oam.dev: velacore-config
|
||||
custom.definition.oam.dev/multi-cluster.config.oam.dev: "true"
|
||||
custom.definition.oam.dev/type.config.oam.dev: image-registry
|
||||
name: config-image-registry
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
schematic:
|
||||
cue:
|
||||
template: |
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
output: {
|
||||
apiVersion: "v1"
|
||||
kind: "Secret"
|
||||
metadata: {
|
||||
name: context.name
|
||||
namespace: context.namespace
|
||||
labels: {
|
||||
"config.oam.dev/catalog": "velacore-config"
|
||||
"config.oam.dev/type": "image-registry"
|
||||
"config.oam.dev/multi-cluster": "true"
|
||||
"config.oam.dev/identifier": parameter.registry
|
||||
"config.oam.dev/sub-type": "auth"
|
||||
}
|
||||
}
|
||||
type: "kubernetes.io/dockerconfigjson"
|
||||
stringData: {
|
||||
if parameter.auth != _|_ {
|
||||
".dockerconfigjson": json.Marshal({
|
||||
auths: "\(parameter.registry)": {
|
||||
username: parameter.auth.username
|
||||
password: parameter.auth.password
|
||||
if parameter.auth.email != _|_ {
|
||||
email: parameter.auth.email
|
||||
}
|
||||
auth: base64.Encode(null, (parameter.auth.username + ":" + parameter.auth.password))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
parameter: {
|
||||
// +usage=Image registry FQDN
|
||||
registry: string
|
||||
// +usage=Authenticate the image registry
|
||||
auth?: {
|
||||
// +usage=Private Image registry username
|
||||
username: string
|
||||
// +usage=Private Image registry password
|
||||
password: string
|
||||
// +usage=Private Image registry email
|
||||
email?: string
|
||||
}
|
||||
}
|
||||
workload:
|
||||
type: autodetects.core.oam.dev
|
||||
|
||||
308
charts/vela-core/templates/defwithtemplate/cron-task.yaml
Normal file
308
charts/vela-core/templates/defwithtemplate/cron-task.yaml
Normal file
@@ -0,0 +1,308 @@
|
||||
# Code generated by KubeVela templates. DO NOT EDIT. Please edit the original cue file.
|
||||
# Definition source cue file: vela-templates/definitions/internal/cron-task.cue
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: ComponentDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Describes cron jobs that run code or a script to completion.
|
||||
name: cron-task
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
schematic:
|
||||
cue:
|
||||
template: |
|
||||
output: {
|
||||
apiVersion: "batch/v1beta1"
|
||||
kind: "CronJob"
|
||||
spec: {
|
||||
schedule: parameter.schedule
|
||||
concurrencyPolicy: parameter.concurrencyPolicy
|
||||
suspend: parameter.suspend
|
||||
successfulJobsHistoryLimit: parameter.successfulJobsHistoryLimit
|
||||
failedJobsHistoryLimit: parameter.failedJobsHistoryLimit
|
||||
if parameter.startingDeadlineSeconds != _|_ {
|
||||
startingDeadlineSeconds: parameter.startingDeadlineSeconds
|
||||
}
|
||||
jobTemplate: {
|
||||
if parameter.labels != _|_ {
|
||||
metadata: labels: parameter.labels
|
||||
}
|
||||
if parameter.annotations != _|_ {
|
||||
metadata: annotations: parameter.annotations
|
||||
}
|
||||
spec: {
|
||||
parallelism: parameter.count
|
||||
completions: parameter.count
|
||||
if parameter.ttlSecondsAfterFinished != _|_ {
|
||||
ttlSecondsAfterFinished: parameter.ttlSecondsAfterFinished
|
||||
}
|
||||
if parameter.activeDeadlineSeconds != _|_ {
|
||||
activeDeadlineSeconds: parameter.activeDeadlineSeconds
|
||||
}
|
||||
backoffLimit: parameter.backoffLimit
|
||||
template: {
|
||||
if parameter.labels != _|_ {
|
||||
metadata: labels: parameter.labels
|
||||
}
|
||||
if parameter.annotations != _|_ {
|
||||
metadata: annotations: parameter.annotations
|
||||
}
|
||||
spec: {
|
||||
restartPolicy: parameter.restart
|
||||
containers: [{
|
||||
name: context.name
|
||||
image: parameter.image
|
||||
if parameter["imagePullPolicy"] != _|_ {
|
||||
imagePullPolicy: parameter.imagePullPolicy
|
||||
}
|
||||
if parameter["cmd"] != _|_ {
|
||||
command: parameter.cmd
|
||||
}
|
||||
if parameter["env"] != _|_ {
|
||||
env: parameter.env
|
||||
}
|
||||
if parameter["cpu"] != _|_ {
|
||||
resources: {
|
||||
limits: cpu: parameter.cpu
|
||||
requests: cpu: parameter.cpu
|
||||
}
|
||||
}
|
||||
if parameter["memory"] != _|_ {
|
||||
resources: {
|
||||
limits: memory: parameter.memory
|
||||
requests: memory: parameter.memory
|
||||
}
|
||||
}
|
||||
if parameter["volumes"] != _|_ {
|
||||
volumeMounts: [ for v in parameter.volumes {
|
||||
{
|
||||
mountPath: v.mountPath
|
||||
name: v.name
|
||||
}}]
|
||||
}
|
||||
}]
|
||||
if parameter["volumes"] != _|_ {
|
||||
volumes: [ for v in parameter.volumes {
|
||||
{
|
||||
name: v.name
|
||||
if v.type == "pvc" {
|
||||
persistentVolumeClaim: claimName: v.claimName
|
||||
}
|
||||
if v.type == "configMap" {
|
||||
configMap: {
|
||||
defaultMode: v.defaultMode
|
||||
name: v.cmName
|
||||
if v.items != _|_ {
|
||||
items: v.items
|
||||
}
|
||||
}
|
||||
}
|
||||
if v.type == "secret" {
|
||||
secret: {
|
||||
defaultMode: v.defaultMode
|
||||
secretName: v.secretName
|
||||
if v.items != _|_ {
|
||||
items: v.items
|
||||
}
|
||||
}
|
||||
}
|
||||
if v.type == "emptyDir" {
|
||||
emptyDir: medium: v.medium
|
||||
}
|
||||
}}]
|
||||
}
|
||||
if parameter["imagePullSecrets"] != _|_ {
|
||||
imagePullSecrets: [ for v in parameter.imagePullSecrets {
|
||||
name: v
|
||||
},
|
||||
]
|
||||
}
|
||||
if parameter.hostAliases != _|_ {
|
||||
hostAliases: [ for v in parameter.hostAliases {
|
||||
ip: v.ip
|
||||
hostnames: v.hostnames
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
parameter: {
|
||||
// +usage=Specify the labels in the workload
|
||||
labels?: [string]: string
|
||||
|
||||
// +usage=Specify the annotations in the workload
|
||||
annotations?: [string]: string
|
||||
|
||||
// +usage=Specify the schedule in Cron format, see https://en.wikipedia.org/wiki/Cron
|
||||
schedule: string
|
||||
|
||||
// +usage=Specify deadline in seconds for starting the job if it misses scheduled
|
||||
startingDeadlineSeconds?: int
|
||||
|
||||
// +usage=suspend subsequent executions
|
||||
suspend: *false | bool
|
||||
|
||||
// +usage=Specifies how to treat concurrent executions of a Job
|
||||
concurrencyPolicy: *"Allow" | "Allow" | "Forbid" | "Replace"
|
||||
|
||||
// +usage=The number of successful finished jobs to retain
|
||||
successfulJobsHistoryLimit: *3 | int
|
||||
|
||||
// +usage=The number of failed finished jobs to retain
|
||||
failedJobsHistoryLimit: *1 | int
|
||||
|
||||
// +usage=Specify number of tasks to run in parallel
|
||||
// +short=c
|
||||
count: *1 | int
|
||||
|
||||
// +usage=Which image would you like to use for your service
|
||||
// +short=i
|
||||
image: string
|
||||
|
||||
// +usage=Specify image pull policy for your service
|
||||
imagePullPolicy?: "Always" | "Never" | "IfNotPresent"
|
||||
|
||||
// +usage=Specify image pull secrets for your service
|
||||
imagePullSecrets?: [...string]
|
||||
|
||||
// +usage=Define the job restart policy, the value can only be Never or OnFailure. By default, it's Never.
|
||||
restart: *"Never" | string
|
||||
|
||||
// +usage=Commands to run in the container
|
||||
cmd?: [...string]
|
||||
|
||||
// +usage=Define arguments by using environment variables
|
||||
env?: [...{
|
||||
// +usage=Environment variable name
|
||||
name: string
|
||||
// +usage=The value of the environment variable
|
||||
value?: string
|
||||
// +usage=Specifies a source the value of this var should come from
|
||||
valueFrom?: {
|
||||
// +usage=Selects a key of a secret in the pod's namespace
|
||||
secretKeyRef: {
|
||||
// +usage=The name of the secret in the pod's namespace to select from
|
||||
name: string
|
||||
// +usage=The key of the secret to select from. Must be a valid secret key
|
||||
key: string
|
||||
}
|
||||
// +usage=Selects a key of a config map in the pod's namespace
|
||||
configMapKeyRef: {
|
||||
// +usage=The name of the config map in the pod's namespace to select from
|
||||
name: string
|
||||
// +usage=The key of the config map to select from. Must be a valid secret key
|
||||
key: string
|
||||
}
|
||||
}
|
||||
}]
|
||||
|
||||
// +usage=Number of CPU units for the service, like `0.5` (0.5 CPU core), `1` (1 CPU core)
|
||||
cpu?: string
|
||||
|
||||
// +usage=Specifies the attributes of the memory resource required for the container.
|
||||
memory?: string
|
||||
|
||||
// +usage=Declare volumes and volumeMounts
|
||||
volumes?: [...{
|
||||
name: string
|
||||
mountPath: string
|
||||
// +usage=Specify volume type, options: "pvc","configMap","secret","emptyDir"
|
||||
type: "pvc" | "configMap" | "secret" | "emptyDir"
|
||||
if type == "pvc" {
|
||||
claimName: string
|
||||
}
|
||||
if type == "configMap" {
|
||||
defaultMode: *420 | int
|
||||
cmName: string
|
||||
items?: [...{
|
||||
key: string
|
||||
path: string
|
||||
mode: *511 | int
|
||||
}]
|
||||
}
|
||||
if type == "secret" {
|
||||
defaultMode: *420 | int
|
||||
secretName: string
|
||||
items?: [...{
|
||||
key: string
|
||||
path: string
|
||||
mode: *511 | int
|
||||
}]
|
||||
}
|
||||
if type == "emptyDir" {
|
||||
medium: *"" | "Memory"
|
||||
}
|
||||
}]
|
||||
|
||||
// +usage=An optional list of hosts and IPs that will be injected into the pod's hosts file
|
||||
hostAliases?: [...{
|
||||
ip: string
|
||||
hostnames: [...string]
|
||||
}]
|
||||
|
||||
// +usage=Limits the lifetime of a Job that has finished
|
||||
ttlSecondsAfterFinished?: int
|
||||
|
||||
// +usage=The duration in seconds relative to the startTime that the job may be continuously active before the system tries to terminate it
|
||||
activeDeadlineSeconds?: int
|
||||
|
||||
// +usage=The number of retries before marking this job failed
|
||||
backoffLimit: *6 | int
|
||||
|
||||
// +usage=Instructions for assessing whether the container is alive.
|
||||
livenessProbe?: #HealthProbe
|
||||
|
||||
// +usage=Instructions for assessing whether the container is in a suitable state to serve traffic.
|
||||
readinessProbe?: #HealthProbe
|
||||
}
|
||||
#HealthProbe: {
|
||||
|
||||
// +usage=Instructions for assessing container health by executing a command. Either this attribute or the httpGet attribute or the tcpSocket attribute MUST be specified. This attribute is mutually exclusive with both the httpGet attribute and the tcpSocket attribute.
|
||||
exec?: {
|
||||
// +usage=A command to be executed inside the container to assess its health. Each space delimited token of the command is a separate array element. Commands exiting 0 are considered to be successful probes, whilst all other exit codes are considered failures.
|
||||
command: [...string]
|
||||
}
|
||||
|
||||
// +usage=Instructions for assessing container health by executing an HTTP GET request. Either this attribute or the exec attribute or the tcpSocket attribute MUST be specified. This attribute is mutually exclusive with both the exec attribute and the tcpSocket attribute.
|
||||
httpGet?: {
|
||||
// +usage=The endpoint, relative to the port, to which the HTTP GET request should be directed.
|
||||
path: string
|
||||
// +usage=The TCP socket within the container to which the HTTP GET request should be directed.
|
||||
port: int
|
||||
httpHeaders?: [...{
|
||||
name: string
|
||||
value: string
|
||||
}]
|
||||
}
|
||||
|
||||
// +usage=Instructions for assessing container health by probing a TCP socket. Either this attribute or the exec attribute or the httpGet attribute MUST be specified. This attribute is mutually exclusive with both the exec attribute and the httpGet attribute.
|
||||
tcpSocket?: {
|
||||
// +usage=The TCP socket within the container that should be probed to assess container health.
|
||||
port: int
|
||||
}
|
||||
|
||||
// +usage=Number of seconds after the container is started before the first probe is initiated.
|
||||
initialDelaySeconds: *0 | int
|
||||
|
||||
// +usage=How often, in seconds, to execute the probe.
|
||||
periodSeconds: *10 | int
|
||||
|
||||
// +usage=Number of seconds after which the probe times out.
|
||||
timeoutSeconds: *1 | int
|
||||
|
||||
// +usage=Minimum consecutive successes for the probe to be considered successful after having failed.
|
||||
successThreshold: *1 | int
|
||||
|
||||
// +usage=Number of consecutive failures required to determine the container is not alive (liveness probe) or not ready (readiness probe).
|
||||
failureThreshold: *3 | int
|
||||
}
|
||||
workload:
|
||||
definition:
|
||||
apiVersion: batch/v1beta1
|
||||
kind: CronJob
|
||||
type: cronjobs.batch
|
||||
|
||||
@@ -8,6 +8,8 @@ metadata:
|
||||
name: gateway
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- '*'
|
||||
podDisruptive: false
|
||||
schematic:
|
||||
cue:
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
# Code generated by KubeVela templates. DO NOT EDIT. Please edit the original cue file.
|
||||
# Definition source cue file: vela-templates/definitions/internal/generate-jdbc-connection.cue
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: WorkflowStepDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Generate a JDBC connection based on Component of alibaba-rds
|
||||
labels:
|
||||
custom.definition.oam.dev/ui-hidden: "true"
|
||||
name: generate-jdbc-connection
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
schematic:
|
||||
cue:
|
||||
template: |
|
||||
import (
|
||||
"vela/op"
|
||||
"encoding/base64"
|
||||
)
|
||||
|
||||
output: op.#Read & {
|
||||
value: {
|
||||
apiVersion: "v1"
|
||||
kind: "Secret"
|
||||
metadata: {
|
||||
name: parameter.name
|
||||
if parameter.namespace != _|_ {
|
||||
namespace: parameter.namespace
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dbHost: op.#ConvertString & {bt: base64.Decode(null, output.value.data["DB_HOST"])}
|
||||
dbPort: op.#ConvertString & {bt: base64.Decode(null, output.value.data["DB_PORT"])}
|
||||
dbName: op.#ConvertString & {bt: base64.Decode(null, output.value.data["DB_NAME"])}
|
||||
username: op.#ConvertString & {bt: base64.Decode(null, output.value.data["DB_USER"])}
|
||||
password: op.#ConvertString & {bt: base64.Decode(null, output.value.data["DB_PASSWORD"])}
|
||||
env: [
|
||||
{name: "url", value: "jdbc://" + dbHost.str + ":" + dbPort.str + "/" + dbName.str + "?characterEncoding=utf8&useSSL=false"},
|
||||
{name: "username", value: username.str},
|
||||
{name: "password", value: password.str},
|
||||
]
|
||||
parameter: {
|
||||
// +usage=Specify the name of the secret generated by database component
|
||||
name: string
|
||||
// +usage=Specify the namespace of the secret generated by database component
|
||||
namespace?: string
|
||||
}
|
||||
|
||||
@@ -16,17 +16,20 @@ spec:
|
||||
schematic:
|
||||
cue:
|
||||
template: |
|
||||
// +patchStrategy=jsonMergePatch
|
||||
patch: {
|
||||
metadata: labels: {
|
||||
for k, v in parameter {
|
||||
"\(k)": v
|
||||
}
|
||||
}
|
||||
spec: template: metadata: labels: {
|
||||
for k, v in parameter {
|
||||
"\(k)": v
|
||||
if context.output.spec != _|_ && context.output.spec.template != _|_ {
|
||||
spec: template: metadata: labels: {
|
||||
for k, v in parameter {
|
||||
"\(k)": v
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
parameter: [string]: string
|
||||
parameter: [string]: string | null
|
||||
|
||||
|
||||
@@ -291,8 +291,10 @@ spec:
|
||||
if parameter.email.from.password.value != _|_ {
|
||||
email1: op.#SendEmail & {
|
||||
from: {
|
||||
address: parameter.email.from.value
|
||||
alias: parameter.email.from.alias
|
||||
address: parameter.email.from.address
|
||||
if parameter.email.from.alias != _|_ {
|
||||
alias: parameter.email.from.alias
|
||||
}
|
||||
password: parameter.email.from.password.value
|
||||
host: parameter.email.from.host
|
||||
port: parameter.email.from.port
|
||||
@@ -318,8 +320,10 @@ spec:
|
||||
stringValue: op.#ConvertString & {bt: decoded}
|
||||
email2: op.#SendEmail & {
|
||||
from: {
|
||||
address: parameter.email.from.value
|
||||
alias: parameter.email.from.alias
|
||||
address: parameter.email.from.address
|
||||
if parameter.email.from.alias != _|_ {
|
||||
alias: parameter.email.from.alias
|
||||
}
|
||||
password: stringValue.str
|
||||
host: parameter.email.from.host
|
||||
port: parameter.email.from.port
|
||||
|
||||
@@ -29,6 +29,47 @@ spec:
|
||||
}
|
||||
}
|
||||
parameter: objects: [...#K8sObject]
|
||||
status:
|
||||
customStatus: |-
|
||||
if context.output.apiVersion == "apps/v1" && context.output.kind == "Deployment" {
|
||||
ready: {
|
||||
readyReplicas: *0 | int
|
||||
} & {
|
||||
if context.output.status.readyReplicas != _|_ {
|
||||
readyReplicas: context.output.status.readyReplicas
|
||||
}
|
||||
}
|
||||
message: "Ready:\(ready.readyReplicas)/\(context.output.spec.replicas)"
|
||||
}
|
||||
if context.output.apiVersion != "apps/v1" || context.output.kind != "Deployment" {
|
||||
message: ""
|
||||
}
|
||||
healthPolicy: |-
|
||||
if context.output.apiVersion == "apps/v1" && context.output.kind == "Deployment" {
|
||||
ready: {
|
||||
updatedReplicas: *0 | int
|
||||
readyReplicas: *0 | int
|
||||
replicas: *0 | int
|
||||
observedGeneration: *0 | int
|
||||
} & {
|
||||
if context.output.status.updatedReplicas != _|_ {
|
||||
updatedReplicas: context.output.status.updatedReplicas
|
||||
}
|
||||
if context.output.status.readyReplicas != _|_ {
|
||||
readyReplicas: context.output.status.readyReplicas
|
||||
}
|
||||
if context.output.status.replicas != _|_ {
|
||||
replicas: context.output.status.replicas
|
||||
}
|
||||
if context.output.status.observedGeneration != _|_ {
|
||||
observedGeneration: context.output.status.observedGeneration
|
||||
}
|
||||
}
|
||||
isHealth: (context.output.spec.replicas == ready.readyReplicas) && (context.output.spec.replicas == ready.updatedReplicas) && (context.output.spec.replicas == ready.replicas) && (ready.observedGeneration == context.output.metadata.generation || ready.observedGeneration > context.output.metadata.generation)
|
||||
}
|
||||
if context.output.apiVersion != "apps/v1" || context.output.kind != "Deployment" {
|
||||
isHealth: true
|
||||
}
|
||||
workload:
|
||||
type: autodetects.core.oam.dev
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ spec:
|
||||
},
|
||||
] | []
|
||||
configMapVolumesList: *[
|
||||
for v in parameter.configMap {
|
||||
for v in parameter.configMap if v.mountPath != _|_ {
|
||||
{
|
||||
name: "configmap-" + v.name
|
||||
configMap: {
|
||||
@@ -37,7 +37,7 @@ spec:
|
||||
},
|
||||
] | []
|
||||
secretVolumesList: *[
|
||||
for v in parameter.secret {
|
||||
for v in parameter.secret if v.mountPath != _|_ {
|
||||
{
|
||||
name: "secret-" + v.name
|
||||
secret: {
|
||||
@@ -69,7 +69,7 @@ spec:
|
||||
},
|
||||
] | []
|
||||
configMapVolumeMountsList: *[
|
||||
for v in parameter.configMap {
|
||||
for v in parameter.configMap if v.mountPath != _|_ {
|
||||
{
|
||||
name: "configmap-" + v.name
|
||||
mountPath: v.mountPath
|
||||
@@ -88,7 +88,7 @@ spec:
|
||||
},
|
||||
] | []
|
||||
secretVolumeMountsList: *[
|
||||
for v in parameter.secret {
|
||||
for v in parameter.secret if v.mountPath != _|_ {
|
||||
{
|
||||
name: "secret-" + v.name
|
||||
mountPath: v.mountPath
|
||||
@@ -126,14 +126,14 @@ spec:
|
||||
// +patchKey=name
|
||||
volumes: pvcVolumesList + configMapVolumesList + secretVolumesList + emptyDirVolumesList
|
||||
|
||||
containers: [...{
|
||||
containers: [{
|
||||
// +patchKey=name
|
||||
env: configMapEnvMountsList + secretEnvMountsList
|
||||
// +patchKey=name
|
||||
volumeDevices: volumeDevicesList
|
||||
// +patchKey=name
|
||||
volumeMounts: pvcVolumeMountsList + configMapVolumeMountsList + secretVolumeMountsList + emptyDirVolumeMountsList
|
||||
}]
|
||||
}, ...]
|
||||
|
||||
}
|
||||
outputs: {
|
||||
@@ -248,7 +248,7 @@ spec:
|
||||
envName: string
|
||||
configMapKey: string
|
||||
}
|
||||
mountPath: string
|
||||
mountPath?: string
|
||||
defaultMode: *420 | int
|
||||
readOnly: *false | bool
|
||||
data?: {...}
|
||||
@@ -267,7 +267,7 @@ spec:
|
||||
envName: string
|
||||
secretKey: string
|
||||
}
|
||||
mountPath: string
|
||||
mountPath?: string
|
||||
defaultMode: *420 | int
|
||||
readOnly: *false | bool
|
||||
stringData?: {...}
|
||||
|
||||
@@ -244,6 +244,30 @@ spec:
|
||||
// +usage=Number of consecutive failures required to determine the container is not alive (liveness probe) or not ready (readiness probe).
|
||||
failureThreshold: *3 | int
|
||||
}
|
||||
status:
|
||||
customStatus: |-
|
||||
status: {
|
||||
active: *0 | int
|
||||
failed: *0 | int
|
||||
succeeded: *0 | int
|
||||
} & {
|
||||
if context.output.status.active != _|_ {
|
||||
active: context.output.status.active
|
||||
}
|
||||
if context.output.status.failed != _|_ {
|
||||
failed: context.output.status.failed
|
||||
}
|
||||
if context.output.status.succeeded != _|_ {
|
||||
succeeded: context.output.status.succeeded
|
||||
}
|
||||
}
|
||||
message: "Active/Failed/Succeeded:\(status.active)/\(status.failed)/\(status.succeeded)"
|
||||
healthPolicy: |-
|
||||
succeeded: *0 | int
|
||||
if context.output.status.succeeded != _|_ {
|
||||
succeeded: context.output.status.succeeded
|
||||
}
|
||||
isHealth: succeeded == context.output.spec.parallelism
|
||||
workload:
|
||||
definition:
|
||||
apiVersion: batch/v1
|
||||
|
||||
@@ -453,6 +453,12 @@ spec:
|
||||
|
||||
// +usage=Instructions for assessing whether the container is in a suitable state to serve traffic.
|
||||
readinessProbe?: #HealthProbe
|
||||
|
||||
// +usage=Specify the hostAliases to add
|
||||
hostAliases: [...{
|
||||
ip: string
|
||||
hostnames: [...string]
|
||||
}]
|
||||
}
|
||||
#HealthProbe: {
|
||||
|
||||
@@ -494,61 +500,38 @@ spec:
|
||||
|
||||
// +usage=Number of consecutive failures required to determine the container is not alive (liveness probe) or not ready (readiness probe).
|
||||
failureThreshold: *3 | int
|
||||
|
||||
// +usage=Specify the hostAliases to add
|
||||
hostAliases: [...{
|
||||
ip: string
|
||||
hostnames: [...string]
|
||||
}]
|
||||
}
|
||||
status:
|
||||
customStatus: |-
|
||||
import "strconv"
|
||||
ready: {
|
||||
if context.output.status.readyReplicas == _|_ {
|
||||
readyReplicas: 0
|
||||
}
|
||||
|
||||
readyReplicas: *0 | int
|
||||
} & {
|
||||
if context.output.status.readyReplicas != _|_ {
|
||||
readyReplicas: context.output.status.readyReplicas
|
||||
}
|
||||
}
|
||||
|
||||
message: "Ready:" + strconv.FormatInt(ready.readyReplicas, 10) + "/" + strconv.FormatInt(context.output.spec.replicas, 10)
|
||||
message: "Ready:\(ready.readyReplicas)/\(context.output.spec.replicas)"
|
||||
healthPolicy: |-
|
||||
ready: {
|
||||
if context.output.status.updatedReplicas == _|_ {
|
||||
updatedReplicas : 0
|
||||
updatedReplicas: *0 | int
|
||||
readyReplicas: *0 | int
|
||||
replicas: *0 | int
|
||||
observedGeneration: *0 | int
|
||||
} & {
|
||||
if context.output.status.updatedReplicas != _|_ {
|
||||
updatedReplicas: context.output.status.updatedReplicas
|
||||
}
|
||||
|
||||
if context.output.status.updatedReplicas != _|_ {
|
||||
updatedReplicas : context.output.status.updatedReplicas
|
||||
}
|
||||
|
||||
if context.output.status.readyReplicas == _|_ {
|
||||
readyReplicas: 0
|
||||
}
|
||||
|
||||
if context.output.status.readyReplicas != _|_ {
|
||||
readyReplicas: context.output.status.readyReplicas
|
||||
}
|
||||
|
||||
if context.output.status.replicas == _|_ {
|
||||
replicas: 0
|
||||
}
|
||||
if context.output.status.replicas != _|_ {
|
||||
replicas: context.output.status.replicas
|
||||
}
|
||||
|
||||
if context.output.status.observedGeneration != _|_ {
|
||||
observedGeneration: context.output.status.observedGeneration
|
||||
}
|
||||
|
||||
if context.output.status.observedGeneration == _|_ {
|
||||
observedGeneration: 0
|
||||
}
|
||||
}
|
||||
isHealth: (context.output.spec.replicas == ready.readyReplicas) && (context.output.spec.replicas == ready.updatedReplicas) && (context.output.spec.replicas == ready.replicas) && (ready.observedGeneration == context.output.metadata.generation || ready.observedGeneration > context.output.metadata.generation)
|
||||
isHealth: (context.output.spec.replicas == ready.readyReplicas) && (context.output.spec.replicas == ready.updatedReplicas) && (context.output.spec.replicas == ready.replicas) && (ready.observedGeneration == context.output.metadata.generation || ready.observedGeneration > context.output.metadata.generation)
|
||||
workload:
|
||||
definition:
|
||||
apiVersion: apps/v1
|
||||
|
||||
@@ -396,52 +396,35 @@ spec:
|
||||
}
|
||||
status:
|
||||
customStatus: |-
|
||||
import "strconv"
|
||||
ready: {
|
||||
if context.output.status.readyReplicas == _|_ {
|
||||
readyReplicas: 0
|
||||
}
|
||||
|
||||
readyReplicas: *0 | int
|
||||
} & {
|
||||
if context.output.status.readyReplicas != _|_ {
|
||||
readyReplicas: context.output.status.readyReplicas
|
||||
}
|
||||
}
|
||||
|
||||
message: "Ready:" + strconv.FormatInt(ready.readyReplicas, 10) + "/" + strconv.FormatInt(context.output.spec.replicas, 10)
|
||||
message: "Ready:\(ready.readyReplicas)/\(context.output.spec.replicas)"
|
||||
healthPolicy: |-
|
||||
ready: {
|
||||
if context.output.status.updatedReplicas == _|_ {
|
||||
updatedReplicas : 0
|
||||
updatedReplicas: *0 | int
|
||||
readyReplicas: *0 | int
|
||||
replicas: *0 | int
|
||||
observedGeneration: *0 | int
|
||||
} & {
|
||||
if context.output.status.updatedReplicas != _|_ {
|
||||
updatedReplicas: context.output.status.updatedReplicas
|
||||
}
|
||||
|
||||
if context.output.status.updatedReplicas != _|_ {
|
||||
updatedReplicas : context.output.status.updatedReplicas
|
||||
}
|
||||
|
||||
if context.output.status.readyReplicas == _|_ {
|
||||
readyReplicas: 0
|
||||
}
|
||||
|
||||
if context.output.status.readyReplicas != _|_ {
|
||||
readyReplicas: context.output.status.readyReplicas
|
||||
}
|
||||
|
||||
if context.output.status.replicas == _|_ {
|
||||
replicas: 0
|
||||
}
|
||||
if context.output.status.replicas != _|_ {
|
||||
replicas: context.output.status.replicas
|
||||
}
|
||||
|
||||
if context.output.status.observedGeneration != _|_ {
|
||||
observedGeneration: context.output.status.observedGeneration
|
||||
}
|
||||
|
||||
if context.output.status.observedGeneration == _|_ {
|
||||
observedGeneration: 0
|
||||
}
|
||||
}
|
||||
isHealth: (context.output.spec.replicas == ready.readyReplicas) && (context.output.spec.replicas == ready.updatedReplicas) && (context.output.spec.replicas == ready.replicas) && (ready.observedGeneration == context.output.metadata.generation || ready.observedGeneration > context.output.metadata.generation)
|
||||
isHealth: (context.output.spec.replicas == ready.readyReplicas) && (context.output.spec.replicas == ready.updatedReplicas) && (context.output.spec.replicas == ready.replicas) && (ready.observedGeneration == context.output.metadata.generation || ready.observedGeneration > context.output.metadata.generation)
|
||||
workload:
|
||||
definition:
|
||||
apiVersion: apps/v1
|
||||
|
||||
44
charts/vela-core/templates/velaql/applied-resources.yaml
Normal file
44
charts/vela-core/templates/velaql/applied-resources.yaml
Normal file
@@ -0,0 +1,44 @@
|
||||
apiVersion: "v1"
|
||||
kind: "ConfigMap"
|
||||
metadata:
|
||||
name: "service-applied-resources-view"
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
data:
|
||||
template: |
|
||||
import (
|
||||
"vela/ql"
|
||||
)
|
||||
parameter: {
|
||||
appName: string
|
||||
appNs: string
|
||||
name?: string
|
||||
cluster?: string
|
||||
clusterNs?: string
|
||||
}
|
||||
response: ql.#ListAppliedResources & {
|
||||
app: {
|
||||
name: parameter.appName
|
||||
namespace: parameter.appNs
|
||||
filter: {
|
||||
if parameter.cluster != _|_ {
|
||||
cluster: parameter.cluster
|
||||
}
|
||||
if parameter.clusterNs != _|_ {
|
||||
clusterNamespace: parameter.clusterNs
|
||||
}
|
||||
if parameter.name != _|_ {
|
||||
components: [parameter.name]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if response.err == _|_ {
|
||||
status: {
|
||||
resources: response.list
|
||||
}
|
||||
}
|
||||
if response.err != _|_ {
|
||||
status: {
|
||||
error: response.err
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ data:
|
||||
parameter: {
|
||||
appName: string
|
||||
appNs: string
|
||||
name?: string
|
||||
cluster?: string
|
||||
clusterNs?: string
|
||||
}
|
||||
@@ -25,6 +26,9 @@ data:
|
||||
if parameter.clusterNs != _|_ {
|
||||
clusterNamespace: parameter.clusterNs
|
||||
}
|
||||
if parameter.name != _|_ {
|
||||
components: [parameter.name]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ multicluster:
|
||||
port: 9443
|
||||
image:
|
||||
repository: oamdev/cluster-gateway
|
||||
tag: v1.1.7
|
||||
tag: v1.3.2
|
||||
pullPolicy: IfNotPresent
|
||||
resources:
|
||||
limits:
|
||||
|
||||
@@ -105,7 +105,7 @@ helm install --create-namespace -n vela-system kubevela kubevela/vela-minimal --
|
||||
| `multicluster.clusterGateway.replicaCount` | ClusterGateway replica count | `1` |
|
||||
| `multicluster.clusterGateway.port` | ClusterGateway port | `9443` |
|
||||
| `multicluster.clusterGateway.image.repository` | ClusterGateway image repository | `oamdev/cluster-gateway` |
|
||||
| `multicluster.clusterGateway.image.tag` | ClusterGateway image tag | `v1.1.7` |
|
||||
| `multicluster.clusterGateway.image.tag` | ClusterGateway image tag | `v1.3.2` |
|
||||
| `multicluster.clusterGateway.image.pullPolicy` | ClusterGateway image pull policy | `IfNotPresent` |
|
||||
| `multicluster.clusterGateway.resources.limits.cpu` | ClusterGateway cpu limit | `100m` |
|
||||
| `multicluster.clusterGateway.resources.limits.memory` | ClusterGateway memory limit | `200Mi` |
|
||||
|
||||
@@ -2025,6 +2025,12 @@ spec:
|
||||
- jsonPath: .metadata.creationTimestamp
|
||||
name: AGE
|
||||
type: date
|
||||
- jsonPath: .metadata.annotations['app\.oam\.dev\/publishVersion']
|
||||
name: PUBLISH_VERSION
|
||||
type: string
|
||||
- jsonPath: .status.succeeded
|
||||
name: SUCCEEDED
|
||||
type: string
|
||||
name: v1beta1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
@@ -2747,13 +2753,6 @@ spec:
|
||||
type: object
|
||||
type: object
|
||||
type: object
|
||||
applicationConfiguration:
|
||||
description: ApplicationConfiguration records the rendered applicationConfiguration
|
||||
from Application, it will contains the whole K8s CR of trait and
|
||||
the reference component in it.
|
||||
type: object
|
||||
x-kubernetes-embedded-resource: true
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
componentDefinitions:
|
||||
additionalProperties:
|
||||
description: ComponentDefinition is the Schema for the componentdefinitions
|
||||
@@ -3087,20 +3086,51 @@ spec:
|
||||
description: ComponentDefinitions records the snapshot of the componentDefinitions
|
||||
related with the created/modified Application
|
||||
type: object
|
||||
components:
|
||||
description: Components records the rendered components from Application,
|
||||
it will contains the whole K8s CR of workload in it.
|
||||
items:
|
||||
description: RawComponent record raw component
|
||||
policies:
|
||||
additionalProperties:
|
||||
description: Policy is the Schema for the policy API
|
||||
properties:
|
||||
raw:
|
||||
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:
|
||||
properties:
|
||||
annotations:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
finalizers:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
labels:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
name:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
type: object
|
||||
properties:
|
||||
type: object
|
||||
x-kubernetes-embedded-resource: true
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
type:
|
||||
type: string
|
||||
required:
|
||||
- raw
|
||||
- type
|
||||
type: object
|
||||
type: array
|
||||
description: Policies records the external policies
|
||||
type: object
|
||||
policyDefinitions:
|
||||
additionalProperties:
|
||||
description: PolicyDefinition is the Schema for the policydefinitions
|
||||
@@ -3377,15 +3407,16 @@ spec:
|
||||
description: PolicyDefinitions records the snapshot of the PolicyDefinitions
|
||||
related with the created/modified Application
|
||||
type: object
|
||||
resourcesConfigMap:
|
||||
description: ResourcesConfigMap references the ConfigMap that's generated
|
||||
to contain all final rendered resources.
|
||||
properties:
|
||||
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
|
||||
type: object
|
||||
referredObjects:
|
||||
description: ReferredObjects records the referred objects used in
|
||||
the ref-object typed components
|
||||
items:
|
||||
description: ReferredObject the referred Kubernetes object
|
||||
type: object
|
||||
x-kubernetes-embedded-resource: true
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
type: array
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
scopeDefinitions:
|
||||
additionalProperties:
|
||||
description: A ScopeDefinition registers a kind of Kubernetes custom
|
||||
@@ -3819,6 +3850,89 @@ spec:
|
||||
description: TraitDefinitions records the snapshot of the traitDefinitions
|
||||
related with the created/modified Application
|
||||
type: object
|
||||
workflow:
|
||||
description: Workflow records the external workflow
|
||||
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:
|
||||
properties:
|
||||
annotations:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
finalizers:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
labels:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
name:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
type: object
|
||||
steps:
|
||||
items:
|
||||
description: WorkflowStep defines how to execute a workflow
|
||||
step.
|
||||
properties:
|
||||
dependsOn:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
inputs:
|
||||
description: StepInputs defines variable input of WorkflowStep
|
||||
items:
|
||||
properties:
|
||||
from:
|
||||
type: string
|
||||
parameterKey:
|
||||
type: string
|
||||
required:
|
||||
- from
|
||||
- parameterKey
|
||||
type: object
|
||||
type: array
|
||||
name:
|
||||
description: Name is the unique name of the workflow step.
|
||||
type: string
|
||||
outputs:
|
||||
description: StepOutputs defines output variable of WorkflowStep
|
||||
items:
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
valueFrom:
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
- valueFrom
|
||||
type: object
|
||||
type: array
|
||||
properties:
|
||||
type: object
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
type:
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
- type
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
workflowStepDefinitions:
|
||||
additionalProperties:
|
||||
description: WorkflowStepDefinition is the Schema for the workflowstepdefinitions
|
||||
@@ -4408,10 +4522,182 @@ spec:
|
||||
required:
|
||||
- application
|
||||
type: object
|
||||
status:
|
||||
description: ApplicationRevisionStatus is the status of ApplicationRevision
|
||||
properties:
|
||||
succeeded:
|
||||
description: Succeeded records if the workflow finished running with
|
||||
success
|
||||
type: boolean
|
||||
workflow:
|
||||
description: Workflow the running status of the workflow
|
||||
properties:
|
||||
appRevision:
|
||||
type: string
|
||||
contextBackend:
|
||||
description: 'ObjectReference contains enough information to let
|
||||
you inspect or modify the referred object. --- New uses of this
|
||||
type are discouraged because of difficulty describing its usage
|
||||
when embedded in APIs. 1. Ignored fields. It includes many
|
||||
fields which are not generally honored. For instance, ResourceVersion
|
||||
and FieldPath are both very rarely valid in actual usage. 2.
|
||||
Invalid usage help. It is impossible to add specific help for
|
||||
individual usage. In most embedded usages, there are particular restrictions
|
||||
like, "must refer only to types A and B" or "UID not honored"
|
||||
or "name must be restricted". Those cannot be well described
|
||||
when embedded. 3. Inconsistent validation. Because the usages
|
||||
are different, the validation rules are different by usage,
|
||||
which makes it hard for users to predict what will happen. 4.
|
||||
The fields are both imprecise and overly precise. Kind is not
|
||||
a precise mapping to a URL. This can produce ambiguity during
|
||||
interpretation and require a REST mapping. In most cases, the
|
||||
dependency is on the group,resource tuple and the version
|
||||
of the actual struct is irrelevant. 5. We cannot easily change
|
||||
it. Because this type is embedded in many locations, updates
|
||||
to this type will affect numerous schemas. Don''t make
|
||||
new APIs embed an underspecified API type they do not control.
|
||||
Instead of using this type, create a locally provided and used
|
||||
type that is well-focused on your reference. For example, ServiceReferences
|
||||
for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533
|
||||
.'
|
||||
properties:
|
||||
apiVersion:
|
||||
description: API version of the referent.
|
||||
type: string
|
||||
fieldPath:
|
||||
description: 'If referring to a piece of an object instead
|
||||
of an entire object, this string should contain a valid
|
||||
JSON/Go field access statement, such as desiredState.manifest.containers[2].
|
||||
For example, if the object reference is to a container within
|
||||
a pod, this would take on a value like: "spec.containers{name}"
|
||||
(where "name" refers to the name of the container that triggered
|
||||
the event) or if no container name is specified "spec.containers[2]"
|
||||
(container with index 2 in this pod). This syntax is chosen
|
||||
only to have some well-defined way of referencing a part
|
||||
of an object. TODO: this design is not final and this field
|
||||
is subject to change in the future.'
|
||||
type: string
|
||||
kind:
|
||||
description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
name:
|
||||
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
|
||||
type: string
|
||||
namespace:
|
||||
description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
|
||||
type: string
|
||||
resourceVersion:
|
||||
description: 'Specific resourceVersion to which this reference
|
||||
is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
|
||||
type: string
|
||||
uid:
|
||||
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
|
||||
type: string
|
||||
type: object
|
||||
finished:
|
||||
type: boolean
|
||||
message:
|
||||
type: string
|
||||
mode:
|
||||
description: WorkflowMode describes the mode of workflow
|
||||
type: string
|
||||
startTime:
|
||||
format: date-time
|
||||
type: string
|
||||
steps:
|
||||
items:
|
||||
description: WorkflowStepStatus record the status of a workflow
|
||||
step
|
||||
properties:
|
||||
firstExecuteTime:
|
||||
description: FirstExecuteTime is the first time this step
|
||||
execution.
|
||||
format: date-time
|
||||
type: string
|
||||
id:
|
||||
type: string
|
||||
lastExecuteTime:
|
||||
description: LastExecuteTime is the last time this step
|
||||
execution.
|
||||
format: date-time
|
||||
type: string
|
||||
message:
|
||||
description: A human readable message indicating details
|
||||
about why the workflowStep is in this state.
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
phase:
|
||||
description: WorkflowStepPhase describes the phase of a
|
||||
workflow step.
|
||||
type: string
|
||||
reason:
|
||||
description: A brief CamelCase message indicating details
|
||||
about why the workflowStep is in this state.
|
||||
type: string
|
||||
subSteps:
|
||||
description: SubStepsStatus record the status of workflow
|
||||
steps.
|
||||
properties:
|
||||
mode:
|
||||
description: WorkflowMode describes the mode of workflow
|
||||
type: string
|
||||
stepIndex:
|
||||
type: integer
|
||||
steps:
|
||||
items:
|
||||
description: WorkflowSubStepStatus record the status
|
||||
of a workflow step
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
message:
|
||||
description: A human readable message indicating
|
||||
details about why the workflowStep is in this
|
||||
state.
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
phase:
|
||||
description: WorkflowStepPhase describes the phase
|
||||
of a workflow step.
|
||||
type: string
|
||||
reason:
|
||||
description: A brief CamelCase message indicating
|
||||
details about why the workflowStep is in this
|
||||
state.
|
||||
type: string
|
||||
type:
|
||||
type: string
|
||||
required:
|
||||
- id
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
type:
|
||||
type: string
|
||||
required:
|
||||
- id
|
||||
type: object
|
||||
type: array
|
||||
suspend:
|
||||
type: boolean
|
||||
terminated:
|
||||
type: boolean
|
||||
required:
|
||||
- finished
|
||||
- mode
|
||||
- suspend
|
||||
- terminated
|
||||
type: object
|
||||
required:
|
||||
- succeeded
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
subresources: {}
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
|
||||
@@ -16,17 +16,20 @@ spec:
|
||||
schematic:
|
||||
cue:
|
||||
template: |
|
||||
// +patchStrategy=jsonMergePatch
|
||||
patch: {
|
||||
metadata: annotations: {
|
||||
for k, v in parameter {
|
||||
"\(k)": v
|
||||
}
|
||||
}
|
||||
spec: template: metadata: annotations: {
|
||||
for k, v in parameter {
|
||||
"\(k)": v
|
||||
if context.output.spec != _|_ && context.output.spec.template != _|_ {
|
||||
spec: template: metadata: annotations: {
|
||||
for k, v in parameter {
|
||||
"\(k)": v
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
parameter: [string]: string
|
||||
parameter: [string]: string | null
|
||||
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
# Code generated by KubeVela templates. DO NOT EDIT. Please edit the original cue file.
|
||||
# Definition source cue file: vela-templates/definitions/internal/config-image-registry.cue
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: ComponentDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
custom.definition.oam.dev/alias.config.oam.dev: Image Registry
|
||||
definition.oam.dev/description: Config information to authenticate image registry
|
||||
labels:
|
||||
custom.definition.oam.dev/catalog.config.oam.dev: velacore-config
|
||||
custom.definition.oam.dev/multi-cluster.config.oam.dev: "true"
|
||||
custom.definition.oam.dev/type.config.oam.dev: image-registry
|
||||
name: config-image-registry
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
schematic:
|
||||
cue:
|
||||
template: |
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
output: {
|
||||
apiVersion: "v1"
|
||||
kind: "Secret"
|
||||
metadata: {
|
||||
name: context.name
|
||||
namespace: context.namespace
|
||||
labels: {
|
||||
"config.oam.dev/catalog": "velacore-config"
|
||||
"config.oam.dev/type": "image-registry"
|
||||
"config.oam.dev/multi-cluster": "true"
|
||||
"config.oam.dev/identifier": parameter.registry
|
||||
"config.oam.dev/sub-type": "auth"
|
||||
}
|
||||
}
|
||||
type: "kubernetes.io/dockerconfigjson"
|
||||
stringData: {
|
||||
if parameter.auth != _|_ {
|
||||
".dockerconfigjson": json.Marshal({
|
||||
auths: "\(parameter.registry)": {
|
||||
username: parameter.auth.username
|
||||
password: parameter.auth.password
|
||||
if parameter.auth.email != _|_ {
|
||||
email: parameter.auth.email
|
||||
}
|
||||
auth: base64.Encode(null, (parameter.auth.username + ":" + parameter.auth.password))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
parameter: {
|
||||
// +usage=Image registry FQDN
|
||||
registry: string
|
||||
// +usage=Authenticate the image registry
|
||||
auth?: {
|
||||
// +usage=Private Image registry username
|
||||
username: string
|
||||
// +usage=Private Image registry password
|
||||
password: string
|
||||
// +usage=Private Image registry email
|
||||
email?: string
|
||||
}
|
||||
}
|
||||
workload:
|
||||
type: autodetects.core.oam.dev
|
||||
|
||||
308
charts/vela-minimal/templates/defwithtemplate/cron-task.yaml
Normal file
308
charts/vela-minimal/templates/defwithtemplate/cron-task.yaml
Normal file
@@ -0,0 +1,308 @@
|
||||
# Code generated by KubeVela templates. DO NOT EDIT. Please edit the original cue file.
|
||||
# Definition source cue file: vela-templates/definitions/internal/cron-task.cue
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: ComponentDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Describes cron jobs that run code or a script to completion.
|
||||
name: cron-task
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
schematic:
|
||||
cue:
|
||||
template: |
|
||||
output: {
|
||||
apiVersion: "batch/v1beta1"
|
||||
kind: "CronJob"
|
||||
spec: {
|
||||
schedule: parameter.schedule
|
||||
concurrencyPolicy: parameter.concurrencyPolicy
|
||||
suspend: parameter.suspend
|
||||
successfulJobsHistoryLimit: parameter.successfulJobsHistoryLimit
|
||||
failedJobsHistoryLimit: parameter.failedJobsHistoryLimit
|
||||
if parameter.startingDeadlineSeconds != _|_ {
|
||||
startingDeadlineSeconds: parameter.startingDeadlineSeconds
|
||||
}
|
||||
jobTemplate: {
|
||||
if parameter.labels != _|_ {
|
||||
metadata: labels: parameter.labels
|
||||
}
|
||||
if parameter.annotations != _|_ {
|
||||
metadata: annotations: parameter.annotations
|
||||
}
|
||||
spec: {
|
||||
parallelism: parameter.count
|
||||
completions: parameter.count
|
||||
if parameter.ttlSecondsAfterFinished != _|_ {
|
||||
ttlSecondsAfterFinished: parameter.ttlSecondsAfterFinished
|
||||
}
|
||||
if parameter.activeDeadlineSeconds != _|_ {
|
||||
activeDeadlineSeconds: parameter.activeDeadlineSeconds
|
||||
}
|
||||
backoffLimit: parameter.backoffLimit
|
||||
template: {
|
||||
if parameter.labels != _|_ {
|
||||
metadata: labels: parameter.labels
|
||||
}
|
||||
if parameter.annotations != _|_ {
|
||||
metadata: annotations: parameter.annotations
|
||||
}
|
||||
spec: {
|
||||
restartPolicy: parameter.restart
|
||||
containers: [{
|
||||
name: context.name
|
||||
image: parameter.image
|
||||
if parameter["imagePullPolicy"] != _|_ {
|
||||
imagePullPolicy: parameter.imagePullPolicy
|
||||
}
|
||||
if parameter["cmd"] != _|_ {
|
||||
command: parameter.cmd
|
||||
}
|
||||
if parameter["env"] != _|_ {
|
||||
env: parameter.env
|
||||
}
|
||||
if parameter["cpu"] != _|_ {
|
||||
resources: {
|
||||
limits: cpu: parameter.cpu
|
||||
requests: cpu: parameter.cpu
|
||||
}
|
||||
}
|
||||
if parameter["memory"] != _|_ {
|
||||
resources: {
|
||||
limits: memory: parameter.memory
|
||||
requests: memory: parameter.memory
|
||||
}
|
||||
}
|
||||
if parameter["volumes"] != _|_ {
|
||||
volumeMounts: [ for v in parameter.volumes {
|
||||
{
|
||||
mountPath: v.mountPath
|
||||
name: v.name
|
||||
}}]
|
||||
}
|
||||
}]
|
||||
if parameter["volumes"] != _|_ {
|
||||
volumes: [ for v in parameter.volumes {
|
||||
{
|
||||
name: v.name
|
||||
if v.type == "pvc" {
|
||||
persistentVolumeClaim: claimName: v.claimName
|
||||
}
|
||||
if v.type == "configMap" {
|
||||
configMap: {
|
||||
defaultMode: v.defaultMode
|
||||
name: v.cmName
|
||||
if v.items != _|_ {
|
||||
items: v.items
|
||||
}
|
||||
}
|
||||
}
|
||||
if v.type == "secret" {
|
||||
secret: {
|
||||
defaultMode: v.defaultMode
|
||||
secretName: v.secretName
|
||||
if v.items != _|_ {
|
||||
items: v.items
|
||||
}
|
||||
}
|
||||
}
|
||||
if v.type == "emptyDir" {
|
||||
emptyDir: medium: v.medium
|
||||
}
|
||||
}}]
|
||||
}
|
||||
if parameter["imagePullSecrets"] != _|_ {
|
||||
imagePullSecrets: [ for v in parameter.imagePullSecrets {
|
||||
name: v
|
||||
},
|
||||
]
|
||||
}
|
||||
if parameter.hostAliases != _|_ {
|
||||
hostAliases: [ for v in parameter.hostAliases {
|
||||
ip: v.ip
|
||||
hostnames: v.hostnames
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
parameter: {
|
||||
// +usage=Specify the labels in the workload
|
||||
labels?: [string]: string
|
||||
|
||||
// +usage=Specify the annotations in the workload
|
||||
annotations?: [string]: string
|
||||
|
||||
// +usage=Specify the schedule in Cron format, see https://en.wikipedia.org/wiki/Cron
|
||||
schedule: string
|
||||
|
||||
// +usage=Specify deadline in seconds for starting the job if it misses scheduled
|
||||
startingDeadlineSeconds?: int
|
||||
|
||||
// +usage=suspend subsequent executions
|
||||
suspend: *false | bool
|
||||
|
||||
// +usage=Specifies how to treat concurrent executions of a Job
|
||||
concurrencyPolicy: *"Allow" | "Allow" | "Forbid" | "Replace"
|
||||
|
||||
// +usage=The number of successful finished jobs to retain
|
||||
successfulJobsHistoryLimit: *3 | int
|
||||
|
||||
// +usage=The number of failed finished jobs to retain
|
||||
failedJobsHistoryLimit: *1 | int
|
||||
|
||||
// +usage=Specify number of tasks to run in parallel
|
||||
// +short=c
|
||||
count: *1 | int
|
||||
|
||||
// +usage=Which image would you like to use for your service
|
||||
// +short=i
|
||||
image: string
|
||||
|
||||
// +usage=Specify image pull policy for your service
|
||||
imagePullPolicy?: "Always" | "Never" | "IfNotPresent"
|
||||
|
||||
// +usage=Specify image pull secrets for your service
|
||||
imagePullSecrets?: [...string]
|
||||
|
||||
// +usage=Define the job restart policy, the value can only be Never or OnFailure. By default, it's Never.
|
||||
restart: *"Never" | string
|
||||
|
||||
// +usage=Commands to run in the container
|
||||
cmd?: [...string]
|
||||
|
||||
// +usage=Define arguments by using environment variables
|
||||
env?: [...{
|
||||
// +usage=Environment variable name
|
||||
name: string
|
||||
// +usage=The value of the environment variable
|
||||
value?: string
|
||||
// +usage=Specifies a source the value of this var should come from
|
||||
valueFrom?: {
|
||||
// +usage=Selects a key of a secret in the pod's namespace
|
||||
secretKeyRef: {
|
||||
// +usage=The name of the secret in the pod's namespace to select from
|
||||
name: string
|
||||
// +usage=The key of the secret to select from. Must be a valid secret key
|
||||
key: string
|
||||
}
|
||||
// +usage=Selects a key of a config map in the pod's namespace
|
||||
configMapKeyRef: {
|
||||
// +usage=The name of the config map in the pod's namespace to select from
|
||||
name: string
|
||||
// +usage=The key of the config map to select from. Must be a valid secret key
|
||||
key: string
|
||||
}
|
||||
}
|
||||
}]
|
||||
|
||||
// +usage=Number of CPU units for the service, like `0.5` (0.5 CPU core), `1` (1 CPU core)
|
||||
cpu?: string
|
||||
|
||||
// +usage=Specifies the attributes of the memory resource required for the container.
|
||||
memory?: string
|
||||
|
||||
// +usage=Declare volumes and volumeMounts
|
||||
volumes?: [...{
|
||||
name: string
|
||||
mountPath: string
|
||||
// +usage=Specify volume type, options: "pvc","configMap","secret","emptyDir"
|
||||
type: "pvc" | "configMap" | "secret" | "emptyDir"
|
||||
if type == "pvc" {
|
||||
claimName: string
|
||||
}
|
||||
if type == "configMap" {
|
||||
defaultMode: *420 | int
|
||||
cmName: string
|
||||
items?: [...{
|
||||
key: string
|
||||
path: string
|
||||
mode: *511 | int
|
||||
}]
|
||||
}
|
||||
if type == "secret" {
|
||||
defaultMode: *420 | int
|
||||
secretName: string
|
||||
items?: [...{
|
||||
key: string
|
||||
path: string
|
||||
mode: *511 | int
|
||||
}]
|
||||
}
|
||||
if type == "emptyDir" {
|
||||
medium: *"" | "Memory"
|
||||
}
|
||||
}]
|
||||
|
||||
// +usage=An optional list of hosts and IPs that will be injected into the pod's hosts file
|
||||
hostAliases?: [...{
|
||||
ip: string
|
||||
hostnames: [...string]
|
||||
}]
|
||||
|
||||
// +usage=Limits the lifetime of a Job that has finished
|
||||
ttlSecondsAfterFinished?: int
|
||||
|
||||
// +usage=The duration in seconds relative to the startTime that the job may be continuously active before the system tries to terminate it
|
||||
activeDeadlineSeconds?: int
|
||||
|
||||
// +usage=The number of retries before marking this job failed
|
||||
backoffLimit: *6 | int
|
||||
|
||||
// +usage=Instructions for assessing whether the container is alive.
|
||||
livenessProbe?: #HealthProbe
|
||||
|
||||
// +usage=Instructions for assessing whether the container is in a suitable state to serve traffic.
|
||||
readinessProbe?: #HealthProbe
|
||||
}
|
||||
#HealthProbe: {
|
||||
|
||||
// +usage=Instructions for assessing container health by executing a command. Either this attribute or the httpGet attribute or the tcpSocket attribute MUST be specified. This attribute is mutually exclusive with both the httpGet attribute and the tcpSocket attribute.
|
||||
exec?: {
|
||||
// +usage=A command to be executed inside the container to assess its health. Each space delimited token of the command is a separate array element. Commands exiting 0 are considered to be successful probes, whilst all other exit codes are considered failures.
|
||||
command: [...string]
|
||||
}
|
||||
|
||||
// +usage=Instructions for assessing container health by executing an HTTP GET request. Either this attribute or the exec attribute or the tcpSocket attribute MUST be specified. This attribute is mutually exclusive with both the exec attribute and the tcpSocket attribute.
|
||||
httpGet?: {
|
||||
// +usage=The endpoint, relative to the port, to which the HTTP GET request should be directed.
|
||||
path: string
|
||||
// +usage=The TCP socket within the container to which the HTTP GET request should be directed.
|
||||
port: int
|
||||
httpHeaders?: [...{
|
||||
name: string
|
||||
value: string
|
||||
}]
|
||||
}
|
||||
|
||||
// +usage=Instructions for assessing container health by probing a TCP socket. Either this attribute or the exec attribute or the httpGet attribute MUST be specified. This attribute is mutually exclusive with both the exec attribute and the httpGet attribute.
|
||||
tcpSocket?: {
|
||||
// +usage=The TCP socket within the container that should be probed to assess container health.
|
||||
port: int
|
||||
}
|
||||
|
||||
// +usage=Number of seconds after the container is started before the first probe is initiated.
|
||||
initialDelaySeconds: *0 | int
|
||||
|
||||
// +usage=How often, in seconds, to execute the probe.
|
||||
periodSeconds: *10 | int
|
||||
|
||||
// +usage=Number of seconds after which the probe times out.
|
||||
timeoutSeconds: *1 | int
|
||||
|
||||
// +usage=Minimum consecutive successes for the probe to be considered successful after having failed.
|
||||
successThreshold: *1 | int
|
||||
|
||||
// +usage=Number of consecutive failures required to determine the container is not alive (liveness probe) or not ready (readiness probe).
|
||||
failureThreshold: *3 | int
|
||||
}
|
||||
workload:
|
||||
definition:
|
||||
apiVersion: batch/v1beta1
|
||||
kind: CronJob
|
||||
type: cronjobs.batch
|
||||
|
||||
@@ -8,6 +8,8 @@ metadata:
|
||||
name: gateway
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- '*'
|
||||
podDisruptive: false
|
||||
schematic:
|
||||
cue:
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
# Code generated by KubeVela templates. DO NOT EDIT. Please edit the original cue file.
|
||||
# Definition source cue file: vela-templates/definitions/internal/generate-jdbc-connection.cue
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: WorkflowStepDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Generate a JDBC connection based on Component of alibaba-rds
|
||||
labels:
|
||||
custom.definition.oam.dev/ui-hidden: "true"
|
||||
name: generate-jdbc-connection
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
schematic:
|
||||
cue:
|
||||
template: |
|
||||
import (
|
||||
"vela/op"
|
||||
"encoding/base64"
|
||||
)
|
||||
|
||||
output: op.#Read & {
|
||||
value: {
|
||||
apiVersion: "v1"
|
||||
kind: "Secret"
|
||||
metadata: {
|
||||
name: parameter.name
|
||||
if parameter.namespace != _|_ {
|
||||
namespace: parameter.namespace
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dbHost: op.#ConvertString & {bt: base64.Decode(null, output.value.data["DB_HOST"])}
|
||||
dbPort: op.#ConvertString & {bt: base64.Decode(null, output.value.data["DB_PORT"])}
|
||||
dbName: op.#ConvertString & {bt: base64.Decode(null, output.value.data["DB_NAME"])}
|
||||
username: op.#ConvertString & {bt: base64.Decode(null, output.value.data["DB_USER"])}
|
||||
password: op.#ConvertString & {bt: base64.Decode(null, output.value.data["DB_PASSWORD"])}
|
||||
env: [
|
||||
{name: "url", value: "jdbc://" + dbHost.str + ":" + dbPort.str + "/" + dbName.str + "?characterEncoding=utf8&useSSL=false"},
|
||||
{name: "username", value: username.str},
|
||||
{name: "password", value: password.str},
|
||||
]
|
||||
parameter: {
|
||||
// +usage=Specify the name of the secret generated by database component
|
||||
name: string
|
||||
// +usage=Specify the namespace of the secret generated by database component
|
||||
namespace?: string
|
||||
}
|
||||
|
||||
@@ -16,17 +16,20 @@ spec:
|
||||
schematic:
|
||||
cue:
|
||||
template: |
|
||||
// +patchStrategy=jsonMergePatch
|
||||
patch: {
|
||||
metadata: labels: {
|
||||
for k, v in parameter {
|
||||
"\(k)": v
|
||||
}
|
||||
}
|
||||
spec: template: metadata: labels: {
|
||||
for k, v in parameter {
|
||||
"\(k)": v
|
||||
if context.output.spec != _|_ && context.output.spec.template != _|_ {
|
||||
spec: template: metadata: labels: {
|
||||
for k, v in parameter {
|
||||
"\(k)": v
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
parameter: [string]: string
|
||||
parameter: [string]: string | null
|
||||
|
||||
|
||||
@@ -291,8 +291,10 @@ spec:
|
||||
if parameter.email.from.password.value != _|_ {
|
||||
email1: op.#SendEmail & {
|
||||
from: {
|
||||
address: parameter.email.from.value
|
||||
alias: parameter.email.from.alias
|
||||
address: parameter.email.from.address
|
||||
if parameter.email.from.alias != _|_ {
|
||||
alias: parameter.email.from.alias
|
||||
}
|
||||
password: parameter.email.from.password.value
|
||||
host: parameter.email.from.host
|
||||
port: parameter.email.from.port
|
||||
@@ -318,8 +320,10 @@ spec:
|
||||
stringValue: op.#ConvertString & {bt: decoded}
|
||||
email2: op.#SendEmail & {
|
||||
from: {
|
||||
address: parameter.email.from.value
|
||||
alias: parameter.email.from.alias
|
||||
address: parameter.email.from.address
|
||||
if parameter.email.from.alias != _|_ {
|
||||
alias: parameter.email.from.alias
|
||||
}
|
||||
password: stringValue.str
|
||||
host: parameter.email.from.host
|
||||
port: parameter.email.from.port
|
||||
|
||||
@@ -29,6 +29,47 @@ spec:
|
||||
}
|
||||
}
|
||||
parameter: objects: [...#K8sObject]
|
||||
status:
|
||||
customStatus: |-
|
||||
if context.output.apiVersion == "apps/v1" && context.output.kind == "Deployment" {
|
||||
ready: {
|
||||
readyReplicas: *0 | int
|
||||
} & {
|
||||
if context.output.status.readyReplicas != _|_ {
|
||||
readyReplicas: context.output.status.readyReplicas
|
||||
}
|
||||
}
|
||||
message: "Ready:\(ready.readyReplicas)/\(context.output.spec.replicas)"
|
||||
}
|
||||
if context.output.apiVersion != "apps/v1" || context.output.kind != "Deployment" {
|
||||
message: ""
|
||||
}
|
||||
healthPolicy: |-
|
||||
if context.output.apiVersion == "apps/v1" && context.output.kind == "Deployment" {
|
||||
ready: {
|
||||
updatedReplicas: *0 | int
|
||||
readyReplicas: *0 | int
|
||||
replicas: *0 | int
|
||||
observedGeneration: *0 | int
|
||||
} & {
|
||||
if context.output.status.updatedReplicas != _|_ {
|
||||
updatedReplicas: context.output.status.updatedReplicas
|
||||
}
|
||||
if context.output.status.readyReplicas != _|_ {
|
||||
readyReplicas: context.output.status.readyReplicas
|
||||
}
|
||||
if context.output.status.replicas != _|_ {
|
||||
replicas: context.output.status.replicas
|
||||
}
|
||||
if context.output.status.observedGeneration != _|_ {
|
||||
observedGeneration: context.output.status.observedGeneration
|
||||
}
|
||||
}
|
||||
isHealth: (context.output.spec.replicas == ready.readyReplicas) && (context.output.spec.replicas == ready.updatedReplicas) && (context.output.spec.replicas == ready.replicas) && (ready.observedGeneration == context.output.metadata.generation || ready.observedGeneration > context.output.metadata.generation)
|
||||
}
|
||||
if context.output.apiVersion != "apps/v1" || context.output.kind != "Deployment" {
|
||||
isHealth: true
|
||||
}
|
||||
workload:
|
||||
type: autodetects.core.oam.dev
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ spec:
|
||||
},
|
||||
] | []
|
||||
configMapVolumesList: *[
|
||||
for v in parameter.configMap {
|
||||
for v in parameter.configMap if v.mountPath != _|_ {
|
||||
{
|
||||
name: "configmap-" + v.name
|
||||
configMap: {
|
||||
@@ -37,7 +37,7 @@ spec:
|
||||
},
|
||||
] | []
|
||||
secretVolumesList: *[
|
||||
for v in parameter.secret {
|
||||
for v in parameter.secret if v.mountPath != _|_ {
|
||||
{
|
||||
name: "secret-" + v.name
|
||||
secret: {
|
||||
@@ -69,7 +69,7 @@ spec:
|
||||
},
|
||||
] | []
|
||||
configMapVolumeMountsList: *[
|
||||
for v in parameter.configMap {
|
||||
for v in parameter.configMap if v.mountPath != _|_ {
|
||||
{
|
||||
name: "configmap-" + v.name
|
||||
mountPath: v.mountPath
|
||||
@@ -88,7 +88,7 @@ spec:
|
||||
},
|
||||
] | []
|
||||
secretVolumeMountsList: *[
|
||||
for v in parameter.secret {
|
||||
for v in parameter.secret if v.mountPath != _|_ {
|
||||
{
|
||||
name: "secret-" + v.name
|
||||
mountPath: v.mountPath
|
||||
@@ -126,14 +126,14 @@ spec:
|
||||
// +patchKey=name
|
||||
volumes: pvcVolumesList + configMapVolumesList + secretVolumesList + emptyDirVolumesList
|
||||
|
||||
containers: [...{
|
||||
containers: [{
|
||||
// +patchKey=name
|
||||
env: configMapEnvMountsList + secretEnvMountsList
|
||||
// +patchKey=name
|
||||
volumeDevices: volumeDevicesList
|
||||
// +patchKey=name
|
||||
volumeMounts: pvcVolumeMountsList + configMapVolumeMountsList + secretVolumeMountsList + emptyDirVolumeMountsList
|
||||
}]
|
||||
}, ...]
|
||||
|
||||
}
|
||||
outputs: {
|
||||
@@ -248,7 +248,7 @@ spec:
|
||||
envName: string
|
||||
configMapKey: string
|
||||
}
|
||||
mountPath: string
|
||||
mountPath?: string
|
||||
defaultMode: *420 | int
|
||||
readOnly: *false | bool
|
||||
data?: {...}
|
||||
@@ -267,7 +267,7 @@ spec:
|
||||
envName: string
|
||||
secretKey: string
|
||||
}
|
||||
mountPath: string
|
||||
mountPath?: string
|
||||
defaultMode: *420 | int
|
||||
readOnly: *false | bool
|
||||
stringData?: {...}
|
||||
|
||||
@@ -244,6 +244,30 @@ spec:
|
||||
// +usage=Number of consecutive failures required to determine the container is not alive (liveness probe) or not ready (readiness probe).
|
||||
failureThreshold: *3 | int
|
||||
}
|
||||
status:
|
||||
customStatus: |-
|
||||
status: {
|
||||
active: *0 | int
|
||||
failed: *0 | int
|
||||
succeeded: *0 | int
|
||||
} & {
|
||||
if context.output.status.active != _|_ {
|
||||
active: context.output.status.active
|
||||
}
|
||||
if context.output.status.failed != _|_ {
|
||||
failed: context.output.status.failed
|
||||
}
|
||||
if context.output.status.succeeded != _|_ {
|
||||
succeeded: context.output.status.succeeded
|
||||
}
|
||||
}
|
||||
message: "Active/Failed/Succeeded:\(status.active)/\(status.failed)/\(status.succeeded)"
|
||||
healthPolicy: |-
|
||||
succeeded: *0 | int
|
||||
if context.output.status.succeeded != _|_ {
|
||||
succeeded: context.output.status.succeeded
|
||||
}
|
||||
isHealth: succeeded == context.output.spec.parallelism
|
||||
workload:
|
||||
definition:
|
||||
apiVersion: batch/v1
|
||||
|
||||
@@ -453,6 +453,12 @@ spec:
|
||||
|
||||
// +usage=Instructions for assessing whether the container is in a suitable state to serve traffic.
|
||||
readinessProbe?: #HealthProbe
|
||||
|
||||
// +usage=Specify the hostAliases to add
|
||||
hostAliases: [...{
|
||||
ip: string
|
||||
hostnames: [...string]
|
||||
}]
|
||||
}
|
||||
#HealthProbe: {
|
||||
|
||||
@@ -494,61 +500,38 @@ spec:
|
||||
|
||||
// +usage=Number of consecutive failures required to determine the container is not alive (liveness probe) or not ready (readiness probe).
|
||||
failureThreshold: *3 | int
|
||||
|
||||
// +usage=Specify the hostAliases to add
|
||||
hostAliases: [...{
|
||||
ip: string
|
||||
hostnames: [...string]
|
||||
}]
|
||||
}
|
||||
status:
|
||||
customStatus: |-
|
||||
import "strconv"
|
||||
ready: {
|
||||
if context.output.status.readyReplicas == _|_ {
|
||||
readyReplicas: 0
|
||||
}
|
||||
|
||||
readyReplicas: *0 | int
|
||||
} & {
|
||||
if context.output.status.readyReplicas != _|_ {
|
||||
readyReplicas: context.output.status.readyReplicas
|
||||
}
|
||||
}
|
||||
|
||||
message: "Ready:" + strconv.FormatInt(ready.readyReplicas, 10) + "/" + strconv.FormatInt(context.output.spec.replicas, 10)
|
||||
message: "Ready:\(ready.readyReplicas)/\(context.output.spec.replicas)"
|
||||
healthPolicy: |-
|
||||
ready: {
|
||||
if context.output.status.updatedReplicas == _|_ {
|
||||
updatedReplicas : 0
|
||||
updatedReplicas: *0 | int
|
||||
readyReplicas: *0 | int
|
||||
replicas: *0 | int
|
||||
observedGeneration: *0 | int
|
||||
} & {
|
||||
if context.output.status.updatedReplicas != _|_ {
|
||||
updatedReplicas: context.output.status.updatedReplicas
|
||||
}
|
||||
|
||||
if context.output.status.updatedReplicas != _|_ {
|
||||
updatedReplicas : context.output.status.updatedReplicas
|
||||
}
|
||||
|
||||
if context.output.status.readyReplicas == _|_ {
|
||||
readyReplicas: 0
|
||||
}
|
||||
|
||||
if context.output.status.readyReplicas != _|_ {
|
||||
readyReplicas: context.output.status.readyReplicas
|
||||
}
|
||||
|
||||
if context.output.status.replicas == _|_ {
|
||||
replicas: 0
|
||||
}
|
||||
if context.output.status.replicas != _|_ {
|
||||
replicas: context.output.status.replicas
|
||||
}
|
||||
|
||||
if context.output.status.observedGeneration != _|_ {
|
||||
observedGeneration: context.output.status.observedGeneration
|
||||
}
|
||||
|
||||
if context.output.status.observedGeneration == _|_ {
|
||||
observedGeneration: 0
|
||||
}
|
||||
}
|
||||
isHealth: (context.output.spec.replicas == ready.readyReplicas) && (context.output.spec.replicas == ready.updatedReplicas) && (context.output.spec.replicas == ready.replicas) && (ready.observedGeneration == context.output.metadata.generation || ready.observedGeneration > context.output.metadata.generation)
|
||||
isHealth: (context.output.spec.replicas == ready.readyReplicas) && (context.output.spec.replicas == ready.updatedReplicas) && (context.output.spec.replicas == ready.replicas) && (ready.observedGeneration == context.output.metadata.generation || ready.observedGeneration > context.output.metadata.generation)
|
||||
workload:
|
||||
definition:
|
||||
apiVersion: apps/v1
|
||||
|
||||
@@ -396,52 +396,35 @@ spec:
|
||||
}
|
||||
status:
|
||||
customStatus: |-
|
||||
import "strconv"
|
||||
ready: {
|
||||
if context.output.status.readyReplicas == _|_ {
|
||||
readyReplicas: 0
|
||||
}
|
||||
|
||||
readyReplicas: *0 | int
|
||||
} & {
|
||||
if context.output.status.readyReplicas != _|_ {
|
||||
readyReplicas: context.output.status.readyReplicas
|
||||
}
|
||||
}
|
||||
|
||||
message: "Ready:" + strconv.FormatInt(ready.readyReplicas, 10) + "/" + strconv.FormatInt(context.output.spec.replicas, 10)
|
||||
message: "Ready:\(ready.readyReplicas)/\(context.output.spec.replicas)"
|
||||
healthPolicy: |-
|
||||
ready: {
|
||||
if context.output.status.updatedReplicas == _|_ {
|
||||
updatedReplicas : 0
|
||||
updatedReplicas: *0 | int
|
||||
readyReplicas: *0 | int
|
||||
replicas: *0 | int
|
||||
observedGeneration: *0 | int
|
||||
} & {
|
||||
if context.output.status.updatedReplicas != _|_ {
|
||||
updatedReplicas: context.output.status.updatedReplicas
|
||||
}
|
||||
|
||||
if context.output.status.updatedReplicas != _|_ {
|
||||
updatedReplicas : context.output.status.updatedReplicas
|
||||
}
|
||||
|
||||
if context.output.status.readyReplicas == _|_ {
|
||||
readyReplicas: 0
|
||||
}
|
||||
|
||||
if context.output.status.readyReplicas != _|_ {
|
||||
readyReplicas: context.output.status.readyReplicas
|
||||
}
|
||||
|
||||
if context.output.status.replicas == _|_ {
|
||||
replicas: 0
|
||||
}
|
||||
if context.output.status.replicas != _|_ {
|
||||
replicas: context.output.status.replicas
|
||||
}
|
||||
|
||||
if context.output.status.observedGeneration != _|_ {
|
||||
observedGeneration: context.output.status.observedGeneration
|
||||
}
|
||||
|
||||
if context.output.status.observedGeneration == _|_ {
|
||||
observedGeneration: 0
|
||||
}
|
||||
}
|
||||
isHealth: (context.output.spec.replicas == ready.readyReplicas) && (context.output.spec.replicas == ready.updatedReplicas) && (context.output.spec.replicas == ready.replicas) && (ready.observedGeneration == context.output.metadata.generation || ready.observedGeneration > context.output.metadata.generation)
|
||||
isHealth: (context.output.spec.replicas == ready.readyReplicas) && (context.output.spec.replicas == ready.updatedReplicas) && (context.output.spec.replicas == ready.replicas) && (ready.observedGeneration == context.output.metadata.generation || ready.observedGeneration > context.output.metadata.generation)
|
||||
workload:
|
||||
definition:
|
||||
apiVersion: apps/v1
|
||||
|
||||
@@ -107,7 +107,7 @@ multicluster:
|
||||
port: 9443
|
||||
image:
|
||||
repository: oamdev/cluster-gateway
|
||||
tag: v1.1.7
|
||||
tag: v1.3.2
|
||||
pullPolicy: IfNotPresent
|
||||
resources:
|
||||
limits:
|
||||
|
||||
@@ -120,5 +120,5 @@ func (s *Server) buildSwagger() (*spec.Swagger, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create apiserver failed : %w ", err)
|
||||
}
|
||||
return restfulspec.BuildSwagger(server.RegisterServices()), nil
|
||||
return restfulspec.BuildSwagger(server.RegisterServices(context.Background(), false)), nil
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
@@ -30,11 +29,14 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
flag "github.com/spf13/pflag"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/klog/v2"
|
||||
"k8s.io/klog/v2/klogr"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/healthz"
|
||||
|
||||
"github.com/oam-dev/kubevela/pkg/auth"
|
||||
ctrlClient "github.com/oam-dev/kubevela/pkg/client"
|
||||
standardcontroller "github.com/oam-dev/kubevela/pkg/controller"
|
||||
commonconfig "github.com/oam-dev/kubevela/pkg/controller/common"
|
||||
@@ -42,6 +44,7 @@ import (
|
||||
oamv1alpha2 "github.com/oam-dev/kubevela/pkg/controller/core.oam.dev/v1alpha2"
|
||||
"github.com/oam-dev/kubevela/pkg/controller/utils"
|
||||
"github.com/oam-dev/kubevela/pkg/cue/packages"
|
||||
_ "github.com/oam-dev/kubevela/pkg/features"
|
||||
_ "github.com/oam-dev/kubevela/pkg/monitor/metrics"
|
||||
"github.com/oam-dev/kubevela/pkg/multicluster"
|
||||
"github.com/oam-dev/kubevela/pkg/oam"
|
||||
@@ -86,6 +89,8 @@ func main() {
|
||||
var renewDeadline time.Duration
|
||||
var retryPeriod time.Duration
|
||||
var enableClusterGateway bool
|
||||
var enableClusterMetrics bool
|
||||
var clusterMetricsInterval time.Duration
|
||||
|
||||
flag.BoolVar(&useWebhook, "use-webhook", false, "Enable Admission Webhook")
|
||||
flag.StringVar(&certDir, "webhook-cert-dir", "/k8s-webhook-server/serving-certs", "Admission webhook cert/key dir.")
|
||||
@@ -133,6 +138,8 @@ func main() {
|
||||
flag.DurationVar(&retryPeriod, "leader-election-retry-period", 2*time.Second,
|
||||
"The duration the LeaderElector clients should wait between tries of actions")
|
||||
flag.BoolVar(&enableClusterGateway, "enable-cluster-gateway", false, "Enable cluster-gateway to use multicluster, disabled by default.")
|
||||
flag.BoolVar(&enableClusterMetrics, "enable-cluster-metrics", false, "Enable cluster-metrics-management to collect metrics from clusters with cluster-gateway, disabled by default. When this param is enabled, enable-cluster-gateway should be enabled")
|
||||
flag.DurationVar(&clusterMetricsInterval, "cluster-metrics-interval", 15*time.Second, "The interval that ClusterMetricsMgr will collect metrics from clusters, default value is 15 seconds.")
|
||||
flag.BoolVar(&controllerArgs.EnableCompatibility, "enable-asi-compatibility", false, "enable compatibility for asi")
|
||||
flag.BoolVar(&controllerArgs.IgnoreAppWithoutControllerRequirement, "ignore-app-without-controller-version", false, "If true, application controller will not process the app without 'app.oam.dev/controller-version-require' annotation")
|
||||
standardcontroller.AddOptimizeFlags()
|
||||
@@ -141,6 +148,7 @@ func main() {
|
||||
flag.IntVar(&workflow.MaxWorkflowWaitBackoffTime, "max-workflow-wait-backoff-time", 60, "Set the max workflow wait backoff time, default is 60")
|
||||
flag.IntVar(&workflow.MaxWorkflowFailedBackoffTime, "max-workflow-failed-backoff-time", 300, "Set the max workflow wait backoff time, default is 300")
|
||||
flag.IntVar(&custom.MaxWorkflowStepErrorRetryTimes, "max-workflow-step-error-retry-times", 10, "Set the max workflow step error retry times, default is 10")
|
||||
utilfeature.DefaultMutableFeatureGate.AddFlag(flag.CommandLine)
|
||||
|
||||
flag.Parse()
|
||||
// setup logging
|
||||
@@ -197,13 +205,23 @@ func main() {
|
||||
restConfig.UserAgent = kubevelaName + "/" + version.GitRevision
|
||||
restConfig.QPS = float32(qps)
|
||||
restConfig.Burst = burst
|
||||
restConfig.Wrap(auth.NewImpersonatingRoundTripper)
|
||||
|
||||
// wrapper the round tripper by multi cluster rewriter
|
||||
if enableClusterGateway {
|
||||
if _, err := multicluster.Initialize(restConfig, true); err != nil {
|
||||
client, err := multicluster.Initialize(restConfig, true)
|
||||
if err != nil {
|
||||
klog.ErrorS(err, "failed to enable multi-cluster capability")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if enableClusterMetrics {
|
||||
_, err := multicluster.NewClusterMetricsMgr(context.Background(), client, clusterMetricsInterval)
|
||||
if err != nil {
|
||||
klog.ErrorS(err, "failed to enable multi-cluster-metrics capability")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
ctrl.SetLogger(klogr.New())
|
||||
|
||||
|
||||
@@ -6,3 +6,6 @@ coverage:
|
||||
patch:
|
||||
default:
|
||||
target: 70%
|
||||
ignore:
|
||||
- "**/zz_generated.deepcopy.go"
|
||||
- "references/"
|
||||
|
||||
@@ -6,3 +6,4 @@ This directory contains guides for contributors to the KubeVela project.
|
||||
* [Developer guide](./developer-guide.md)
|
||||
* [Triage issues](./triage-issues.md)
|
||||
* [Code conventions](./coding-conventions.md)
|
||||
* [Develop Code Flow](./develop-code-flow.pdf)
|
||||
|
||||
BIN
contribute/develop-code-flow.pdf
Normal file
BIN
contribute/develop-code-flow.pdf
Normal file
Binary file not shown.
@@ -5,7 +5,7 @@ This guide helps you get started developing KubeVela.
|
||||
## Prerequisites
|
||||
|
||||
1. Golang version 1.17+
|
||||
2. Kubernetes version v1.18+ with `~/.kube/config` configured.
|
||||
2. Kubernetes version v1.20+ with `~/.kube/config` configured.
|
||||
3. ginkgo 1.14.0+ (just for [E2E test](./developer-guide.md#e2e-test))
|
||||
4. golangci-lint 1.38.0+, it will install automatically if you run `make`, you can [install it manually](https://golangci-lint.run/usage/install/#local-installation) if the installation is too slow.
|
||||
5. kubebuilder v3.1.0+ and you need to manually install the dependency tools for unit test.
|
||||
@@ -177,7 +177,7 @@ To execute the e2e test of the API module, the mongodb service needs to exist lo
|
||||
# save your config
|
||||
mv ~/.kube/config ~/.kube/config.save
|
||||
|
||||
kind create cluster --image kindest/node:v1.18.15@sha256:5c1b980c4d0e0e8e7eb9f36f7df525d079a96169c8a8f20d8bd108c0d0889cc4 --name worker
|
||||
kind create cluster --image kindest/node:v1.20.7@sha256:688fba5ce6b825be62a7c7fe1415b35da2bdfbb5a69227c499ea4cc0008661ca --name worker
|
||||
kind get kubeconfig --name worker --internal > /tmp/worker.kubeconfig
|
||||
kind get kubeconfig --name worker > /tmp/worker.client.kubeconfig
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -95,7 +95,32 @@ spec:
|
||||
properties:
|
||||
rules:
|
||||
- selector:
|
||||
componentTypes:
|
||||
- webservice
|
||||
strategy: never
|
||||
componentTypes:
|
||||
- webservice
|
||||
strategy: never
|
||||
```
|
||||
|
||||
A more straightforward way is to specify `compNames` to match specified components.
|
||||
```yaml
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: create-ns-app
|
||||
spec:
|
||||
components:
|
||||
- name: example-addon-namespace
|
||||
type: k8s-objects
|
||||
properties:
|
||||
objects:
|
||||
- apiVersion: v1
|
||||
kind: Namespace
|
||||
policies:
|
||||
- name: garbage-collect
|
||||
type: garbage-collect
|
||||
properties:
|
||||
rules:
|
||||
- selector:
|
||||
componentNames:
|
||||
- example-addon-namespace
|
||||
strategy: never
|
||||
```
|
||||
|
||||
BIN
docs/examples/application/application-revision-arch.jpg
Normal file
BIN
docs/examples/application/application-revision-arch.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 249 KiB |
139
docs/examples/application/versioning.md
Normal file
139
docs/examples/application/versioning.md
Normal file
@@ -0,0 +1,139 @@
|
||||
# Managing KubeVela Application Versions
|
||||
|
||||

|
||||
|
||||
In KubeVela, ApplicationRevision keeps the snapshot of application and all its runtime dependencies such as ComponentRevision, external Policy or referred objects.
|
||||
This revision can be used review the application changes and rollback to past configurations.
|
||||
|
||||
In KubeVela v1.3, for application which uses the `PublishVersion` feature, we support viewing the history revisions, checking the differences across revisions, and rolling back to the latest succeeded revision.
|
||||
|
||||
For application with the `app.oam.dev/publishVersion` annotation, the workflow runs are strictly controlled.
|
||||
The annotation, which is noted as *publishVersion* in the following paragraphs, is used to identify a static version of the application and its dependencies.
|
||||
|
||||
When the annotation is updated to a new value, the application will generate a new revision no matter if the application spec or the dependencies are changed.
|
||||
It will then trigger a fresh new run of workflow after terminating the previous run.
|
||||
|
||||
During the running of workflow, all related data are retrieved from the ApplicationRevision, which means the changes to the application spec or the dependencies will not take effects until a newer `publishVerison` is annotated.
|
||||
|
||||
Fo example, let's start with an application with has referred objects, external workflow and policies.
|
||||
|
||||
```yaml
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: nginx-publish-version
|
||||
namespace: examples
|
||||
annotations:
|
||||
app.oam.dev/publishVersion: alpha1
|
||||
spec:
|
||||
components:
|
||||
- name: nginx-publish-version
|
||||
type: ref-objects
|
||||
properties:
|
||||
objects:
|
||||
- resource: deployment
|
||||
workflow:
|
||||
ref: make-release-in-hangzhou
|
||||
---
|
||||
apiVersion: core.oam.dev/v1alpha1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: topology-hangzhou-clusters
|
||||
namespace: examples
|
||||
type: topology
|
||||
properties:
|
||||
clusterLabelSelector:
|
||||
region: hangzhou
|
||||
---
|
||||
apiVersion: core.oam.dev/v1alpha1
|
||||
kind: Workflow
|
||||
metadata:
|
||||
name: make-release-in-hangzhou
|
||||
namespace: examples
|
||||
steps:
|
||||
- name: deploy-hangzhou
|
||||
type: deploy
|
||||
properties:
|
||||
policies: ["topology-hangzhou-clusters"]
|
||||
```
|
||||
|
||||
This application should be successful after a while.
|
||||
Now if we edit the referred deployment and set its image to an invalid value, such as `nginx:1.200`.
|
||||
The application will not re-run the workflow to make this change take effect automatically.
|
||||
But since the dependencies of this application changes, it means the next workflow run will update the deployment image.
|
||||
|
||||
Now let's run `vela live-diff nginx-publish-version -n examples` to check this diff
|
||||
```bash
|
||||
$ vela live-diff nginx-publish-version -n examples
|
||||
* Application (nginx-publish-version) has no change
|
||||
* External Policy (topology-hangzhou-clusters) has no change
|
||||
* External Workflow (make-release-in-hangzhou) has no change
|
||||
* Referred Object (apps/v1 Deployment examples/nginx-publish-version) has been modified(*)
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
annotations:
|
||||
- deployment.kubernetes.io/revision: "1"
|
||||
+ deployment.kubernetes.io/revision: "2"
|
||||
labels:
|
||||
app: nginx-publish-version
|
||||
name: nginx-publish-version
|
||||
namespace: examples
|
||||
spec:
|
||||
progressDeadlineSeconds: 600
|
||||
replicas: 1
|
||||
revisionHistoryLimit: 10
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nginx-publish-version
|
||||
strategy:
|
||||
rollingUpdate:
|
||||
maxSurge: 25%
|
||||
maxUnavailable: 25%
|
||||
type: RollingUpdate
|
||||
template:
|
||||
metadata:
|
||||
creationTimestamp: null
|
||||
labels:
|
||||
app: nginx-publish-version
|
||||
spec:
|
||||
containers:
|
||||
- - image: nginx
|
||||
+ - image: nginx:1.200
|
||||
imagePullPolicy: Always
|
||||
name: nginx
|
||||
resources: {}
|
||||
terminationMessagePath: /dev/termination-log
|
||||
terminationMessagePolicy: File
|
||||
dnsPolicy: ClusterFirst
|
||||
restartPolicy: Always
|
||||
schedulerName: default-scheduler
|
||||
securityContext: {}
|
||||
terminationGracePeriodSeconds: 30
|
||||
```
|
||||
|
||||
We can see all the changes of the application spec and the dependencies.
|
||||
Now let's make this change take effects.
|
||||
Update the `publishVersion` annotation in the application to `alpha2` to trigger the re-run of workflow.
|
||||
We will find the application stuck at `runningWorkflow` as the deployment cannot finish the update progress due to the invalid image.
|
||||
|
||||
Now we can run `vela revision list nginx-publish-version -n examples` to list all the available revisions.
|
||||
```bash
|
||||
$ vela revision list nginx-publish-version -n examples
|
||||
NAME PUBLISH_VERSION SUCCEEDED HASH BEGIN_TIME STATUS SIZE
|
||||
nginx-publish-version-v1 alpha1 true d428eff1f0a7918 2022-03-28 20:54:25 Succeeded 8.1 KiB
|
||||
nginx-publish-version-v2 alpha2 false 4f04da8827d87922 2022-03-28 21:01:25 Executing 8.1 KiB
|
||||
```
|
||||
|
||||
Before rolling back, we need to suspend the workflow of the application first. Run `vela workflow suspend nginx-publish-version -n examples`.
|
||||
After the application workflow is suspended, run `vela workflow rollback nginx-publish-version -n examples`, the workflow will be rolled back and the application resources will restore to the succeeded state.
|
||||
```bash
|
||||
$ vela workflow suspend nginx-publish-version -n examples
|
||||
Successfully suspend workflow: nginx-publish-version
|
||||
$ vela workflow rollback nginx-publish-version -n examples
|
||||
Find succeeded application revision nginx-publish-version-v1 (PublishVersion: alpha1) to rollback.
|
||||
Application spec rollback successfully.
|
||||
Application status rollback successfully.
|
||||
Application rollback completed.
|
||||
Application outdated revision cleaned up.
|
||||
```
|
||||
@@ -0,0 +1,21 @@
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: config-dex-connector-dev
|
||||
namespace: vela-system
|
||||
labels:
|
||||
"app.oam.dev/source-of-truth": "from-inner-system"
|
||||
"config.oam.dev/catalog": "velacore-config"
|
||||
"config.oam.dev/type": "config-dex-connector"
|
||||
"config.oam.dev/sub-type": "github"
|
||||
project: abc
|
||||
spec:
|
||||
components:
|
||||
- name: dev
|
||||
type: config-dex-connector
|
||||
properties:
|
||||
type: github
|
||||
github:
|
||||
clientID: "aa"
|
||||
clientSecret: "bb"
|
||||
redirectURI: "http://localhost:8080/callback"
|
||||
102
docs/examples/config/image-registry/README.md
Normal file
102
docs/examples/config/image-registry/README.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# How to store and use configurations
|
||||
|
||||
## General
|
||||
|
||||
- list all configuration types
|
||||
```shell
|
||||
$ vela components --label custom.definition.oam.dev/catalog.config.oam.dev=velacore-config
|
||||
NAME DEFINITION
|
||||
config-dex-connector autodetects.core.oam.dev
|
||||
config-helm-repository autodetects.core.oam.dev
|
||||
config-image-registry autodetects.core.oam.dev
|
||||
terraform-azure autodetects.core.oam.dev
|
||||
terraform-baidu autodetects.core.oam.dev
|
||||
```
|
||||
|
||||
```json
|
||||
# Get http://127.0.0.1:8000/api/v1/configs
|
||||
|
||||
[
|
||||
{
|
||||
"definitions": [
|
||||
"config-dex-connector"
|
||||
],
|
||||
"name": "Dex Connectors",
|
||||
"type": "dex-connector"
|
||||
},
|
||||
{
|
||||
"definitions": [
|
||||
"config-helm-repository"
|
||||
],
|
||||
"name": "Helm Repository",
|
||||
"type": "helm-repository"
|
||||
},
|
||||
{
|
||||
"definitions": [
|
||||
"config-image-registry"
|
||||
],
|
||||
"name": "Image Registry",
|
||||
"type": "image-registry"
|
||||
},
|
||||
null,
|
||||
{
|
||||
"definitions": [
|
||||
"terraform-baidu"
|
||||
],
|
||||
"name": "Terraform Cloud Provider",
|
||||
"type": "terraform-provider"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
- list all configurations
|
||||
|
||||
```shell
|
||||
$ kubectl get secret -n vela-system -l=config.oam.dev/catalog=velacore-config
|
||||
NAME TYPE DATA AGE
|
||||
image-registry-dev kubernetes.io/dockerconfigjson 1 3h51m
|
||||
```
|
||||
|
||||
## Image registry
|
||||
|
||||
- Create a config for an image registry
|
||||
|
||||
```shell
|
||||
$ vela up -f app-config-image-registry-account-auth.yaml
|
||||
Applying an application in vela K8s object format...
|
||||
I0323 10:45:25.347102 85930 apply.go:107] "creating object" name="config-image-registry-account-auth-dev" resource="core.oam.dev/v1beta1, Kind=Application"
|
||||
✅ App has been deployed 🚀🚀🚀
|
||||
Port forward: vela port-forward config-image-registry-account-auth-dev
|
||||
SSH: vela exec config-image-registry-account-auth-dev
|
||||
Logging: vela logs config-image-registry-account-auth-dev
|
||||
App status: vela status config-image-registry-account-auth-dev
|
||||
Endpoint: vela status config-image-registry-account-auth-dev
|
||||
--endpoint%
|
||||
|
||||
|
||||
$ kubectl get secret -n vela-system -l=config.oam.dev/catalog=velacore-config
|
||||
NAME TYPE DATA AGE
|
||||
image-registry-dev kubernetes.io/dockerconfigjson 1 77s
|
||||
```
|
||||
|
||||
- Deliver the config secret to working cluster
|
||||
|
||||
```shell
|
||||
$ vela cluster list
|
||||
CLUSTER TYPE ENDPOINT ACCEPTED LABELS
|
||||
local Internal - true
|
||||
bj X509Certificate https://123.57.73.107:6443 true
|
||||
|
||||
$ vela up -f app-deliever-secret.yaml
|
||||
```
|
||||
|
||||
- Deploy an application who needs to pull images from the private image registry
|
||||
|
||||
```shell
|
||||
$ export KUBECONFIG=~/.kube/config-bj
|
||||
$ kubectl get secret -n vela-system -l=config.oam.dev/catalog=velacore-config
|
||||
NAME TYPE DATA AGE
|
||||
image-registry-dev kubernetes.io/dockerconfigjson 1 120s
|
||||
|
||||
$ vela up -f app-validate-imagePullSecret.yaml
|
||||
```
|
||||
@@ -0,0 +1,20 @@
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: image-dev
|
||||
namespace: vela-system
|
||||
labels:
|
||||
"app.oam.dev/source-of-truth": "from-inner-system"
|
||||
"config.oam.dev/catalog": "velacore-config"
|
||||
"config.oam.dev/type": "config-image-registry"
|
||||
project: abc
|
||||
spec:
|
||||
components:
|
||||
- name: image-dev
|
||||
type: config-image-registry
|
||||
properties:
|
||||
registry: "registry.cn-beijing.aliyuncs.com"
|
||||
auth:
|
||||
username: "xxx"
|
||||
password: "PfwrjwifjFaked"
|
||||
email: "a@gmail.com"
|
||||
22
docs/examples/config/image-registry/app-deliever-secret.yaml
Normal file
22
docs/examples/config/image-registry/app-deliever-secret.yaml
Normal file
@@ -0,0 +1,22 @@
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: config-project1
|
||||
namespace: vela-system
|
||||
labels:
|
||||
config.oam.dev/catalog: "velacore-config"
|
||||
config.oam.dev/type: "helm-repository"
|
||||
spec:
|
||||
components:
|
||||
- name: deliver-secret
|
||||
type: ref-objects
|
||||
properties:
|
||||
objects:
|
||||
- name: reg-demo
|
||||
resource: secret
|
||||
policies:
|
||||
- type: topology
|
||||
name: dev
|
||||
properties:
|
||||
clusters: ["bj"]
|
||||
namespace: default
|
||||
14
docs/examples/config/image-registry/app-sample.yaml
Normal file
14
docs/examples/config/image-registry/app-sample.yaml
Normal file
@@ -0,0 +1,14 @@
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: app-sample
|
||||
namespace: ns1
|
||||
spec:
|
||||
components:
|
||||
- name: sample
|
||||
type: webservice
|
||||
properties:
|
||||
image: registry.cn-beijing.aliyuncs.com/vela/nginx:latest
|
||||
imagePullPolicy: Always
|
||||
imagePullSecrets:
|
||||
- image-registry-dev
|
||||
@@ -0,0 +1,14 @@
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: app-validate-image-pull-secret
|
||||
namespace: vela-system
|
||||
spec:
|
||||
components:
|
||||
- name: validate
|
||||
type: webservice
|
||||
properties:
|
||||
image: registry.cn-beijing.aliyuncs.com/vela/nginx:latest
|
||||
imagePullPolicy: Always
|
||||
imagePullSecrets:
|
||||
- image-registry-dev
|
||||
103
docs/examples/custom-trait/README.md
Normal file
103
docs/examples/custom-trait/README.md
Normal file
@@ -0,0 +1,103 @@
|
||||
# How to use
|
||||
|
||||
1. define a stateful component with StatefulSet as output
|
||||
|
||||
```shell
|
||||
$ vela def apply stateful.cue
|
||||
ComponentDefinition test-stateful created in namespace vela-system.
|
||||
```
|
||||
|
||||
2. define a custom trait with patch volume
|
||||
|
||||
```shell
|
||||
$ vela def apply volume-trait.cue
|
||||
TraitDefinition storageclass created in namespace vela-system.
|
||||
```
|
||||
|
||||
3. You can validate it by:
|
||||
```
|
||||
$ vela def vet volume-trait.cue
|
||||
Validation succeed.
|
||||
```
|
||||
|
||||
|
||||
|
||||
4. try dry run your app:
|
||||
```
|
||||
vela dry-run -f app.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# Application(website) -- Component(custom-component)
|
||||
---
|
||||
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
annotations: {}
|
||||
labels:
|
||||
app.oam.dev/appRevision: ""
|
||||
app.oam.dev/component: custom-component
|
||||
app.oam.dev/name: website
|
||||
app.oam.dev/namespace: default
|
||||
app.oam.dev/resourceType: WORKLOAD
|
||||
workload.oam.dev/type: test-stateful
|
||||
name: custom-component
|
||||
namespace: default
|
||||
spec:
|
||||
minReadySeconds: 10
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: custom-component
|
||||
serviceName: custom-component
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: custom-component
|
||||
spec:
|
||||
containers:
|
||||
- image: nginx:latest
|
||||
name: nginx
|
||||
ports:
|
||||
- containerPort: 80
|
||||
name: web
|
||||
volumeMounts:
|
||||
- mountPath: /usr/share/nginx/html
|
||||
name: test
|
||||
terminationGracePeriodSeconds: 10
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: test
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 10Gi
|
||||
storageClassName: cbs
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
annotations: {}
|
||||
labels:
|
||||
app: custom-component
|
||||
app.oam.dev/appRevision: ""
|
||||
app.oam.dev/component: custom-component
|
||||
app.oam.dev/name: website
|
||||
app.oam.dev/namespace: default
|
||||
app.oam.dev/resourceType: TRAIT
|
||||
trait.oam.dev/resource: web
|
||||
trait.oam.dev/type: AuxiliaryWorkload
|
||||
name: custom-component
|
||||
namespace: default
|
||||
spec:
|
||||
clusterIP: None
|
||||
ports:
|
||||
- name: web
|
||||
port: 80
|
||||
selector:
|
||||
app: custom-component
|
||||
```
|
||||
20
docs/examples/custom-trait/app.yaml
Normal file
20
docs/examples/custom-trait/app.yaml
Normal file
@@ -0,0 +1,20 @@
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: website
|
||||
namespace: default
|
||||
spec:
|
||||
components:
|
||||
- name: custom-component
|
||||
type: test-stateful
|
||||
properties:
|
||||
image: nginx:latest
|
||||
replicas: 1
|
||||
traits:
|
||||
- type: storageclass
|
||||
properties:
|
||||
volumeClaimTemplates:
|
||||
- name: test
|
||||
requests: 10Gi
|
||||
storageClassName: cbs
|
||||
mountPath: /usr/share/nginx/html
|
||||
58
docs/examples/custom-trait/stateful.cue
Normal file
58
docs/examples/custom-trait/stateful.cue
Normal file
@@ -0,0 +1,58 @@
|
||||
"test-stateful": {
|
||||
annotations: {}
|
||||
attributes: workload: definition: {
|
||||
apiVersion: "apps/v1"
|
||||
kind: "StatefulSet"
|
||||
}
|
||||
description: "StatefulSet component."
|
||||
labels: {}
|
||||
type: "component"
|
||||
}
|
||||
|
||||
template: {
|
||||
output: {
|
||||
apiVersion: "apps/v1"
|
||||
kind: "StatefulSet"
|
||||
metadata: name: context.name
|
||||
spec: {
|
||||
selector: matchLabels: app: context.name
|
||||
minReadySeconds: 10
|
||||
replicas: parameter.replicas
|
||||
serviceName: context.name
|
||||
template: {
|
||||
metadata: labels: app: context.name
|
||||
spec: {
|
||||
containers: [{
|
||||
name: "nginx"
|
||||
ports: [{
|
||||
name: "web"
|
||||
containerPort: 80
|
||||
}]
|
||||
image: parameter.image
|
||||
}]
|
||||
terminationGracePeriodSeconds: 10
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
outputs: web: {
|
||||
apiVersion: "v1"
|
||||
kind: "Service"
|
||||
metadata: {
|
||||
name: context.name
|
||||
labels: app: context.name
|
||||
}
|
||||
spec: {
|
||||
clusterIP: "None"
|
||||
ports: [{
|
||||
name: "web"
|
||||
port: 80
|
||||
}]
|
||||
selector: app: context.name
|
||||
}
|
||||
}
|
||||
parameter: {
|
||||
image: string
|
||||
replicas: int
|
||||
}
|
||||
}
|
||||
56
docs/examples/custom-trait/volume-trait.cue
Normal file
56
docs/examples/custom-trait/volume-trait.cue
Normal file
@@ -0,0 +1,56 @@
|
||||
storageclass: {
|
||||
type: "trait"
|
||||
annotations: {}
|
||||
labels: {}
|
||||
description: "Add storageclass on K8s pod for your workload which follows the pod spec in path 'spec.template'."
|
||||
attributes: {
|
||||
appliesToWorkloads: ["*"]
|
||||
}
|
||||
}
|
||||
template: {
|
||||
|
||||
volumeClaimTemplatesList: *[
|
||||
for v in parameter.volumeClaimTemplates {
|
||||
{
|
||||
metadata: name: v.name
|
||||
spec: {
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
resources: requests: storage: v.requests
|
||||
storageClassName: v.storageClassName
|
||||
}
|
||||
}
|
||||
},
|
||||
] | []
|
||||
|
||||
volumeClaimTemplateVolumeMountsList: *[
|
||||
for v in parameter.volumeClaimTemplates {
|
||||
{
|
||||
name: v.name
|
||||
mountPath: v.mountPath
|
||||
}
|
||||
},
|
||||
] | []
|
||||
|
||||
patch: {
|
||||
// +patchKey=name
|
||||
spec: {
|
||||
template: spec: {
|
||||
containers: [...{
|
||||
// +patchKey=name
|
||||
volumeMounts: volumeClaimTemplateVolumeMountsList
|
||||
}]
|
||||
}
|
||||
// +patchKey=name
|
||||
volumeClaimTemplates: volumeClaimTemplatesList
|
||||
}
|
||||
}
|
||||
|
||||
parameter: {
|
||||
volumeClaimTemplates?: [...{
|
||||
name: string
|
||||
requests: string
|
||||
storageClassName: string
|
||||
mountPath: string
|
||||
}]
|
||||
}
|
||||
}
|
||||
433
docs/examples/multicluster/deploy.md
Normal file
433
docs/examples/multicluster/deploy.md
Normal file
@@ -0,0 +1,433 @@
|
||||
# Advanced examples for multi-cluster deployment
|
||||
|
||||
The below features are introduced in KubeVela v1.3.
|
||||
|
||||

|
||||
|
||||
## Topology Policy
|
||||
|
||||
Topology policy is a policy used to describe the location where application component should be deployed and managed.
|
||||
|
||||
The most straight forward way is directly specifying the names of clusters to be deployed.
|
||||
In the following example, the nginx webservice will be deployed to the `examples` namespace in both `hangzhou-1` and `hangzhou-2` clusters concurrently.
|
||||
After nginx in both clusters are ready, the application will finish running workflow and becomes healthy.
|
||||
|
||||
```yaml
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: basic-topology
|
||||
namespace: examples
|
||||
spec:
|
||||
components:
|
||||
- name: nginx-basic
|
||||
type: webservice
|
||||
properties:
|
||||
image: nginx
|
||||
policies:
|
||||
- name: topology-hangzhou-clusters
|
||||
type: topology
|
||||
properties:
|
||||
clusters: ["hangzhou-1", "hangzhou-2"]
|
||||
```
|
||||
|
||||
The clusters in the topology can also be selected by labels instead of names.
|
||||
|
||||
```yaml
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: label-selector-topology
|
||||
namespace: examples
|
||||
spec:
|
||||
components:
|
||||
- name: nginx-label-selector
|
||||
type: webservice
|
||||
properties:
|
||||
image: nginx
|
||||
policies:
|
||||
- name: topology-hangzhou-clusters
|
||||
type: topology
|
||||
properties:
|
||||
clusterLabelSelector:
|
||||
region: hangzhou
|
||||
```
|
||||
|
||||
If you want to deploy application components into the control plane cluster, you can use the `local` cluster.
|
||||
Besides, you can also deploy your application components in another namespace other than the application's namespace.
|
||||
|
||||
```yaml
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: local-ns-topology
|
||||
namespace: examples
|
||||
spec:
|
||||
components:
|
||||
- name: nginx-local-ns
|
||||
type: webservice
|
||||
properties:
|
||||
image: nginx
|
||||
policies:
|
||||
- name: topology-local
|
||||
type: topology
|
||||
properties:
|
||||
clusters: ["local"]
|
||||
namespace: examples-alternative
|
||||
```
|
||||
|
||||
## Deploy WorkflowStep
|
||||
|
||||
By default, if you declare multiple topology policies in the application, the application components will be deployed in all destinations following the order of the policies.
|
||||
|
||||
If you want to manipulate the process of deploying them, for example, changing the order or adding manual-approval, you can use the `deploy` workflow step explicitly in the workflow to achieve that.
|
||||
|
||||
```yaml
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: deploy-workflowstep
|
||||
namespace: examples
|
||||
spec:
|
||||
components:
|
||||
- name: nginx-deploy-workflowstep
|
||||
type: webservice
|
||||
properties:
|
||||
image: nginx
|
||||
policies:
|
||||
- name: topology-hangzhou-clusters
|
||||
type: topology
|
||||
properties:
|
||||
clusterLabelSelector:
|
||||
region: hangzhou
|
||||
- name: topology-local
|
||||
type: topology
|
||||
properties:
|
||||
clusters: ["local"]
|
||||
namespace: examples-alternative
|
||||
workflow:
|
||||
steps:
|
||||
- type: deploy
|
||||
name: deploy-local
|
||||
properties:
|
||||
policies: ["topology-local"]
|
||||
- type: deploy
|
||||
name: deploy-hangzhou
|
||||
properties:
|
||||
# require manual approval before running this step
|
||||
auto: false
|
||||
policies: ["topology-hangzhou-clusters"]
|
||||
```
|
||||
|
||||
You can also deploy application components with different topology policies concurrently, by filling these topology policies in on `deploy` step.
|
||||
|
||||
```yaml
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: deploy-concurrently
|
||||
namespace: examples
|
||||
spec:
|
||||
components:
|
||||
- name: nginx-deploy-concurrently
|
||||
type: webservice
|
||||
properties:
|
||||
image: nginx
|
||||
policies:
|
||||
- name: topology-hangzhou-clusters
|
||||
type: topology
|
||||
properties:
|
||||
clusterLabelSelector:
|
||||
region: hangzhou
|
||||
- name: topology-local
|
||||
type: topology
|
||||
properties:
|
||||
clusters: ["local"]
|
||||
namespace: examples-alternative
|
||||
workflow:
|
||||
steps:
|
||||
- type: deploy
|
||||
name: deploy-all
|
||||
properties:
|
||||
policies: ["topology-local", "topology-hangzhou-clusters"]
|
||||
```
|
||||
|
||||
## Override Policy
|
||||
|
||||
Override policy helps you to customize the application components in different clusters. For example, using a different container image or changing the default number of replicas. The override policy should be used together with the topology policy in the `deploy` workflow step.
|
||||
|
||||
```yaml
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: deploy-with-override
|
||||
namespace: examples
|
||||
spec:
|
||||
components:
|
||||
- name: nginx-with-override
|
||||
type: webservice
|
||||
properties:
|
||||
image: nginx
|
||||
policies:
|
||||
- name: topology-hangzhou-clusters
|
||||
type: topology
|
||||
properties:
|
||||
clusterLabelSelector:
|
||||
region: hangzhou
|
||||
- name: topology-local
|
||||
type: topology
|
||||
properties:
|
||||
clusters: ["local"]
|
||||
namespace: examples-alternative
|
||||
- name: override-nginx-legacy-image
|
||||
type: override
|
||||
properties:
|
||||
components:
|
||||
- name: nginx-with-override
|
||||
properties:
|
||||
image: nginx:1.20
|
||||
- name: override-high-availability
|
||||
type: override
|
||||
properties:
|
||||
components:
|
||||
- type: webservice
|
||||
traits:
|
||||
- type: scaler
|
||||
properties:
|
||||
replicas: 3
|
||||
workflow:
|
||||
steps:
|
||||
- type: deploy
|
||||
name: deploy-local
|
||||
properties:
|
||||
policies: ["topology-local"]
|
||||
- type: deploy
|
||||
name: deploy-hangzhou
|
||||
properties:
|
||||
policies: ["topology-hangzhou-clusters", "override-nginx-legacy-image", "override-high-availability"]
|
||||
```
|
||||
|
||||
The override policy has many advanced capabilities, such as adding new component or selecting components to use.
|
||||
The following example will deploy `nginx:1.20` to local cluster. `nginx` and `nginx:stable` will be deployed to hangzhou clusters.
|
||||
|
||||
```yaml
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: advance-override
|
||||
namespace: examples
|
||||
spec:
|
||||
components:
|
||||
- name: nginx-advance-override-legacy
|
||||
type: webservice
|
||||
properties:
|
||||
image: nginx:1.20
|
||||
- name: nginx-advance-override-latest
|
||||
type: webservice
|
||||
properties:
|
||||
image: nginx
|
||||
policies:
|
||||
- name: topology-hangzhou-clusters
|
||||
type: topology
|
||||
properties:
|
||||
clusterLabelSelector:
|
||||
region: hangzhou
|
||||
- name: topology-local
|
||||
type: topology
|
||||
properties:
|
||||
clusters: ["local"]
|
||||
namespace: examples-alternative
|
||||
- name: override-nginx-legacy
|
||||
type: override
|
||||
properties:
|
||||
selector: ["nginx-advance-override-legacy"]
|
||||
- name: override-nginx-latest
|
||||
type: override
|
||||
properties:
|
||||
selector: ["nginx-advance-override-latest", "nginx-advance-override-stable"]
|
||||
components:
|
||||
- name: nginx-advance-override-stable
|
||||
type: webservice
|
||||
properties:
|
||||
image: nginx:stable
|
||||
workflow:
|
||||
steps:
|
||||
- type: deploy
|
||||
name: deploy-local
|
||||
properties:
|
||||
policies: ["topology-local", "override-nginx-legacy"]
|
||||
- type: deploy
|
||||
name: deploy-hangzhou
|
||||
properties:
|
||||
policies: ["topology-hangzhou-clusters", "override-nginx-latest"]
|
||||
```
|
||||
|
||||
## Ref-object Component
|
||||
|
||||
Sometimes, you may want to copy resources from one place to other places, such as copying secrets from the control plane cluster into managed clusters.
|
||||
You can use the `ref-object` typed component to achieve that.
|
||||
|
||||
```yaml
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: ref-objects-example
|
||||
namespace: examples
|
||||
spec:
|
||||
components:
|
||||
- name: image-pull-secrets
|
||||
type: ref-objects
|
||||
properties:
|
||||
objects:
|
||||
- resource: secret
|
||||
name: image-credential-to-copy
|
||||
policies:
|
||||
- name: topology-hangzhou-clusters
|
||||
type: topology
|
||||
properties:
|
||||
clusterLabelSelector:
|
||||
region: hangzhou
|
||||
```
|
||||
|
||||
You can also select resources by labels and duplicate them from one cluster into another cluster.
|
||||
|
||||
```yaml
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: ref-objects-duplicate-deployments
|
||||
namespace: examples
|
||||
spec:
|
||||
components:
|
||||
- name: duplicate-deployment
|
||||
type: ref-objects
|
||||
properties:
|
||||
objects:
|
||||
- resource: deployment
|
||||
cluster: hangzhou-1
|
||||
# select all deployment in the `examples` namespace in cluster `hangzhou-1` that matches the labelSelector
|
||||
labelSelector:
|
||||
need-duplicate: "true"
|
||||
policies:
|
||||
- name: topology-hangzhou-2
|
||||
type: topology
|
||||
properties:
|
||||
clusters: ["hangzhou-2"]
|
||||
```
|
||||
|
||||
You can also form a component by multiple referenced resources and even attach traits to the main workload.
|
||||
|
||||
```yaml
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: ref-objects-multiple-resources
|
||||
namespace: examples
|
||||
spec:
|
||||
components:
|
||||
- name: nginx-ref-multiple-resources
|
||||
type: ref-objects
|
||||
properties:
|
||||
objects:
|
||||
- resource: deployment
|
||||
- resource: service
|
||||
traits:
|
||||
- type: scaler
|
||||
properties:
|
||||
replicas: 3
|
||||
policies:
|
||||
- name: topology-hangzhou-clusters
|
||||
type: topology
|
||||
properties:
|
||||
clusterLabelSelector:
|
||||
region: hangzhou
|
||||
```
|
||||
|
||||
## External Policies and Workflow
|
||||
|
||||
Sometimes, you may want to use the same policy across multiple applications or reuse previous workflow to deploy different resources.
|
||||
To reduce the repeated code, you can leverage the external policies and workflow and refer to them in your applications.
|
||||
|
||||
> NOTE: you can only refer to Policy and Workflow within your application's namespace.
|
||||
|
||||
```yaml
|
||||
apiVersion: core.oam.dev/v1alpha1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: topology-hangzhou-clusters
|
||||
namespace: examples
|
||||
type: topology
|
||||
properties:
|
||||
clusterLabelSelector:
|
||||
region: hangzhou
|
||||
---
|
||||
apiVersion: core.oam.dev/v1alpha1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: override-high-availability-webservice
|
||||
namespace: examples
|
||||
type: override
|
||||
properties:
|
||||
components:
|
||||
- type: webservice
|
||||
traits:
|
||||
- type: scaler
|
||||
properties:
|
||||
replicas: 3
|
||||
---
|
||||
apiVersion: core.oam.dev/v1alpha1
|
||||
kind: Workflow
|
||||
metadata:
|
||||
name: make-release-in-hangzhou
|
||||
namespace: examples
|
||||
steps:
|
||||
- type: deploy
|
||||
name: deploy-hangzhou
|
||||
properties:
|
||||
auto: false
|
||||
policies: ["override-high-availability-webservice", "topology-hangzhou-clusters"]
|
||||
```
|
||||
|
||||
```yaml
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: external-policies-and-workflow
|
||||
namespace: examples
|
||||
spec:
|
||||
components:
|
||||
- name: nginx-external-policies-and-workflow
|
||||
type: webservice
|
||||
properties:
|
||||
image: nginx
|
||||
workflow:
|
||||
ref: make-release-in-hangzhou
|
||||
```
|
||||
|
||||
> NOTE: The internal policies will be loaded first. External policies will only be used when there is no corresponding policy inside the application. In the following example, we can reuse `tology-hangzhou-clusters` policy and `make-release-in-hangzhou` workflow but modify the `override-high-availability-webservice` by injecting the same-named policy inside the new application.
|
||||
|
||||
```yaml
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: nginx-stable-ultra
|
||||
namespace: examples
|
||||
spec:
|
||||
components:
|
||||
- name: nginx-stable-ultra
|
||||
type: webservice
|
||||
properties:
|
||||
image: nginx:stable
|
||||
policies:
|
||||
- name: override-high-availability-webservice
|
||||
type: override
|
||||
properties:
|
||||
components:
|
||||
- type: webservice
|
||||
traits:
|
||||
- type: scaler
|
||||
properties:
|
||||
replicas: 5
|
||||
workflow:
|
||||
ref: make-release-in-hangzhou
|
||||
```
|
||||
BIN
docs/examples/multicluster/ref-arch.jpg
Normal file
BIN
docs/examples/multicluster/ref-arch.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 111 KiB |
107
docs/examples/rbac/rbac.md
Normal file
107
docs/examples/rbac/rbac.md
Normal file
@@ -0,0 +1,107 @@
|
||||
# RBAC
|
||||
|
||||
User:
|
||||
|
||||
```yaml
|
||||
name: user
|
||||
userRoles: ["app-developer"]
|
||||
...
|
||||
```
|
||||
|
||||
ProjectUser:
|
||||
|
||||
```yaml
|
||||
username: user
|
||||
project: demo
|
||||
userRoles: ["app-developer"]
|
||||
```
|
||||
|
||||
Role:
|
||||
|
||||
```yaml
|
||||
name: app-developer
|
||||
project: demo
|
||||
permissions: ["app-manage"]
|
||||
```
|
||||
|
||||
```yaml
|
||||
name: admin
|
||||
permissions: ["all"]
|
||||
```
|
||||
|
||||
Permission:
|
||||
|
||||
```yaml
|
||||
name: app-manage
|
||||
project: demo
|
||||
resource: ["project:demo/application:*"]
|
||||
actions: ["*"]
|
||||
effect: Allow
|
||||
principal: {}
|
||||
condition: {}
|
||||
```
|
||||
|
||||
```yaml
|
||||
name: app1-manage
|
||||
project: demo
|
||||
resource: ["project:demo/application:app1/*"]
|
||||
actions: ["*"]
|
||||
effect: Allow
|
||||
principal: {}
|
||||
condition: {}
|
||||
|
||||
name: app2-manage
|
||||
project: demo
|
||||
resource: ["project:demo/application:app2/*"]
|
||||
actions: ["*"]
|
||||
effect: Allow
|
||||
principal: {}
|
||||
condition: {}
|
||||
```
|
||||
|
||||
```yaml
|
||||
name: cluster-manage
|
||||
resource: ["cluster:*"]
|
||||
actions: ["*"]
|
||||
effect: Allow
|
||||
principal: {}
|
||||
condition: {}
|
||||
```
|
||||
|
||||
```yaml
|
||||
name: cluster-beijing-manage
|
||||
resource: ["cluster:beijing"]
|
||||
actions: ["*"]
|
||||
effect: Allow
|
||||
principal: {}
|
||||
condition: {}
|
||||
```
|
||||
|
||||
```yaml
|
||||
name: all
|
||||
resource: ["*"]
|
||||
actions: ["*"]
|
||||
effect: Allow
|
||||
principal: {}
|
||||
condition: {}
|
||||
```
|
||||
|
||||
PermissionTemplate:
|
||||
|
||||
```yaml
|
||||
name: app-manage
|
||||
resource: ["project:${projectName}/application:*"]
|
||||
actions: ["*"]
|
||||
level: project
|
||||
effect: Allow
|
||||
principal: {}
|
||||
condition: {}
|
||||
```
|
||||
|
||||
```yaml
|
||||
name: deny-delete-cluster
|
||||
resource: ["cluster:*"]
|
||||
actions: ["delete"]
|
||||
level: platform
|
||||
effect: Deny
|
||||
```
|
||||
@@ -29,5 +29,5 @@ kubectl apply -f ./docs/examples/rollout-trait/app-v3.yaml
|
||||
|
||||
6. modify targetSize as 7 to scale
|
||||
```shell
|
||||
kubectl apply -f ./docs/examples/rollout-trait/app-sacle.yaml
|
||||
kubectl apply -f ./docs/examples/rollout-trait/app-scale.yaml
|
||||
```
|
||||
|
||||
40
docs/examples/terraform/app-jdbc.yaml
Normal file
40
docs/examples/terraform/app-jdbc.yaml
Normal file
@@ -0,0 +1,40 @@
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: jdbc
|
||||
spec:
|
||||
components:
|
||||
- name: db
|
||||
type: alibaba-rds
|
||||
properties:
|
||||
instance_name: favorite-links
|
||||
database_name: db1
|
||||
account_name: oamtest
|
||||
password: U34rfwefwefffaked
|
||||
security_ips: [ "0.0.0.0/0" ]
|
||||
privilege: ReadWrite
|
||||
writeConnectionSecretToRef:
|
||||
name: db-conn
|
||||
- name: express-server
|
||||
type: webservice
|
||||
properties:
|
||||
image: crccheck/hello-world
|
||||
port: 8000
|
||||
|
||||
workflow:
|
||||
steps:
|
||||
- name: jdbc
|
||||
type: generate-jdbc-connection
|
||||
outputs:
|
||||
- name: jdbc
|
||||
valueFrom: jdbc
|
||||
properties:
|
||||
name: db-conn
|
||||
namespace: default
|
||||
- name: apply
|
||||
type: apply-component
|
||||
inputs:
|
||||
- from: jdbc
|
||||
parameterKey: env
|
||||
properties:
|
||||
component: express-server
|
||||
25
docs/examples/traits/annotations/example.yaml
Normal file
25
docs/examples/traits/annotations/example.yaml
Normal file
@@ -0,0 +1,25 @@
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: busybox
|
||||
spec:
|
||||
components:
|
||||
- name: busybox
|
||||
type: webservice
|
||||
properties:
|
||||
image: busybox
|
||||
cmd: ["sleep", "86400"]
|
||||
annotations:
|
||||
annotation-key: annotation-value
|
||||
to-delete-annotation-key: to-delete-annotation-value
|
||||
traits:
|
||||
# the `annotations` trait will add/delete annotation key/value pair to the
|
||||
# labels of the workload and the template inside the spec of the workload (if exists)
|
||||
# 1. if original annotations contains the key, value will be overridden
|
||||
# 2. if original annotations do not contain the key, value will be added
|
||||
# 3. if original annotations contains the key and the value is null, the key will be removed
|
||||
- type: annotations
|
||||
properties:
|
||||
added-annotation-key: added-annotation-value
|
||||
annotation-key: modified-annotation-value
|
||||
to-delete-annotation-key: null
|
||||
@@ -23,11 +23,6 @@ spec:
|
||||
- type: json-patch
|
||||
properties:
|
||||
operations:
|
||||
- op: add
|
||||
path: "/metadata"
|
||||
value:
|
||||
labels:
|
||||
deploy-label-key: deploy-label-added-value
|
||||
- op: add
|
||||
path: "/spec/replicas"
|
||||
value: 3
|
||||
|
||||
25
docs/examples/traits/labels/example.yaml
Normal file
25
docs/examples/traits/labels/example.yaml
Normal file
@@ -0,0 +1,25 @@
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: busybox
|
||||
spec:
|
||||
components:
|
||||
- name: busybox
|
||||
type: webservice
|
||||
properties:
|
||||
image: busybox
|
||||
cmd: ["sleep", "86400"]
|
||||
labels:
|
||||
label-key: label-value
|
||||
to-delete-label-key: to-delete-label-value
|
||||
traits:
|
||||
# the `labels` trait will add/delete label key/value pair to the
|
||||
# labels of the workload and the template inside the spec of the workload (if exists)
|
||||
# 1. if original labels contains the key, value will be overridden
|
||||
# 2. if original labels do not contain the key, value will be added
|
||||
# 3. if original labels contains the key and the value is null, the key will be removed
|
||||
- type: labels
|
||||
properties:
|
||||
added-label-key: added-label-value
|
||||
label-key: modified-label-value
|
||||
to-delete-label-key: null
|
||||
@@ -22,6 +22,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
@@ -62,6 +64,7 @@ var _ = Describe("Addon Test", func() {
|
||||
Expect(output).To(ContainSubstring("Successfully disable addon"))
|
||||
Eventually(func(g Gomega) {
|
||||
g.Expect(apierrors.IsNotFound(k8sClient.Get(context.Background(), types.NamespacedName{Name: "addon-test-addon", Namespace: "vela-system"}, &v1beta1.Application{}))).Should(BeTrue())
|
||||
g.Expect(apierrors.IsNotFound(k8sClient.Get(context.Background(), types.NamespacedName{Name: "addon-secret-test-addon", Namespace: "vela-system"}, &v1.Secret{}))).Should(BeTrue())
|
||||
}, 60*time.Second).Should(Succeed())
|
||||
})
|
||||
|
||||
|
||||
@@ -129,7 +129,7 @@ var _ = Describe("Test Kubectl Plugin", func() {
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(output).Should(ContainSubstring(showTdResult))
|
||||
})
|
||||
It("Test show componentDefinition use Helm Charts as Workload", func() {
|
||||
PIt("Test show componentDefinition use Helm Charts as Workload", func() {
|
||||
Eventually(func() string {
|
||||
cdName := "test-webapp-chart"
|
||||
output, _ := e2e.Exec(fmt.Sprintf("kubectl-vela show %s -n default", cdName))
|
||||
@@ -156,7 +156,7 @@ var _ = Describe("Test Kubectl Plugin", func() {
|
||||
tdName := "annotations"
|
||||
output, err := e2e.Exec(fmt.Sprintf("kubectl-vela show %s -n default", tdName))
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(output).Should(ContainSubstring("map[string]string"))
|
||||
Expect(output).Should(ContainSubstring("map[string](null|string)"))
|
||||
})
|
||||
It("Test show webservice def with cue ignore annotation ", func() {
|
||||
tdName := "webservice"
|
||||
@@ -728,9 +728,7 @@ spec:
|
||||
---
|
||||
`
|
||||
|
||||
var livediffResult = `---
|
||||
# Application (test-vela-app) has been modified(*)
|
||||
---
|
||||
var livediffResult = `Application (test-vela-app) has been modified(*)
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
@@ -759,15 +757,11 @@ var livediffResult = `---
|
||||
type: test-webservice
|
||||
status: {}
|
||||
|
||||
---
|
||||
## Component (express-server) has been removed(-)
|
||||
---
|
||||
* Component (express-server) has been removed(-)
|
||||
- apiVersion: apps/v1
|
||||
- kind: Deployment
|
||||
- metadata:
|
||||
- annotations: {}
|
||||
- labels:
|
||||
- app.oam.dev/appRevision: ""
|
||||
- app.oam.dev/component: express-server
|
||||
- app.oam.dev/name: test-vela-app
|
||||
- app.oam.dev/namespace: default
|
||||
@@ -790,15 +784,11 @@ var livediffResult = `---
|
||||
- ports:
|
||||
- - containerPort: 80
|
||||
|
||||
---
|
||||
### Component (express-server) / Trait (test-ingress/service) has been removed(-)
|
||||
---
|
||||
* Component (express-server) / Trait (test-ingress/service) has been removed(-)
|
||||
- apiVersion: v1
|
||||
- kind: Service
|
||||
- metadata:
|
||||
- annotations: {}
|
||||
- labels:
|
||||
- app.oam.dev/appRevision: ""
|
||||
- app.oam.dev/component: express-server
|
||||
- app.oam.dev/name: test-vela-app
|
||||
- app.oam.dev/namespace: default
|
||||
@@ -814,15 +804,11 @@ var livediffResult = `---
|
||||
- selector:
|
||||
- app.oam.dev/component: express-server
|
||||
|
||||
---
|
||||
### Component (express-server) / Trait (test-ingress/ingress) has been removed(-)
|
||||
---
|
||||
* Component (express-server) / Trait (test-ingress/ingress) has been removed(-)
|
||||
- apiVersion: networking.k8s.io/v1beta1
|
||||
- kind: Ingress
|
||||
- metadata:
|
||||
- annotations: {}
|
||||
- labels:
|
||||
- app.oam.dev/appRevision: ""
|
||||
- app.oam.dev/component: express-server
|
||||
- app.oam.dev/name: test-vela-app
|
||||
- app.oam.dev/namespace: default
|
||||
@@ -841,15 +827,11 @@ var livediffResult = `---
|
||||
- servicePort: 80
|
||||
- path: /
|
||||
|
||||
---
|
||||
## Component (new-express-server) has been added(+)
|
||||
---
|
||||
* Component (new-express-server) has been added(+)
|
||||
+ apiVersion: apps/v1
|
||||
+ kind: Deployment
|
||||
+ metadata:
|
||||
+ annotations: {}
|
||||
+ labels:
|
||||
+ app.oam.dev/appRevision: ""
|
||||
+ app.oam.dev/component: new-express-server
|
||||
+ app.oam.dev/name: test-vela-app
|
||||
+ app.oam.dev/namespace: default
|
||||
@@ -877,15 +859,11 @@ var livediffResult = `---
|
||||
+ requests:
|
||||
+ cpu: "0.5"
|
||||
|
||||
---
|
||||
### Component (new-express-server) / Trait (test-ingress/service) has been added(+)
|
||||
---
|
||||
* Component (new-express-server) / Trait (test-ingress/service) has been added(+)
|
||||
+ apiVersion: v1
|
||||
+ kind: Service
|
||||
+ metadata:
|
||||
+ annotations: {}
|
||||
+ labels:
|
||||
+ app.oam.dev/appRevision: ""
|
||||
+ app.oam.dev/component: new-express-server
|
||||
+ app.oam.dev/name: test-vela-app
|
||||
+ app.oam.dev/namespace: default
|
||||
@@ -901,15 +879,11 @@ var livediffResult = `---
|
||||
+ selector:
|
||||
+ app.oam.dev/component: new-express-server
|
||||
|
||||
---
|
||||
### Component (new-express-server) / Trait (test-ingress/ingress) has been added(+)
|
||||
---
|
||||
* Component (new-express-server) / Trait (test-ingress/ingress) has been added(+)
|
||||
+ apiVersion: networking.k8s.io/v1beta1
|
||||
+ kind: Ingress
|
||||
+ metadata:
|
||||
+ annotations: {}
|
||||
+ labels:
|
||||
+ app.oam.dev/appRevision: ""
|
||||
+ app.oam.dev/component: new-express-server
|
||||
+ app.oam.dev/name: test-vela-app
|
||||
+ app.oam.dev/namespace: default
|
||||
|
||||
20
go.mod
20
go.mod
@@ -14,6 +14,7 @@ require (
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869
|
||||
github.com/briandowns/spinner v1.11.1
|
||||
github.com/containerd/containerd v1.4.13
|
||||
github.com/coreos/go-oidc v2.1.0+incompatible
|
||||
github.com/coreos/prometheus-operator v0.41.1
|
||||
github.com/crossplane/crossplane-runtime v0.14.1-0.20210722005935-0b469fcc77cd
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
@@ -22,6 +23,7 @@ require (
|
||||
github.com/emicklei/go-restful/v3 v3.0.0-rc2
|
||||
github.com/evanphx/json-patch v4.11.0+incompatible
|
||||
github.com/fatih/color v1.12.0
|
||||
github.com/form3tech-oss/jwt-go v3.2.3+incompatible
|
||||
github.com/fsnotify/fsnotify v1.5.1 // indirect
|
||||
github.com/gertd/go-pluralize v0.1.7
|
||||
github.com/getkin/kin-openapi v0.34.0
|
||||
@@ -41,7 +43,7 @@ require (
|
||||
github.com/kyokomi/emoji v2.2.4+incompatible
|
||||
github.com/mitchellh/hashstructure/v2 v2.0.1
|
||||
github.com/oam-dev/cluster-gateway v1.1.6
|
||||
github.com/oam-dev/cluster-register v1.0.3
|
||||
github.com/oam-dev/cluster-register v1.0.4-0.20220325092210-cee4a3d3fb7d
|
||||
github.com/oam-dev/terraform-config-inspect v0.0.0-20210418082552-fc72d929aa28
|
||||
github.com/oam-dev/terraform-controller v0.4.2
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
@@ -61,8 +63,10 @@ require (
|
||||
github.com/wonderflow/cert-manager-api v1.0.3
|
||||
go.mongodb.org/mongo-driver v1.5.1
|
||||
go.uber.org/zap v1.18.1
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97
|
||||
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 // indirect
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211
|
||||
golang.org/x/tools v0.1.6 // indirect
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||
@@ -74,8 +78,10 @@ require (
|
||||
k8s.io/api v0.22.1
|
||||
k8s.io/apiextensions-apiserver v0.22.1
|
||||
k8s.io/apimachinery v0.22.1
|
||||
k8s.io/apiserver v0.22.1
|
||||
k8s.io/cli-runtime v0.21.0
|
||||
k8s.io/client-go v0.22.1
|
||||
k8s.io/component-base v0.22.1
|
||||
k8s.io/klog v1.0.0
|
||||
k8s.io/klog/v2 v2.9.0
|
||||
k8s.io/kube-aggregator v0.22.1
|
||||
@@ -140,13 +146,13 @@ require (
|
||||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916 // indirect
|
||||
github.com/docker/go-units v0.4.0 // indirect
|
||||
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 // indirect
|
||||
github.com/emicklei/go-restful v2.9.5+incompatible // indirect
|
||||
github.com/emicklei/proto v1.6.15 // indirect
|
||||
github.com/emirpasic/gods v1.12.0 // indirect
|
||||
github.com/evanphx/json-patch/v5 v5.1.0 // indirect
|
||||
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect
|
||||
github.com/fatih/camelcase v1.0.0 // indirect
|
||||
github.com/form3tech-oss/jwt-go v3.2.3+incompatible // indirect
|
||||
github.com/ghodss/yaml v1.0.0 // indirect
|
||||
github.com/go-errors/errors v1.0.1 // indirect
|
||||
github.com/go-logr/zapr v0.4.0 // indirect
|
||||
@@ -212,6 +218,7 @@ require (
|
||||
github.com/pelletier/go-toml v1.9.3 // indirect
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021 // indirect
|
||||
github.com/prometheus/client_model v0.2.0 // indirect
|
||||
github.com/prometheus/common v0.26.0 // indirect
|
||||
github.com/prometheus/procfs v0.6.0 // indirect
|
||||
@@ -242,12 +249,10 @@ require (
|
||||
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect
|
||||
go.uber.org/atomic v1.7.0 // indirect
|
||||
go.uber.org/multierr v1.6.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect
|
||||
golang.org/x/mod v0.4.2 // indirect
|
||||
golang.org/x/net v0.0.0-20211029224645-99673261e6eb // indirect
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b // indirect
|
||||
golang.org/x/text v0.3.6 // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
|
||||
@@ -258,14 +263,13 @@ require (
|
||||
gopkg.in/gorp.v1 v1.7.2 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/ini.v1 v1.62.0 // indirect
|
||||
gopkg.in/square/go-jose.v2 v2.2.2 // indirect
|
||||
gopkg.in/src-d/go-billy.v4 v4.3.2 // indirect
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
istio.io/api v0.0.0-20210128181506-0c4b8e54850f // indirect
|
||||
istio.io/gogo-genproto v0.0.0-20190930162913-45029607206a // indirect
|
||||
k8s.io/apiserver v0.22.1 // indirect
|
||||
k8s.io/component-base v0.22.1 // indirect
|
||||
sigs.k8s.io/apiserver-network-proxy v0.0.24 // indirect
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.24 // indirect
|
||||
sigs.k8s.io/apiserver-runtime v1.0.3-0.20210913073608-0663f60bfee2 // indirect
|
||||
|
||||
20
go.sum
20
go.sum
@@ -353,6 +353,7 @@ github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc
|
||||
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/etcd v3.3.15+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
||||
github.com/coreos/go-oidc v2.1.0+incompatible h1:sdJrfw8akMnCuUlaZU3tE/uYXFgfqom8DBE9so9EBsM=
|
||||
github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=
|
||||
@@ -419,8 +420,9 @@ github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw
|
||||
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
|
||||
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1 h1:ZClxb8laGDf5arXfYcAtECDFgAgHklGI8CxgjHnXKJ4=
|
||||
github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
|
||||
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4=
|
||||
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
|
||||
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
|
||||
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
|
||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
@@ -1250,8 +1252,8 @@ github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/oam-dev/cluster-gateway v1.1.6 h1:CY6m2Qcs6XJ/l/NY48CdHD7GAel9zZ/erUOz2zYzxkI=
|
||||
github.com/oam-dev/cluster-gateway v1.1.6/go.mod h1:SF7S4Ss+VUs2OVxmvSrrFGcaNFoXy6JWxHAnUxC1QcY=
|
||||
github.com/oam-dev/cluster-register v1.0.3 h1:n6OTkNYxXYtkl2KjFv8444hF0B3SV9uyP8FL8G1QPUk=
|
||||
github.com/oam-dev/cluster-register v1.0.3/go.mod h1:AoqoF9HgmluxtRBYyvKDbLNdlPY6Xvm+/6uo6LjLaBw=
|
||||
github.com/oam-dev/cluster-register v1.0.4-0.20220325092210-cee4a3d3fb7d h1:ZZsBkksYDzwJEjqx9/XBD+VwlhHz8flkZvMJYzO4ASA=
|
||||
github.com/oam-dev/cluster-register v1.0.4-0.20220325092210-cee4a3d3fb7d/go.mod h1:nKEUMfuEB8pHKsaSah9IA+UQzezrPYebBdRozyNtlZc=
|
||||
github.com/oam-dev/stern v1.13.2 h1:jlGgtJbKmIVhzkH44ft5plkgs8XEfvxbFrQdX60CQR4=
|
||||
github.com/oam-dev/stern v1.13.2/go.mod h1:0pLjZt0amXE/ErF16Rdrgd98H2owN8Hmn3/7CX5+AeA=
|
||||
github.com/oam-dev/terraform-config-inspect v0.0.0-20210418082552-fc72d929aa28 h1:tD8HiFKnt0jnwdTWjeqUnfnUYLD/+Nsmj8ZGIxqDWiU=
|
||||
@@ -1359,6 +1361,7 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/polyfloyd/go-errorlint v0.0.0-20210510181950-ab96adb96fea/go.mod h1:wi9BfjxjF/bwiZ701TzmfKu6UKC357IOAtNr0Td0Lvw=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021 h1:0XM1XL/OFFJjXsYXlG30spTkV/E9+gmd5GD1w2HE8xM=
|
||||
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
|
||||
github.com/prometheus-community/prom-label-proxy v0.1.1-0.20200616110844-0fbfa11fa8f3/go.mod h1:XdjyZg7LCbCC5FADHtpgNp6kQ0W9beXVGfmcvndMj5Y=
|
||||
github.com/prometheus/alertmanager v0.18.0/go.mod h1:WcxHBl40VSPuOaqWae6l6HpnEOVRIycEJ7i9iYkadEE=
|
||||
@@ -2044,13 +2047,14 @@ golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 h1:foEbQz/B0Oz6YIqu/69kfXPYeFQAuuMYFkjaqXzl5Wo=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE=
|
||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -2061,8 +2065,9 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/time v0.0.0-20161028155119-f51c12702a4d/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
@@ -2385,6 +2390,7 @@ gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/square/go-jose.v2 v2.2.2 h1:orlkJ3myw8CN1nVQHBFfloD+L3egixIa4FvUP6RosSA=
|
||||
gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
gopkg.in/src-d/go-billy.v4 v4.3.2 h1:0SQA1pRztfTFx2miS8sA97XvooFeNOmvUenF4o0EcVg=
|
||||
gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98=
|
||||
|
||||
@@ -42,7 +42,8 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if err := ref.GenerateReferenceDocs(ctx, c, path, types.DefaultKubeVelaNS); err != nil {
|
||||
ref.Remote = &plugins.Remote{Namespace: types.DefaultKubeVelaNS}
|
||||
if err := ref.GenerateReferenceDocs(ctx, c, path); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
@@ -2025,6 +2025,12 @@ spec:
|
||||
- jsonPath: .metadata.creationTimestamp
|
||||
name: AGE
|
||||
type: date
|
||||
- jsonPath: .metadata.annotations['app\.oam\.dev\/publishVersion']
|
||||
name: PUBLISH_VERSION
|
||||
type: string
|
||||
- jsonPath: .status.succeeded
|
||||
name: SUCCEEDED
|
||||
type: string
|
||||
name: v1beta1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
@@ -2747,13 +2753,6 @@ spec:
|
||||
type: object
|
||||
type: object
|
||||
type: object
|
||||
applicationConfiguration:
|
||||
description: ApplicationConfiguration records the rendered applicationConfiguration
|
||||
from Application, it will contains the whole K8s CR of trait and
|
||||
the reference component in it.
|
||||
type: object
|
||||
|
||||
|
||||
componentDefinitions:
|
||||
additionalProperties:
|
||||
description: ComponentDefinition is the Schema for the componentdefinitions
|
||||
@@ -3087,20 +3086,51 @@ spec:
|
||||
description: ComponentDefinitions records the snapshot of the componentDefinitions
|
||||
related with the created/modified Application
|
||||
type: object
|
||||
components:
|
||||
description: Components records the rendered components from Application,
|
||||
it will contains the whole K8s CR of workload in it.
|
||||
items:
|
||||
description: RawComponent record raw component
|
||||
policies:
|
||||
additionalProperties:
|
||||
description: Policy is the Schema for the policy API
|
||||
properties:
|
||||
raw:
|
||||
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:
|
||||
properties:
|
||||
annotations:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
finalizers:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
labels:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
name:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
type: object
|
||||
properties:
|
||||
type: object
|
||||
|
||||
|
||||
type:
|
||||
type: string
|
||||
required:
|
||||
- raw
|
||||
- type
|
||||
type: object
|
||||
type: array
|
||||
description: Policies records the external policies
|
||||
type: object
|
||||
policyDefinitions:
|
||||
additionalProperties:
|
||||
description: PolicyDefinition is the Schema for the policydefinitions
|
||||
@@ -3377,15 +3407,16 @@ spec:
|
||||
description: PolicyDefinitions records the snapshot of the PolicyDefinitions
|
||||
related with the created/modified Application
|
||||
type: object
|
||||
resourcesConfigMap:
|
||||
description: ResourcesConfigMap references the ConfigMap that's generated
|
||||
to contain all final rendered resources.
|
||||
properties:
|
||||
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
|
||||
type: object
|
||||
referredObjects:
|
||||
description: ReferredObjects records the referred objects used in
|
||||
the ref-object typed components
|
||||
items:
|
||||
description: ReferredObject the referred Kubernetes object
|
||||
type: object
|
||||
|
||||
|
||||
type: array
|
||||
|
||||
scopeDefinitions:
|
||||
additionalProperties:
|
||||
description: A ScopeDefinition registers a kind of Kubernetes custom
|
||||
@@ -3819,6 +3850,89 @@ spec:
|
||||
description: TraitDefinitions records the snapshot of the traitDefinitions
|
||||
related with the created/modified Application
|
||||
type: object
|
||||
workflow:
|
||||
description: Workflow records the external workflow
|
||||
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:
|
||||
properties:
|
||||
annotations:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
finalizers:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
labels:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
name:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
type: object
|
||||
steps:
|
||||
items:
|
||||
description: WorkflowStep defines how to execute a workflow
|
||||
step.
|
||||
properties:
|
||||
dependsOn:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
inputs:
|
||||
description: StepInputs defines variable input of WorkflowStep
|
||||
items:
|
||||
properties:
|
||||
from:
|
||||
type: string
|
||||
parameterKey:
|
||||
type: string
|
||||
required:
|
||||
- from
|
||||
- parameterKey
|
||||
type: object
|
||||
type: array
|
||||
name:
|
||||
description: Name is the unique name of the workflow step.
|
||||
type: string
|
||||
outputs:
|
||||
description: StepOutputs defines output variable of WorkflowStep
|
||||
items:
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
valueFrom:
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
- valueFrom
|
||||
type: object
|
||||
type: array
|
||||
properties:
|
||||
type: object
|
||||
|
||||
type:
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
- type
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
workflowStepDefinitions:
|
||||
additionalProperties:
|
||||
description: WorkflowStepDefinition is the Schema for the workflowstepdefinitions
|
||||
@@ -4408,10 +4522,182 @@ spec:
|
||||
required:
|
||||
- application
|
||||
type: object
|
||||
status:
|
||||
description: ApplicationRevisionStatus is the status of ApplicationRevision
|
||||
properties:
|
||||
succeeded:
|
||||
description: Succeeded records if the workflow finished running with
|
||||
success
|
||||
type: boolean
|
||||
workflow:
|
||||
description: Workflow the running status of the workflow
|
||||
properties:
|
||||
appRevision:
|
||||
type: string
|
||||
contextBackend:
|
||||
description: 'ObjectReference contains enough information to let
|
||||
you inspect or modify the referred object. --- New uses of this
|
||||
type are discouraged because of difficulty describing its usage
|
||||
when embedded in APIs. 1. Ignored fields. It includes many
|
||||
fields which are not generally honored. For instance, ResourceVersion
|
||||
and FieldPath are both very rarely valid in actual usage. 2.
|
||||
Invalid usage help. It is impossible to add specific help for
|
||||
individual usage. In most embedded usages, there are particular restrictions
|
||||
like, "must refer only to types A and B" or "UID not honored"
|
||||
or "name must be restricted". Those cannot be well described
|
||||
when embedded. 3. Inconsistent validation. Because the usages
|
||||
are different, the validation rules are different by usage,
|
||||
which makes it hard for users to predict what will happen. 4.
|
||||
The fields are both imprecise and overly precise. Kind is not
|
||||
a precise mapping to a URL. This can produce ambiguity during
|
||||
interpretation and require a REST mapping. In most cases, the
|
||||
dependency is on the group,resource tuple and the version
|
||||
of the actual struct is irrelevant. 5. We cannot easily change
|
||||
it. Because this type is embedded in many locations, updates
|
||||
to this type will affect numerous schemas. Don''t make
|
||||
new APIs embed an underspecified API type they do not control.
|
||||
Instead of using this type, create a locally provided and used
|
||||
type that is well-focused on your reference. For example, ServiceReferences
|
||||
for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533
|
||||
.'
|
||||
properties:
|
||||
apiVersion:
|
||||
description: API version of the referent.
|
||||
type: string
|
||||
fieldPath:
|
||||
description: 'If referring to a piece of an object instead
|
||||
of an entire object, this string should contain a valid
|
||||
JSON/Go field access statement, such as desiredState.manifest.containers[2].
|
||||
For example, if the object reference is to a container within
|
||||
a pod, this would take on a value like: "spec.containers{name}"
|
||||
(where "name" refers to the name of the container that triggered
|
||||
the event) or if no container name is specified "spec.containers[2]"
|
||||
(container with index 2 in this pod). This syntax is chosen
|
||||
only to have some well-defined way of referencing a part
|
||||
of an object. TODO: this design is not final and this field
|
||||
is subject to change in the future.'
|
||||
type: string
|
||||
kind:
|
||||
description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
||||
type: string
|
||||
name:
|
||||
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
|
||||
type: string
|
||||
namespace:
|
||||
description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
|
||||
type: string
|
||||
resourceVersion:
|
||||
description: 'Specific resourceVersion to which this reference
|
||||
is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
|
||||
type: string
|
||||
uid:
|
||||
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
|
||||
type: string
|
||||
type: object
|
||||
finished:
|
||||
type: boolean
|
||||
message:
|
||||
type: string
|
||||
mode:
|
||||
description: WorkflowMode describes the mode of workflow
|
||||
type: string
|
||||
startTime:
|
||||
format: date-time
|
||||
type: string
|
||||
steps:
|
||||
items:
|
||||
description: WorkflowStepStatus record the status of a workflow
|
||||
step
|
||||
properties:
|
||||
firstExecuteTime:
|
||||
description: FirstExecuteTime is the first time this step
|
||||
execution.
|
||||
format: date-time
|
||||
type: string
|
||||
id:
|
||||
type: string
|
||||
lastExecuteTime:
|
||||
description: LastExecuteTime is the last time this step
|
||||
execution.
|
||||
format: date-time
|
||||
type: string
|
||||
message:
|
||||
description: A human readable message indicating details
|
||||
about why the workflowStep is in this state.
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
phase:
|
||||
description: WorkflowStepPhase describes the phase of a
|
||||
workflow step.
|
||||
type: string
|
||||
reason:
|
||||
description: A brief CamelCase message indicating details
|
||||
about why the workflowStep is in this state.
|
||||
type: string
|
||||
subSteps:
|
||||
description: SubStepsStatus record the status of workflow
|
||||
steps.
|
||||
properties:
|
||||
mode:
|
||||
description: WorkflowMode describes the mode of workflow
|
||||
type: string
|
||||
stepIndex:
|
||||
type: integer
|
||||
steps:
|
||||
items:
|
||||
description: WorkflowSubStepStatus record the status
|
||||
of a workflow step
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
message:
|
||||
description: A human readable message indicating
|
||||
details about why the workflowStep is in this
|
||||
state.
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
phase:
|
||||
description: WorkflowStepPhase describes the phase
|
||||
of a workflow step.
|
||||
type: string
|
||||
reason:
|
||||
description: A brief CamelCase message indicating
|
||||
details about why the workflowStep is in this
|
||||
state.
|
||||
type: string
|
||||
type:
|
||||
type: string
|
||||
required:
|
||||
- id
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
type:
|
||||
type: string
|
||||
required:
|
||||
- id
|
||||
type: object
|
||||
type: array
|
||||
suspend:
|
||||
type: boolean
|
||||
terminated:
|
||||
type: boolean
|
||||
required:
|
||||
- finished
|
||||
- mode
|
||||
- suspend
|
||||
- terminated
|
||||
type: object
|
||||
required:
|
||||
- succeeded
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
subresources: {}
|
||||
subresources:
|
||||
status: {}
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
|
||||
@@ -53,6 +53,7 @@ import (
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
common2 "github.com/oam-dev/kubevela/apis/core.oam.dev/common"
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha1"
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
|
||||
"github.com/oam-dev/kubevela/apis/types"
|
||||
utils2 "github.com/oam-dev/kubevela/pkg/controller/utils"
|
||||
@@ -113,6 +114,9 @@ var (
|
||||
|
||||
// CLIMetaOptions get Addon metadata for CLI display
|
||||
CLIMetaOptions = ListOptions{}
|
||||
|
||||
// UnInstallOptions used for addon uninstalling
|
||||
UnInstallOptions = ListOptions{GetDefinition: true}
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -282,6 +286,7 @@ func GetUIDataFromReader(r AsyncReader, meta *SourceMeta, opt ListOptions) (*UID
|
||||
return nil, fmt.Errorf("fail to generate openAPIschema for addon %s : %w", meta.Name, err)
|
||||
}
|
||||
}
|
||||
addon.AvailableVersions = []string{addon.Version}
|
||||
return addon, nil
|
||||
}
|
||||
|
||||
@@ -520,32 +525,22 @@ func genAddonAPISchema(addonRes *UIData) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// RenderApp render a K8s application
|
||||
func RenderApp(ctx context.Context, addon *InstallPackage, config *rest.Config, k8sClient client.Client, args map[string]interface{}) (*v1beta1.Application, error) {
|
||||
if args == nil {
|
||||
args = map[string]interface{}{}
|
||||
func getClusters(args map[string]interface{}) []string {
|
||||
ccr, ok := args[types.ClustersArg]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
app := addon.AppTemplate
|
||||
if app == nil {
|
||||
app = &v1beta1.Application{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: "core.oam.dev/v1beta1", Kind: "Application"},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: Convert2AppName(addon.Name),
|
||||
Namespace: types.DefaultKubeVelaNS,
|
||||
Labels: map[string]string{
|
||||
oam.LabelAddonName: addon.Name,
|
||||
},
|
||||
},
|
||||
Spec: v1beta1.ApplicationSpec{
|
||||
Components: []common2.ApplicationComponent{},
|
||||
},
|
||||
}
|
||||
cc, ok := ccr.([]string)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
app.Labels = util.MergeMapOverrideWithDst(app.Labels, map[string]string{oam.LabelAddonName: addon.Name})
|
||||
|
||||
// force override the namespace defined vela with DefaultVelaNS,this value can be modified by Env
|
||||
app.SetNamespace(types.DefaultKubeVelaNS)
|
||||
return cc
|
||||
}
|
||||
|
||||
// renderNeededNamespaceAsComps will convert namespace as app components to create namespace for managed clusters
|
||||
func renderNeededNamespaceAsComps(addon *InstallPackage) []common2.ApplicationComponent {
|
||||
var nscomps []common2.ApplicationComponent
|
||||
// create namespace for managed clusters
|
||||
for _, namespace := range addon.NeedNamespace {
|
||||
// vela-system must exist before rendering vela addon
|
||||
if namespace == types.DefaultKubeVelaNS {
|
||||
@@ -556,42 +551,157 @@ func RenderApp(ctx context.Context, addon *InstallPackage, config *rest.Config,
|
||||
Name: fmt.Sprintf("%s-namespace", namespace),
|
||||
Properties: util.Object2RawExtension(renderNamespace(namespace)),
|
||||
}
|
||||
app.Spec.Components = append(app.Spec.Components, comp)
|
||||
nscomps = append(nscomps, comp)
|
||||
}
|
||||
return nscomps
|
||||
}
|
||||
|
||||
func renderResources(addon *InstallPackage, args map[string]interface{}) ([]common2.ApplicationComponent, error) {
|
||||
var resources []common2.ApplicationComponent
|
||||
if len(addon.YAMLTemplates) != 0 {
|
||||
comp, err := renderK8sObjectsComponent(addon.YAMLTemplates, addon.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
app.Spec.Components = append(app.Spec.Components, *comp)
|
||||
resources = append(resources, *comp)
|
||||
}
|
||||
|
||||
for _, tmpl := range addon.CUETemplates {
|
||||
comp, err := renderCUETemplate(tmpl, addon.Parameters, args)
|
||||
comp, err := renderCUETemplate(tmpl, addon.Parameters, args, addon.Meta)
|
||||
if err != nil {
|
||||
return nil, ErrRenderCueTmpl
|
||||
return nil, NewAddonError(fmt.Sprintf("fail to render cue template %s", err.Error()))
|
||||
}
|
||||
if addon.Name == ObservabilityAddon && strings.HasSuffix(comp.Name, ".cue") {
|
||||
comp.Name = strings.Split(comp.Name, ".cue")[0]
|
||||
}
|
||||
app.Spec.Components = append(app.Spec.Components, *comp)
|
||||
resources = append(resources, *comp)
|
||||
}
|
||||
return resources, nil
|
||||
}
|
||||
|
||||
func formatAppFramework(addon *InstallPackage) *v1beta1.Application {
|
||||
app := addon.AppTemplate
|
||||
if app == nil {
|
||||
app = &v1beta1.Application{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: "core.oam.dev/v1beta1", Kind: "Application"},
|
||||
Spec: v1beta1.ApplicationSpec{
|
||||
Components: []common2.ApplicationComponent{},
|
||||
},
|
||||
}
|
||||
}
|
||||
if app.Spec.Components == nil {
|
||||
app.Spec.Components = []common2.ApplicationComponent{}
|
||||
}
|
||||
app.Name = Convert2AppName(addon.Name)
|
||||
// force override the namespace defined vela with DefaultVelaNS,this value can be modified by Env
|
||||
app.SetNamespace(types.DefaultKubeVelaNS)
|
||||
if app.Labels == nil {
|
||||
app.Labels = make(map[string]string)
|
||||
}
|
||||
app.Labels[oam.LabelAddonName] = addon.Name
|
||||
app.Labels[oam.LabelAddonVersion] = addon.Version
|
||||
return app
|
||||
}
|
||||
|
||||
func checkDeployClusters(ctx context.Context, k8sClient client.Client, args map[string]interface{}) ([]string, error) {
|
||||
deployClusters := getClusters(args)
|
||||
if len(deployClusters) == 0 || k8sClient == nil {
|
||||
return nil, nil
|
||||
}
|
||||
vcs, err := multicluster.ListVirtualClusters(ctx, k8sClient)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var res []string
|
||||
for _, c := range deployClusters {
|
||||
c = strings.TrimSpace(c)
|
||||
if c == "" {
|
||||
continue
|
||||
}
|
||||
var found bool
|
||||
for _, vc := range vcs {
|
||||
if c == vc.Name {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return nil, errors.Errorf("cluster %s not exist", c)
|
||||
}
|
||||
res = append(res, c)
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// RenderApp render a K8s application
|
||||
func RenderApp(ctx context.Context, addon *InstallPackage, k8sClient client.Client, args map[string]interface{}) (*v1beta1.Application, error) {
|
||||
|
||||
if args == nil {
|
||||
args = map[string]interface{}{}
|
||||
}
|
||||
|
||||
app := formatAppFramework(addon)
|
||||
app.Spec.Components = append(app.Spec.Components, renderNeededNamespaceAsComps(addon)...)
|
||||
|
||||
resources, err := renderResources(addon, args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
app.Spec.Components = append(app.Spec.Components, resources...)
|
||||
|
||||
deployClusters, err := checkDeployClusters(ctx, k8sClient, args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch {
|
||||
case isDeployToRuntimeOnly(addon):
|
||||
if app.Spec.Workflow == nil {
|
||||
app.Spec.Workflow = &v1beta1.Workflow{Steps: make([]v1beta1.WorkflowStep, 0)}
|
||||
}
|
||||
app.Spec.Workflow.Steps = append(app.Spec.Workflow.Steps,
|
||||
v1beta1.WorkflowStep{
|
||||
Name: "deploy-control-plane",
|
||||
Type: "apply-application",
|
||||
},
|
||||
v1beta1.WorkflowStep{
|
||||
Name: "deploy-runtime",
|
||||
Type: "deploy2runtime",
|
||||
if len(deployClusters) == 0 {
|
||||
// deploy to all clusters
|
||||
app.Spec.Workflow = &v1beta1.Workflow{Steps: []v1beta1.WorkflowStep{
|
||||
{
|
||||
Name: "deploy-control-plane",
|
||||
Type: "apply-application",
|
||||
},
|
||||
{
|
||||
Name: "deploy-runtime",
|
||||
Type: "deploy2runtime",
|
||||
},
|
||||
}}
|
||||
// TODO(wonderflow): this can be merged into len(deployClusters) > 0 case
|
||||
/*
|
||||
allclusters, err := multicluster.ListVirtualClusters(ctx, k8sClient)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, c := range allclusters {
|
||||
deployClusters = append(deployClusters, c.Name)
|
||||
}
|
||||
*/
|
||||
} else {
|
||||
var found bool
|
||||
for _, c := range deployClusters {
|
||||
if c == multicluster.ClusterLocalName {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
deployClusters = append(deployClusters, multicluster.ClusterLocalName)
|
||||
}
|
||||
// deploy to specified clusters
|
||||
if app.Spec.Policies == nil {
|
||||
app.Spec.Policies = []v1beta1.AppPolicy{}
|
||||
}
|
||||
body, _ := json.Marshal(map[string][]string{types.ClustersArg: deployClusters})
|
||||
app.Spec.Policies = append(app.Spec.Policies, v1beta1.AppPolicy{
|
||||
Name: "specified-addon-clusters",
|
||||
Type: v1alpha1.TopologyPolicyType,
|
||||
Properties: &runtime.RawExtension{Raw: body},
|
||||
})
|
||||
// addon should not contain workflow, this also update legacy addon with deploy2runtime steps
|
||||
app.Spec.Workflow = nil
|
||||
}
|
||||
case addon.Name == ObservabilityAddon:
|
||||
clusters, err := allocateDomainForAddon(ctx, k8sClient)
|
||||
if err != nil {
|
||||
@@ -627,36 +737,7 @@ func RenderApp(ctx context.Context, addon *InstallPackage, config *rest.Config,
|
||||
app.Spec.Workflow.Steps = append(app.Spec.Workflow.Steps, workflowSteps...)
|
||||
|
||||
default:
|
||||
for _, cueDef := range addon.CUEDefinitions {
|
||||
def := definition.Definition{Unstructured: unstructured.Unstructured{}}
|
||||
err := def.FromCUEString(cueDef.Data, config)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "fail to render definition: %s in cue's format", cueDef.Name)
|
||||
}
|
||||
if def.Unstructured.GetNamespace() == "" {
|
||||
def.Unstructured.SetNamespace(types.DefaultKubeVelaNS)
|
||||
}
|
||||
app.Spec.Components = append(app.Spec.Components, common2.ApplicationComponent{
|
||||
Name: cueDef.Name,
|
||||
Type: "raw",
|
||||
Properties: util.Object2RawExtension(&def.Unstructured),
|
||||
})
|
||||
}
|
||||
for _, teml := range addon.DefSchemas {
|
||||
u, err := renderSchemaConfigmap(teml)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
app.Spec.Components = append(app.Spec.Components, common2.ApplicationComponent{
|
||||
Name: teml.Name,
|
||||
Type: "raw",
|
||||
Properties: util.Object2RawExtension(u),
|
||||
})
|
||||
}
|
||||
// set to nil so workflow mode will be set to "DAG" automatically
|
||||
if app.Spec.Workflow != nil && len(app.Spec.Workflow.Steps) == 0 {
|
||||
app.Spec.Workflow = nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return app, nil
|
||||
@@ -695,14 +776,13 @@ func RenderDefinitions(addon *InstallPackage, config *rest.Config) ([]*unstructu
|
||||
func RenderDefinitionSchema(addon *InstallPackage) ([]*unstructured.Unstructured, error) {
|
||||
schemaConfigmaps := make([]*unstructured.Unstructured, 0)
|
||||
|
||||
if isDeployToRuntimeOnly(addon) {
|
||||
for _, teml := range addon.DefSchemas {
|
||||
u, err := renderSchemaConfigmap(teml)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
schemaConfigmaps = append(schemaConfigmaps, u)
|
||||
// No matter runtime mode or control mode , definition schemas only needs to control plane k8s.
|
||||
for _, teml := range addon.DefSchemas {
|
||||
u, err := renderSchemaConfigmap(teml)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
schemaConfigmaps = append(schemaConfigmaps, u)
|
||||
}
|
||||
return schemaConfigmaps, nil
|
||||
}
|
||||
@@ -852,17 +932,28 @@ func renderSchemaConfigmap(elem ElementFile) (*unstructured.Unstructured, error)
|
||||
}
|
||||
|
||||
// renderCUETemplate will return a component from cue template
|
||||
func renderCUETemplate(elem ElementFile, parameters string, args map[string]interface{}) (*common2.ApplicationComponent, error) {
|
||||
func renderCUETemplate(elem ElementFile, parameters string, args map[string]interface{}, metadata Meta) (*common2.ApplicationComponent, error) {
|
||||
bt, err := json.Marshal(args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var contextFile = strings.Builder{}
|
||||
var paramFile = cuemodel.ParameterFieldName + ": {}"
|
||||
if string(bt) != "null" {
|
||||
paramFile = fmt.Sprintf("%s: %s", cuemodel.ParameterFieldName, string(bt))
|
||||
}
|
||||
param := fmt.Sprintf("%s\n%s", paramFile, parameters)
|
||||
v, err := value.NewValue(param, nil, "")
|
||||
// addon metadata context
|
||||
metadataJSON, err := json.Marshal(metadata)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
contextFile.WriteString(fmt.Sprintf("context: metadata: %s\n", string(metadataJSON)))
|
||||
// parameter definition
|
||||
contextFile.WriteString(paramFile + "\n")
|
||||
// user custom parameter
|
||||
contextFile.WriteString(parameters + "\n")
|
||||
|
||||
v, err := value.NewValue(contextFile.String(), nil, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -979,7 +1070,7 @@ func (h *Installer) enableAddon(addon *InstallPackage) error {
|
||||
h.addon = addon
|
||||
err = checkAddonVersionMeetRequired(h.ctx, addon.SystemRequirements, h.cli, h.dc)
|
||||
if err != nil {
|
||||
return ErrVersionMismatch
|
||||
return VersionUnMatchError{addonName: addon.Name, err: err}
|
||||
}
|
||||
|
||||
if err = h.installDependency(addon); err != nil {
|
||||
@@ -996,26 +1087,37 @@ func (h *Installer) enableAddon(addon *InstallPackage) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *Installer) loadInstallPackage(name string) (*InstallPackage, error) {
|
||||
metas, err := h.getAddonMeta()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fail to get addon meta")
|
||||
func (h *Installer) loadInstallPackage(name, version string) (*InstallPackage, error) {
|
||||
var installPackage *InstallPackage
|
||||
var err error
|
||||
if !IsVersionRegistry(*h.r) {
|
||||
metas, err := h.getAddonMeta()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fail to get addon meta")
|
||||
}
|
||||
|
||||
meta, ok := metas[name]
|
||||
if !ok {
|
||||
return nil, ErrNotExist
|
||||
}
|
||||
var uiData *UIData
|
||||
uiData, err = h.cache.GetUIData(*h.r, name, version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// enable this addon if it's invisible
|
||||
installPackage, err = h.r.GetInstallPackage(&meta, uiData)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fail to find dependent addon in source repository")
|
||||
}
|
||||
} else {
|
||||
versionedRegistry := BuildVersionedRegistry(h.r.Name, h.r.Helm.URL)
|
||||
installPackage, err = versionedRegistry.GetAddonInstallPackage(context.Background(), name, version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
meta, ok := metas[name]
|
||||
if !ok {
|
||||
return nil, ErrNotExist
|
||||
}
|
||||
var uiData *UIData
|
||||
uiData, err = h.cache.GetUIData(*h.r, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// enable this addon if it's invisible
|
||||
installPackage, err := h.r.GetInstallPackage(&meta, uiData)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fail to find dependent addon in source repository")
|
||||
}
|
||||
return installPackage, nil
|
||||
}
|
||||
|
||||
@@ -1043,7 +1145,8 @@ func (h *Installer) installDependency(addon *InstallPackage) error {
|
||||
if !apierrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
depAddon, err := h.loadInstallPackage(dep.Name)
|
||||
// always install addon's latest version
|
||||
depAddon, err := h.loadInstallPackage(dep.Name, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1075,9 +1178,29 @@ func (h *Installer) checkDependency(addon *InstallPackage) ([]string, error) {
|
||||
}
|
||||
return needEnable, nil
|
||||
}
|
||||
func (h *Installer) createOrUpdate(app *v1beta1.Application) error {
|
||||
var getapp v1beta1.Application
|
||||
err := h.cli.Get(h.ctx, client.ObjectKey{Name: app.Name, Namespace: app.Namespace}, &getapp)
|
||||
if apierrors.IsNotFound(err) {
|
||||
return h.cli.Create(h.ctx, app)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
getapp.Spec = app.Spec
|
||||
getapp.Labels = app.Labels
|
||||
getapp.Annotations = app.Annotations
|
||||
err = h.cli.Update(h.ctx, &getapp)
|
||||
if err != nil {
|
||||
klog.Errorf("fail to create application: %v", err)
|
||||
return errors.Wrap(err, "fail to create application")
|
||||
}
|
||||
getapp.DeepCopyInto(app)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *Installer) dispatchAddonResource(addon *InstallPackage) error {
|
||||
app, err := RenderApp(h.ctx, addon, h.config, h.cli, h.args)
|
||||
app, err := RenderApp(h.ctx, addon, h.cli, h.args)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "render addon application fail")
|
||||
}
|
||||
@@ -1100,10 +1223,12 @@ func (h *Installer) dispatchAddonResource(addon *InstallPackage) error {
|
||||
return errors.Wrap(err, "render addon definitions' schema fail")
|
||||
}
|
||||
|
||||
err = h.apply.Apply(h.ctx, app, apply.DisableUpdateAnnotation())
|
||||
if err != nil {
|
||||
klog.Errorf("fail to create application: %v", err)
|
||||
return errors.Wrap(err, "fail to create application")
|
||||
if err := passDefInAppAnnotation(defs, app); err != nil {
|
||||
return errors.Wrapf(err, "cannot pass definition to addon app's annotation")
|
||||
}
|
||||
|
||||
if err = h.createOrUpdate(app); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, def := range defs {
|
||||
@@ -1219,7 +1344,7 @@ func checkAddonVersionMeetRequired(ctx context.Context, require *SystemRequireme
|
||||
return err
|
||||
}
|
||||
if !res {
|
||||
return fmt.Errorf("vela cli/ux version: %s cannot meet requirement", version2.VelaVersion)
|
||||
return fmt.Errorf("vela cli/ux version: %s require: %s", version2.VelaVersion, require.VelaVersion)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1236,7 +1361,7 @@ func checkAddonVersionMeetRequired(ctx context.Context, require *SystemRequireme
|
||||
return err
|
||||
}
|
||||
if !res {
|
||||
return fmt.Errorf("the vela core controller: %s cannot meet requirement ", imageVersion)
|
||||
return fmt.Errorf("the vela core controller: %s require: %s", imageVersion, require.VelaVersion)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1257,7 +1382,7 @@ func checkAddonVersionMeetRequired(ctx context.Context, require *SystemRequireme
|
||||
}
|
||||
|
||||
if !res {
|
||||
return fmt.Errorf("the kubernetes version %s cannot meet requirement", k8sVersion.GitVersion)
|
||||
return fmt.Errorf("the kubernetes version %s require: %s", k8sVersion.GitVersion, require.KubernetesVersion)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,9 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/oam-dev/cluster-gateway/pkg/apis/cluster/v1alpha1"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@@ -33,6 +35,7 @@ import (
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
|
||||
v1alpha12 "github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha1"
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
|
||||
"github.com/oam-dev/kubevela/apis/types"
|
||||
"github.com/oam-dev/kubevela/pkg/oam/util"
|
||||
@@ -270,6 +273,95 @@ var _ = Describe("Test addon util func", func() {
|
||||
|
||||
})
|
||||
|
||||
var _ = Describe("Test render addon with specified clusters", func() {
|
||||
BeforeEach(func() {
|
||||
Expect(k8sClient.Create(ctx, &v1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "add-c1",
|
||||
Namespace: "vela-system",
|
||||
Labels: map[string]string{
|
||||
v1alpha1.LabelKeyClusterCredentialType: string(v1alpha1.CredentialTypeX509Certificate),
|
||||
v1alpha1.LabelKeyClusterEndpointType: v1alpha1.ClusterEndpointTypeConst,
|
||||
"key": "value",
|
||||
},
|
||||
},
|
||||
})).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{}))
|
||||
Expect(k8sClient.Create(ctx, &v1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "add-c2",
|
||||
Namespace: "vela-system",
|
||||
Labels: map[string]string{
|
||||
v1alpha1.LabelKeyClusterCredentialType: string(v1alpha1.CredentialTypeX509Certificate),
|
||||
v1alpha1.LabelKeyClusterEndpointType: v1alpha1.ClusterEndpointTypeConst,
|
||||
"key": "value",
|
||||
},
|
||||
},
|
||||
})).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{}))
|
||||
})
|
||||
It("test render not exits cluster", func() {
|
||||
i := &baseAddon
|
||||
i.Name = "test-cluster-addon"
|
||||
|
||||
args := map[string]interface{}{
|
||||
"clusters": []string{"add-c1", "ne"},
|
||||
}
|
||||
_, err := RenderApp(ctx, i, k8sClient, args)
|
||||
Expect(err.Error()).Should(BeEquivalentTo("cluster ne not exist"))
|
||||
})
|
||||
It("test render normal addon with specified clusters", func() {
|
||||
i := &baseAddon
|
||||
i.DeployTo = &DeployTo{RuntimeCluster: true}
|
||||
i.Name = "test-cluster-addon-normal"
|
||||
args := map[string]interface{}{
|
||||
"clusters": []string{"add-c1", "add-c2"},
|
||||
}
|
||||
ap, err := RenderApp(ctx, i, k8sClient, args)
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(ap.Spec.Policies).Should(BeEquivalentTo([]v1beta1.AppPolicy{{Name: "specified-addon-clusters",
|
||||
Type: v1alpha12.TopologyPolicyType,
|
||||
Properties: &runtime.RawExtension{Raw: []byte(`{"clusters":["add-c1","add-c2","local"]}`)}}}))
|
||||
})
|
||||
})
|
||||
|
||||
var _ = Describe("func addon update ", func() {
|
||||
It("test update addon app label", func() {
|
||||
app_test_update := v1beta1.Application{}
|
||||
Expect(yaml.Unmarshal([]byte(addonUpdateAppYaml), &app_test_update)).Should(BeNil())
|
||||
Expect(k8sClient.Create(ctx, &app_test_update)).Should(BeNil())
|
||||
|
||||
Eventually(func() error {
|
||||
var err error
|
||||
appCheck := v1beta1.Application{}
|
||||
err = k8sClient.Get(ctx, types2.NamespacedName{Namespace: "vela-system", Name: "addon-test-update"}, &appCheck)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if appCheck.Labels["addons.oam.dev/version"] != "v1.2.0" {
|
||||
return fmt.Errorf("label missmatch")
|
||||
}
|
||||
return nil
|
||||
}, time.Millisecond*500, 30*time.Second).Should(BeNil())
|
||||
|
||||
pkg := &InstallPackage{Meta: Meta{Name: "test-update", Version: "1.3.0"}}
|
||||
h := NewAddonInstaller(context.Background(), k8sClient, nil, nil, nil, &Registry{Name: "test"}, nil, nil)
|
||||
h.addon = pkg
|
||||
Expect(h.dispatchAddonResource(pkg)).Should(BeNil())
|
||||
|
||||
Eventually(func() error {
|
||||
var err error
|
||||
appCheck := v1beta1.Application{}
|
||||
err = k8sClient.Get(context.Background(), types2.NamespacedName{Namespace: "vela-system", Name: "addon-test-update"}, &appCheck)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if appCheck.Labels["addons.oam.dev/version"] != "1.3.0" {
|
||||
return fmt.Errorf("label missmatch")
|
||||
}
|
||||
return nil
|
||||
}, time.Second*3, 300*time.Second).Should(BeNil())
|
||||
})
|
||||
})
|
||||
|
||||
const (
|
||||
appYaml = `apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
@@ -347,4 +439,21 @@ spec:
|
||||
schedulerName: default-scheduler
|
||||
securityContext: {}
|
||||
terminationGracePeriodSeconds: 30`
|
||||
|
||||
addonUpdateAppYaml = `
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: addon-test-update
|
||||
namespace: vela-system
|
||||
labels:
|
||||
addons.oam.dev/version: v1.2.0
|
||||
spec:
|
||||
components:
|
||||
- name: express-server
|
||||
type: webservice
|
||||
properties:
|
||||
image: crccheck/hello-world
|
||||
port: 8000
|
||||
`
|
||||
)
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
@@ -35,7 +36,7 @@ import (
|
||||
v1alpha12 "github.com/oam-dev/cluster-gateway/pkg/apis/cluster/v1alpha1"
|
||||
"github.com/stretchr/testify/assert"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
kerrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
@@ -61,6 +62,10 @@ var paths = []string{
|
||||
|
||||
"test-error-addon/metadata.yaml",
|
||||
"test-error-addon/resources/parameter.cue",
|
||||
|
||||
"test-disable-addon/metadata.yaml",
|
||||
"test-disable-addon/definitions/compDef.yaml",
|
||||
"test-disable-addon/definitions/traitDef.cue",
|
||||
}
|
||||
|
||||
var ossHandler http.HandlerFunc = func(rw http.ResponseWriter, req *http.Request) {
|
||||
@@ -128,7 +133,7 @@ func testReaderFunc(t *testing.T, reader AsyncReader) {
|
||||
rName := "KubeVela"
|
||||
uiDataList, err := ListAddonUIDataFromReader(reader, registryMeta, rName, UIMetaOptions)
|
||||
assert.True(t, strings.Contains(err.Error(), "#parameter.example: preference mark not allowed at this position"))
|
||||
assert.Equal(t, len(uiDataList), 3)
|
||||
assert.Equal(t, 4, len(uiDataList))
|
||||
assert.Equal(t, uiDataList[0].RegistryName, rName)
|
||||
|
||||
// test get install package
|
||||
@@ -224,15 +229,16 @@ func TestRender(t *testing.T) {
|
||||
|
||||
func TestRenderApp(t *testing.T) {
|
||||
addon := baseAddon
|
||||
app, err := RenderApp(ctx, &addon, nil, nil, map[string]interface{}{})
|
||||
app, err := RenderApp(ctx, &addon, nil, map[string]interface{}{})
|
||||
assert.NoError(t, err, "render app fail")
|
||||
assert.Equal(t, len(app.Spec.Components), 2)
|
||||
// definition should not be rendered
|
||||
assert.Equal(t, len(app.Spec.Components), 1)
|
||||
}
|
||||
|
||||
func TestRenderAppWithNeedNamespace(t *testing.T) {
|
||||
addon := baseAddon
|
||||
addon.NeedNamespace = append(addon.NeedNamespace, types.DefaultKubeVelaNS)
|
||||
app, err := RenderApp(ctx, &addon, nil, nil, map[string]interface{}{})
|
||||
addon.NeedNamespace = append(addon.NeedNamespace, types.DefaultKubeVelaNS, "test-ns2")
|
||||
app, err := RenderApp(ctx, &addon, nil, map[string]interface{}{})
|
||||
assert.NoError(t, err, "render app fail")
|
||||
assert.Equal(t, len(app.Spec.Components), 2)
|
||||
for _, c := range app.Spec.Components {
|
||||
@@ -253,7 +259,7 @@ func TestRenderDeploy2RuntimeAddon(t *testing.T) {
|
||||
assert.Equal(t, def.GetAPIVersion(), "core.oam.dev/v1beta1")
|
||||
assert.Equal(t, def.GetKind(), "TraitDefinition")
|
||||
|
||||
app, err := RenderApp(ctx, &addonDeployToRuntime, nil, nil, map[string]interface{}{})
|
||||
app, err := RenderApp(ctx, &addonDeployToRuntime, nil, map[string]interface{}{})
|
||||
assert.NoError(t, err)
|
||||
steps := app.Spec.Workflow.Steps
|
||||
assert.True(t, len(steps) >= 2)
|
||||
@@ -274,7 +280,7 @@ func TestRenderDefinitions(t *testing.T) {
|
||||
assert.Equal(t, def.GetAPIVersion(), "core.oam.dev/v1beta1")
|
||||
assert.Equal(t, def.GetKind(), "TraitDefinition")
|
||||
|
||||
app, err := RenderApp(ctx, &addonDeployToRuntime, nil, nil, map[string]interface{}{})
|
||||
app, err := RenderApp(ctx, &addonDeployToRuntime, nil, map[string]interface{}{})
|
||||
assert.NoError(t, err)
|
||||
// addon which app work on no-runtime-cluster mode workflow is nil
|
||||
assert.Nil(t, app.Spec.Workflow)
|
||||
@@ -287,7 +293,7 @@ func TestRenderK8sObjects(t *testing.T) {
|
||||
RuntimeCluster: false,
|
||||
}
|
||||
|
||||
app, err := RenderApp(ctx, &addonMultiYaml, nil, nil, map[string]interface{}{})
|
||||
app, err := RenderApp(ctx, &addonMultiYaml, nil, map[string]interface{}{})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, len(app.Spec.Components), 1)
|
||||
comp := app.Spec.Components[0]
|
||||
@@ -298,7 +304,7 @@ func TestGetAddonStatus(t *testing.T) {
|
||||
getFunc := test.MockGetFn(func(ctx context.Context, key client.ObjectKey, obj client.Object) error {
|
||||
switch key.Name {
|
||||
case "addon-disabled", "disabled":
|
||||
return errors.NewNotFound(schema.GroupResource{Group: "apiVersion: core.oam.dev/v1beta1", Resource: "app"}, key.Name)
|
||||
return kerrors.NewNotFound(schema.GroupResource{Group: "apiVersion: core.oam.dev/v1beta1", Resource: "app"}, key.Name)
|
||||
case "addon-suspend":
|
||||
o := obj.(*v1beta1.Application)
|
||||
app := &v1beta1.Application{}
|
||||
@@ -547,12 +553,12 @@ func TestRenderApp4Observability(t *testing.T) {
|
||||
},
|
||||
},
|
||||
args: map[string]interface{}{},
|
||||
application: `{"kind":"Application","apiVersion":"core.oam.dev/v1beta1","metadata":{"name":"addon-observability","namespace":"vela-system","creationTimestamp":null,"labels":{"addons.oam.dev/name":"observability"}},"spec":{"components":[],"policies":[{"name":"domain","type":"env-binding","properties":{"envs":null}}],"workflow":{"steps":[{"name":"deploy-control-plane","type":"apply-application"}]}},"status":{}}`,
|
||||
application: `{"kind":"Application","apiVersion":"core.oam.dev/v1beta1","metadata":{"name":"addon-observability","namespace":"vela-system","creationTimestamp":null,"labels":{"addons.oam.dev/name":"observability","addons.oam.dev/version":""}},"spec":{"components":[],"policies":[{"name":"domain","type":"env-binding","properties":{"envs":null}}],"workflow":{"steps":[{"name":"deploy-control-plane","type":"apply-application"}]}},"status":{}}`,
|
||||
},
|
||||
}
|
||||
for _, tc := range testcases {
|
||||
t.Run("", func(t *testing.T) {
|
||||
app, err := RenderApp(ctx, &tc.addon, nil, k8sClient, tc.args)
|
||||
app, err := RenderApp(ctx, &tc.addon, k8sClient, tc.args)
|
||||
assert.Equal(t, tc.err, err)
|
||||
if app != nil {
|
||||
data, err := json.Marshal(app)
|
||||
@@ -594,12 +600,12 @@ func TestRenderApp4ObservabilityWithK8sData(t *testing.T) {
|
||||
},
|
||||
},
|
||||
args: map[string]interface{}{},
|
||||
application: `{"kind":"Application","apiVersion":"core.oam.dev/v1beta1","metadata":{"name":"addon-observability","namespace":"vela-system","creationTimestamp":null,"labels":{"addons.oam.dev/name":"observability"}},"spec":{"components":[],"policies":[{"name":"domain","type":"env-binding","properties":{"envs":[{"name":"test-secret","placement":{"clusterSelector":{"name":"test-secret"}}}]}}],"workflow":{"steps":[{"name":"deploy-control-plane","type":"apply-application-in-parallel"},{"name":"test-secret","type":"deploy2env","properties":{"env":"test-secret","parallel":true,"policy":"domain"}}]}},"status":{}}`,
|
||||
application: `{"kind":"Application","apiVersion":"core.oam.dev/v1beta1","metadata":{"name":"addon-observability","namespace":"vela-system","creationTimestamp":null,"labels":{"addons.oam.dev/name":"observability","addons.oam.dev/version":""}},"spec":{"components":[],"policies":[{"name":"domain","type":"env-binding","properties":{"envs":[{"name":"test-secret","placement":{"clusterSelector":{"name":"test-secret"}}}]}}],"workflow":{"steps":[{"name":"deploy-control-plane","type":"apply-application-in-parallel"},{"name":"test-secret","type":"deploy2env","properties":{"env":"test-secret","parallel":true,"policy":"domain"}}]}},"status":{}}`,
|
||||
},
|
||||
}
|
||||
for _, tc := range testcases {
|
||||
t.Run("", func(t *testing.T) {
|
||||
app, err := RenderApp(ctx, &tc.addon, nil, k8sClient, tc.args)
|
||||
app, err := RenderApp(ctx, &tc.addon, k8sClient, tc.args)
|
||||
assert.Equal(t, tc.err, err)
|
||||
if app != nil {
|
||||
data, err := json.Marshal(app)
|
||||
@@ -875,3 +881,28 @@ func TestReadDefFile(t *testing.T) {
|
||||
// verify
|
||||
assert.True(t, len(uiData.Definitions) == 1)
|
||||
}
|
||||
|
||||
func TestRenderCUETemplate(t *testing.T) {
|
||||
fileDate, err := os.ReadFile("./testdata/example/resources/configmap.cue")
|
||||
assert.NoError(t, err)
|
||||
component, err := renderCUETemplate(ElementFile{Data: string(fileDate), Name: "configmap.cue"}, "{\"example\": \"\"}", map[string]interface{}{
|
||||
"example": "render",
|
||||
}, Meta{
|
||||
Version: "1.0.1",
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, component.Type == "raw")
|
||||
var config = make(map[string]interface{})
|
||||
err = json.Unmarshal(component.Properties.Raw, &config)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, component.Type == "raw")
|
||||
assert.True(t, config["metadata"].(map[string]interface{})["labels"].(map[string]interface{})["version"] == "1.0.1")
|
||||
}
|
||||
|
||||
func TestCheckEnableAddonErrorWhenMissMatch(t *testing.T) {
|
||||
version2.VelaVersion = "v1.3.0"
|
||||
i := InstallPackage{Meta: Meta{SystemRequirements: &SystemRequirements{VelaVersion: ">=1.4.0"}}}
|
||||
installer := &Installer{}
|
||||
err := installer.enableAddon(&i)
|
||||
assert.Equal(t, errors.As(err, &VersionUnMatchError{}), true)
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/oam-dev/kubevela/pkg/utils"
|
||||
|
||||
"github.com/oam-dev/kubevela/pkg/apiserver/log"
|
||||
)
|
||||
|
||||
@@ -43,6 +45,8 @@ type Cache struct {
|
||||
|
||||
registry map[string]Registry
|
||||
|
||||
versionedUIData map[string]map[string]*UIData
|
||||
|
||||
mutex *sync.RWMutex
|
||||
|
||||
ds RegistryDataStore
|
||||
@@ -51,11 +55,12 @@ type Cache struct {
|
||||
// NewCache will build a new cache instance
|
||||
func NewCache(ds RegistryDataStore) *Cache {
|
||||
return &Cache{
|
||||
uiData: make(map[string][]*UIData),
|
||||
registryMeta: make(map[string]map[string]SourceMeta),
|
||||
registry: make(map[string]Registry),
|
||||
mutex: new(sync.RWMutex),
|
||||
ds: ds,
|
||||
uiData: make(map[string][]*UIData),
|
||||
registryMeta: make(map[string]map[string]SourceMeta),
|
||||
registry: make(map[string]Registry),
|
||||
versionedUIData: make(map[string]map[string]*UIData),
|
||||
mutex: new(sync.RWMutex),
|
||||
ds: ds,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,21 +85,35 @@ func (u *Cache) ListAddonMeta(r Registry) (map[string]SourceMeta, error) {
|
||||
}
|
||||
|
||||
// GetUIData get addon data for UI display from cache, if cache not found, it will find from source
|
||||
func (u *Cache) GetUIData(r Registry, addonName string) (*UIData, error) {
|
||||
addon := u.getCachedUIData(r.Name, addonName)
|
||||
func (u *Cache) GetUIData(r Registry, addonName, version string) (*UIData, error) {
|
||||
addon := u.getCachedUIData(r, addonName, version)
|
||||
if addon != nil {
|
||||
return addon, nil
|
||||
}
|
||||
var err error
|
||||
registryMeta, err := u.ListAddonMeta(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if !IsVersionRegistry(r) {
|
||||
registryMeta, err := u.ListAddonMeta(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
meta, ok := registryMeta[addonName]
|
||||
if !ok {
|
||||
return nil, ErrNotExist
|
||||
}
|
||||
addon, err = r.GetUIData(&meta, UIMetaOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
versionedRegistry := BuildVersionedRegistry(r.Name, r.Helm.URL)
|
||||
addon, err = versionedRegistry.GetAddonUIData(context.Background(), addonName, version)
|
||||
if err != nil {
|
||||
log.Logger.Errorf("fail to get addons from registry %s for cache updating, %v", utils.Sanitize(r.Name), err)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
meta, ok := registryMeta[addonName]
|
||||
if !ok {
|
||||
return nil, ErrNotExist
|
||||
}
|
||||
return r.GetUIData(&meta, UIMetaOptions)
|
||||
|
||||
return addon, nil
|
||||
}
|
||||
|
||||
// ListUIData will always list UIData from cache first, if not exist, read from source.
|
||||
@@ -104,24 +123,40 @@ func (u *Cache) ListUIData(r Registry) ([]*UIData, error) {
|
||||
if listAddons != nil {
|
||||
return listAddons, nil
|
||||
}
|
||||
addonMeta, err := u.ListAddonMeta(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
listAddons, err = r.ListUIData(addonMeta, UIMetaOptions)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("fail to get addons from registry %s, %w", r.Name, err)
|
||||
if !IsVersionRegistry(r) {
|
||||
addonMeta, err := u.ListAddonMeta(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
listAddons, err = r.ListUIData(addonMeta, UIMetaOptions)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("fail to get addons from registry %s, %w", r.Name, err)
|
||||
}
|
||||
} else {
|
||||
versionedRegistry := BuildVersionedRegistry(r.Name, r.Helm.URL)
|
||||
listAddons, err = versionedRegistry.ListAddon()
|
||||
if err != nil {
|
||||
log.Logger.Errorf("fail to get addons from registry %s for cache updating, %v", r.Name, err)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
u.putAddonUIData2Cache(r.Name, listAddons)
|
||||
return listAddons, nil
|
||||
}
|
||||
|
||||
func (u *Cache) getCachedUIData(registry, addonName string) *UIData {
|
||||
addons := u.listCachedUIData(registry)
|
||||
for _, a := range addons {
|
||||
if a.Name == addonName {
|
||||
return a
|
||||
func (u *Cache) getCachedUIData(registry Registry, addonName, version string) *UIData {
|
||||
if !IsVersionRegistry(registry) {
|
||||
addons := u.listCachedUIData(registry.Name)
|
||||
for _, a := range addons {
|
||||
if a.Name == addonName {
|
||||
return a
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if len(version) == 0 {
|
||||
version = "latest"
|
||||
}
|
||||
return u.versionedUIData[registry.Name][fmt.Sprintf("%s-%s", addonName, version)]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -201,6 +236,20 @@ func (u *Cache) putRegistry2Cache(registry []Registry) {
|
||||
}
|
||||
}
|
||||
|
||||
func (u *Cache) putVersionedUIData2Cache(registryName, addonName, version string, uiData *UIData) {
|
||||
if u == nil {
|
||||
return
|
||||
}
|
||||
|
||||
u.mutex.Lock()
|
||||
defer u.mutex.Unlock()
|
||||
|
||||
if u.versionedUIData[registryName] == nil {
|
||||
u.versionedUIData[registryName] = make(map[string]*UIData)
|
||||
}
|
||||
u.versionedUIData[registryName][fmt.Sprintf("%s-%s", addonName, version)] = uiData
|
||||
}
|
||||
|
||||
func (u *Cache) discoverAndRefreshRegistry() {
|
||||
registries, err := u.ds.ListRegistries(context.Background())
|
||||
if err != nil {
|
||||
@@ -210,17 +259,36 @@ func (u *Cache) discoverAndRefreshRegistry() {
|
||||
u.putRegistry2Cache(registries)
|
||||
|
||||
for _, r := range registries {
|
||||
registryMeta, err := r.ListAddonMeta()
|
||||
if err != nil {
|
||||
log.Logger.Errorf("fail to list registry %s metadata, %v", r.Name, err)
|
||||
continue
|
||||
if !IsVersionRegistry(r) {
|
||||
registryMeta, err := r.ListAddonMeta()
|
||||
if err != nil {
|
||||
log.Logger.Errorf("fail to list registry %s metadata, %v", r.Name, err)
|
||||
continue
|
||||
}
|
||||
u.putAddonMeta2Cache(r.Name, registryMeta)
|
||||
uiData, err := r.ListUIData(registryMeta, UIMetaOptions)
|
||||
if err != nil {
|
||||
log.Logger.Errorf("fail to get addons from registry %s for cache updating, %v", r.Name, err)
|
||||
continue
|
||||
}
|
||||
u.putAddonUIData2Cache(r.Name, uiData)
|
||||
} else {
|
||||
versionedRegistry := BuildVersionedRegistry(r.Name, r.Helm.URL)
|
||||
uiDatas, err := versionedRegistry.ListAddon()
|
||||
if err != nil {
|
||||
log.Logger.Errorf("fail to get addons from registry %s for cache updating, %v", r.Name, err)
|
||||
continue
|
||||
}
|
||||
for _, addon := range uiDatas {
|
||||
uiData, err := versionedRegistry.GetAddonUIData(context.Background(), addon.Name, addon.Version)
|
||||
if err != nil {
|
||||
log.Logger.Errorf("fail to get addon from registry %s, addon %s version %s for cache updating, %v", addon.Name, r.Name, err)
|
||||
continue
|
||||
}
|
||||
u.putVersionedUIData2Cache(r.Name, addon.Name, addon.Version, uiData)
|
||||
// we also no version key, if use get addonUIData without version will return this vale as latest data.
|
||||
u.putVersionedUIData2Cache(r.Name, addon.Name, "latest", uiData)
|
||||
}
|
||||
}
|
||||
u.putAddonMeta2Cache(r.Name, registryMeta)
|
||||
uiData, err := r.ListUIData(registryMeta, UIMetaOptions)
|
||||
if err != nil {
|
||||
log.Logger.Errorf("fail to get addons from registry %s for cache updating, %v", r.Name, err)
|
||||
continue
|
||||
}
|
||||
u.putAddonUIData2Cache(r.Name, uiData)
|
||||
}
|
||||
}
|
||||
|
||||
33
pkg/addon/cache_test.go
Normal file
33
pkg/addon/cache_test.go
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
Copyright 2021 The KubeVela Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package addon
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestPutVersionedUIData2cache(t *testing.T) {
|
||||
uiData := UIData{Meta: Meta{Name: "fluxcd", Icon: "test.com/fluxcd.png", Version: "1.0.0"}}
|
||||
u := NewCache(nil)
|
||||
u.putVersionedUIData2Cache("helm-repo", "fluxcd", "1.0.0", &uiData)
|
||||
assert.NotEmpty(t, u.versionedUIData)
|
||||
assert.NotEmpty(t, u.versionedUIData["helm-repo"])
|
||||
assert.NotEmpty(t, u.versionedUIData["helm-repo"]["fluxcd-1.0.0"])
|
||||
assert.Equal(t, u.versionedUIData["helm-repo"]["fluxcd-1.0.0"].Name, "fluxcd")
|
||||
}
|
||||
@@ -17,6 +17,8 @@ limitations under the License.
|
||||
package addon
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/google/go-github/v32/github"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
@@ -35,9 +37,6 @@ var (
|
||||
|
||||
// ErrNotExist means addon not exists
|
||||
ErrNotExist = NewAddonError("addon not exist")
|
||||
|
||||
// ErrVersionMismatch means addon version requirement mismatch
|
||||
ErrVersionMismatch = NewAddonError("addon version requirements mismatch")
|
||||
)
|
||||
|
||||
// WrapErrRateLimit return ErrRateLimit if is the situation, or return error directly
|
||||
@@ -48,3 +47,13 @@ func WrapErrRateLimit(err error) error {
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// VersionUnMatchError means addon system requirement cannot meet requirement
|
||||
type VersionUnMatchError struct {
|
||||
err error
|
||||
addonName string
|
||||
}
|
||||
|
||||
func (v VersionUnMatchError) Error() string {
|
||||
return fmt.Sprintf("addon %s system requirement miss match: %v", v.addonName, v.err)
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user