mirror of
https://github.com/kubevela/kubevela.git
synced 2026-02-28 08:43:57 +00:00
Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9c57c09878 | ||
|
|
cc1ac251ce | ||
|
|
18fb098fce | ||
|
|
5a5721048c | ||
|
|
bab5bb2caf | ||
|
|
cce1859294 | ||
|
|
72bb0798ef | ||
|
|
29aa2b9644 | ||
|
|
307d1db36d | ||
|
|
00ae0c9494 | ||
|
|
f0357fdc8f | ||
|
|
ef8b0ac00f | ||
|
|
aaaf2bddac | ||
|
|
eeb6f08edf | ||
|
|
b9f1cc97a9 | ||
|
|
2117554d53 | ||
|
|
9edd6ebc30 | ||
|
|
ccdfc409a8 | ||
|
|
449b3e0b49 | ||
|
|
8be1fb29b4 | ||
|
|
b42e6cf1e6 | ||
|
|
096afa227b | ||
|
|
57b74c3687 | ||
|
|
9203bbcdb8 | ||
|
|
f3e920ab60 | ||
|
|
6893a2b776 |
2
.github/workflows/chart.yml
vendored
2
.github/workflows/chart.yml
vendored
@@ -28,7 +28,7 @@ jobs:
|
||||
with:
|
||||
version: v3.4.0
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c
|
||||
uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8
|
||||
with:
|
||||
node-version: '14'
|
||||
- name: Generate helm doc
|
||||
|
||||
6
.github/workflows/go.yml
vendored
6
.github/workflows/go.yml
vendored
@@ -104,7 +104,7 @@ jobs:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c
|
||||
uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8
|
||||
with:
|
||||
node-version: '14'
|
||||
|
||||
@@ -176,7 +176,7 @@ jobs:
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@2b82ce82d56a2a04d2637cd93a637ae1b359c0a7 # v2.2.0
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@16c0bc4a6e6ada2cfd8afd41d22d95379cf7c32a # v2.8.0
|
||||
uses: docker/setup-buildx-action@2a1a44ac4aa01993040736bd95bb470da1a38365 # v2.9.0
|
||||
- name: Build Test for vela core
|
||||
uses: docker/build-push-action@2eb1c1961a95fc15694676618e422e8ba1d63825 # v4.1.1
|
||||
with:
|
||||
@@ -196,7 +196,7 @@ jobs:
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@2b82ce82d56a2a04d2637cd93a637ae1b359c0a7 # v2.2.0
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@16c0bc4a6e6ada2cfd8afd41d22d95379cf7c32a # v2.8.0
|
||||
uses: docker/setup-buildx-action@2a1a44ac4aa01993040736bd95bb470da1a38365 # v2.9.0
|
||||
- name: Build Test for CLI
|
||||
uses: docker/build-push-action@2eb1c1961a95fc15694676618e422e8ba1d63825 # v4.1.1
|
||||
with:
|
||||
|
||||
3
.github/workflows/issue-commands.yml
vendored
3
.github/workflows/issue-commands.yml
vendored
@@ -7,6 +7,7 @@ on:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
bot:
|
||||
@@ -22,7 +23,7 @@ jobs:
|
||||
path: ./actions
|
||||
ref: v0.4.2
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c
|
||||
uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8
|
||||
with:
|
||||
node-version: '14'
|
||||
cache: 'npm'
|
||||
|
||||
2
.github/workflows/registry.yml
vendored
2
.github/workflows/registry.yml
vendored
@@ -43,7 +43,7 @@ jobs:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
- uses: docker/setup-qemu-action@2b82ce82d56a2a04d2637cd93a637ae1b359c0a7 # v2.2.0
|
||||
- uses: docker/setup-buildx-action@16c0bc4a6e6ada2cfd8afd41d22d95379cf7c32a # v2.8.0
|
||||
- uses: docker/setup-buildx-action@2a1a44ac4aa01993040736bd95bb470da1a38365 # v2.9.0
|
||||
with:
|
||||
driver-opts: image=moby/buildkit:master
|
||||
|
||||
|
||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -33,7 +33,7 @@ jobs:
|
||||
with:
|
||||
go-version: 1.19
|
||||
cache: true
|
||||
- uses: goreleaser/goreleaser-action@336e29918d653399e599bfca99fadc1d7ffbc9f7 # v4.3.0
|
||||
- uses: goreleaser/goreleaser-action@3fa32b8bb5620a2c1afe798654bbad59f9da4906 # v4.4.0
|
||||
with:
|
||||
distribution: goreleaser
|
||||
version: 1.14.1
|
||||
|
||||
2
.github/workflows/unit-test.yml
vendored
2
.github/workflows/unit-test.yml
vendored
@@ -71,7 +71,7 @@ jobs:
|
||||
kind create cluster
|
||||
|
||||
- name: install Kubebuilder
|
||||
uses: RyanSiu1995/kubebuilder-action@ed0e300b13152c2c2bfb104475665c7bf609332f
|
||||
uses: RyanSiu1995/kubebuilder-action@7170cb0476187070ae04cbb6cee305e809de2693
|
||||
with:
|
||||
version: 3.9.1
|
||||
kubebuilderOnly: false
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
ARG BASE_IMAGE
|
||||
# Build the manager binary
|
||||
FROM --platform=${BUILDPLATFORM:-linux/amd64} golang:1.19-alpine@sha256:2381c1e5f8350a901597d633b2e517775eeac7a6682be39225a93b22cfd0f8bb as builder
|
||||
FROM golang:1.19-alpine3.18 as builder
|
||||
|
||||
WORKDIR /workspace
|
||||
# Copy the Go Modules manifests
|
||||
@@ -34,7 +34,7 @@ RUN GO111MODULE=on CGO_ENABLED=0 GOOS=linux GOARCH=${TARGETARCH} \
|
||||
# You can replace distroless as minimal base image to package the manager binary
|
||||
# Refer to https://github.com/GoogleContainerTools/distroless for more details
|
||||
# Overwrite `BASE_IMAGE` by passing `--build-arg=BASE_IMAGE=gcr.io/distroless/static:nonroot`
|
||||
FROM ${BASE_IMAGE:-alpine@sha256:e2e16842c9b54d985bf1ef9242a313f36b856181f188de21313820e177002501}
|
||||
FROM ${BASE_IMAGE:-alpine:3.18}
|
||||
# This is required by daemon connecting with cri
|
||||
RUN apk add --no-cache ca-certificates bash expat
|
||||
|
||||
|
||||
@@ -32,22 +32,6 @@ type CRDInfo struct {
|
||||
Kind string `json:"kind"`
|
||||
}
|
||||
|
||||
// Chart defines all necessary information to install a whole chart
|
||||
type Chart struct {
|
||||
Repo string `json:"repo"`
|
||||
URL string `json:"url"`
|
||||
Name string `json:"name"`
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
Version string `json:"version"`
|
||||
Values map[string]interface{} `json:"values"`
|
||||
}
|
||||
|
||||
// Installation defines the installation method for this Capability, currently only helm is supported
|
||||
type Installation struct {
|
||||
Helm Chart `json:"helm"`
|
||||
// TODO(wonderflow) add raw yaml file support for install capability
|
||||
}
|
||||
|
||||
// CapType defines the type of capability
|
||||
type CapType string
|
||||
|
||||
@@ -107,7 +91,6 @@ type Capability struct {
|
||||
CueTemplateURI string `json:"templateURI,omitempty"`
|
||||
Parameters []Parameter `json:"parameters,omitempty"`
|
||||
CrdName string `json:"crdName,omitempty"`
|
||||
Center string `json:"center,omitempty"`
|
||||
Status string `json:"status,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Example string `json:"example,omitempty"`
|
||||
@@ -121,8 +104,7 @@ type Capability struct {
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
|
||||
// Plugin Source
|
||||
Source *Source `json:"source,omitempty"`
|
||||
CrdInfo *CRDInfo `json:"crdInfo,omitempty"`
|
||||
Source *Source `json:"source,omitempty"`
|
||||
|
||||
// Terraform
|
||||
TerraformConfiguration string `json:"terraformConfiguration,omitempty"`
|
||||
|
||||
139
charts/vela-core/templates/defwithtemplate/container-ports.yaml
Normal file
139
charts/vela-core/templates/defwithtemplate/container-ports.yaml
Normal file
@@ -0,0 +1,139 @@
|
||||
# Code generated by KubeVela templates. DO NOT EDIT. Please edit the original cue file.
|
||||
# Definition source cue file: vela-templates/definitions/internal/container-ports.cue
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: TraitDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: Expose on the host and bind the external port to host to enable web traffic for your component.
|
||||
name: container-ports
|
||||
namespace: {{ include "systemDefinitionNamespace" . }}
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- deployments.apps
|
||||
- statefulsets.apps
|
||||
- daemonsets.apps
|
||||
- jobs.batch
|
||||
podDisruptive: true
|
||||
schematic:
|
||||
cue:
|
||||
template: |
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
#PatchParams: {
|
||||
// +usage=Specify the name of the target container, if not set, use the component name
|
||||
containerName: *"" | string
|
||||
// +usage=Specify ports you want customer traffic sent to
|
||||
ports: *[] | [...{
|
||||
// +usage=Number of port to expose on the pod's IP address
|
||||
containerPort: int
|
||||
// +usage=Protocol for port. Must be UDP, TCP, or SCTP
|
||||
protocol: *"TCP" | "UDP" | "SCTP"
|
||||
// +usage=Number of port to expose on the host
|
||||
hostPort?: int
|
||||
// +usage=What host IP to bind the external port to.
|
||||
hostIP?: string
|
||||
}]
|
||||
}
|
||||
|
||||
PatchContainer: {
|
||||
_params: #PatchParams
|
||||
name: _params.containerName
|
||||
_baseContainers: context.output.spec.template.spec.containers
|
||||
_matchContainers_: [ for _container_ in _baseContainers if _container_.name == name {_container_}]
|
||||
_baseContainer: *_|_ | {...}
|
||||
if len(_matchContainers_) == 0 {
|
||||
err: "container \(name) not found"
|
||||
}
|
||||
if len(_matchContainers_) > 0 {
|
||||
_baseContainer: _matchContainers_[0]
|
||||
_basePorts: _baseContainer.ports
|
||||
if _basePorts == _|_ {
|
||||
// +patchStrategy=replace
|
||||
ports: [ for port in _params.ports {
|
||||
containerPort: port.containerPort
|
||||
protocol: port.protocol
|
||||
if port.hostPort != _|_ {
|
||||
hostPort: port.hostPort
|
||||
}
|
||||
if port.hostIP != _|_ {
|
||||
hostIP: port.hostIP
|
||||
}
|
||||
}]
|
||||
}
|
||||
if _basePorts != _|_ {
|
||||
_basePortsMap: {for _basePort in _basePorts {(strings.ToLower(_basePort.protocol) + strconv.FormatInt(_basePort.containerPort, 10)): _basePort}}
|
||||
_portsMap: {for port in _params.ports {(strings.ToLower(port.protocol) + strconv.FormatInt(port.containerPort, 10)): port}}
|
||||
// +patchStrategy=replace
|
||||
ports: [ for portVar in _basePorts {
|
||||
containerPort: portVar.containerPort
|
||||
protocol: portVar.protocol
|
||||
_uniqueKey: strings.ToLower(portVar.protocol) + strconv.FormatInt(portVar.containerPort, 10)
|
||||
if _portsMap[_uniqueKey] != _|_ {
|
||||
if _portsMap[_uniqueKey].hostPort != _|_ {
|
||||
hostPort: _portsMap[_uniqueKey].hostPort
|
||||
}
|
||||
if _portsMap[_uniqueKey].hostIP != _|_ {
|
||||
hostIP: _portsMap[_uniqueKey].hostIP
|
||||
}
|
||||
}
|
||||
if _portsMap[_uniqueKey] == _|_ {
|
||||
if portVar.name != _|_ {
|
||||
name: portVar.name
|
||||
}
|
||||
}
|
||||
}] + [ for port in _params.ports if _basePortsMap[strings.ToLower(port.protocol)+strconv.FormatInt(port.containerPort, 10)] == _|_ {
|
||||
if port.containerPort != _|_ {
|
||||
containerPort: port.containerPort
|
||||
}
|
||||
if port.protocol != _|_ {
|
||||
protocol: port.protocol
|
||||
}
|
||||
if port.hostPort != _|_ {
|
||||
hostPort: port.hostPort
|
||||
}
|
||||
if port.hostIP != _|_ {
|
||||
hostIP: port.hostIP
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
patch: spec: template: spec: {
|
||||
if parameter.containers == _|_ {
|
||||
// +patchKey=name
|
||||
containers: [{
|
||||
PatchContainer & {_params: {
|
||||
if parameter.containerName == "" {
|
||||
containerName: context.name
|
||||
}
|
||||
if parameter.containerName != "" {
|
||||
containerName: parameter.containerName
|
||||
}
|
||||
ports: parameter.ports
|
||||
}}
|
||||
}]
|
||||
}
|
||||
if parameter.containers != _|_ {
|
||||
// +patchKey=name
|
||||
containers: [ for c in parameter.containers {
|
||||
if c.containerName == "" {
|
||||
err: "container name must be set for containers"
|
||||
}
|
||||
if c.containerName != "" {
|
||||
PatchContainer & {_params: c}
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
parameter: *#PatchParams | close({
|
||||
// +usage=Specify the container ports for multiple containers
|
||||
containers: [...#PatchParams]
|
||||
})
|
||||
|
||||
errs: [ for c in patch.spec.template.spec.containers if c.err != _|_ {c.err}]
|
||||
|
||||
@@ -81,7 +81,6 @@ func NewCoreOptions() *CoreOptions {
|
||||
DefRevisionLimit: 20,
|
||||
AutoGenWorkloadDefinition: true,
|
||||
ConcurrentReconciles: 4,
|
||||
EnableCompatibility: false,
|
||||
IgnoreAppWithoutControllerRequirement: false,
|
||||
IgnoreDefinitionWithoutControllerRequirement: false,
|
||||
},
|
||||
|
||||
@@ -47,7 +47,7 @@ import (
|
||||
"github.com/oam-dev/kubevela/pkg/auth"
|
||||
"github.com/oam-dev/kubevela/pkg/cache"
|
||||
commonconfig "github.com/oam-dev/kubevela/pkg/controller/common"
|
||||
oamv1alpha2 "github.com/oam-dev/kubevela/pkg/controller/core.oam.dev/v1beta1"
|
||||
oamv1beta1 "github.com/oam-dev/kubevela/pkg/controller/core.oam.dev/v1beta1"
|
||||
"github.com/oam-dev/kubevela/pkg/controller/core.oam.dev/v1beta1/application"
|
||||
"github.com/oam-dev/kubevela/pkg/features"
|
||||
"github.com/oam-dev/kubevela/pkg/monitor/watcher"
|
||||
@@ -227,7 +227,7 @@ func prepareRun(ctx context.Context, mgr manager.Manager, s *options.CoreOptions
|
||||
}
|
||||
}
|
||||
|
||||
if err := oamv1alpha2.Setup(mgr, *s.ControllerArgs); err != nil {
|
||||
if err := oamv1beta1.Setup(mgr, *s.ControllerArgs); err != nil {
|
||||
klog.ErrorS(err, "Unable to setup the oam controller")
|
||||
return err
|
||||
}
|
||||
|
||||
39
go.mod
39
go.mod
@@ -24,12 +24,12 @@ require (
|
||||
github.com/form3tech-oss/jwt-go v3.2.5+incompatible
|
||||
github.com/gdamore/tcell/v2 v2.6.0
|
||||
github.com/getkin/kin-openapi v0.118.0
|
||||
github.com/go-git/go-git/v5 v5.7.0
|
||||
github.com/go-git/go-git/v5 v5.8.1
|
||||
github.com/go-logr/logr v1.2.4
|
||||
github.com/go-resty/resty/v2 v2.7.0
|
||||
github.com/golang/mock v1.6.0
|
||||
github.com/google/go-cmp v0.5.9
|
||||
github.com/google/go-containerregistry v0.15.2
|
||||
github.com/google/go-containerregistry v0.16.1
|
||||
github.com/google/go-github/v32 v32.1.0
|
||||
github.com/gosuri/uitable v0.0.4
|
||||
github.com/hashicorp/go-version v1.6.0
|
||||
@@ -37,10 +37,10 @@ require (
|
||||
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174
|
||||
github.com/imdario/mergo v0.3.16
|
||||
github.com/kubevela/pkg v1.8.1-0.20230522085329-7d5e1241a86d
|
||||
github.com/kubevela/workflow v0.5.1-0.20230412142834-be9e5a10baf0
|
||||
github.com/kubevela/workflow v0.6.0
|
||||
github.com/kyokomi/emoji v2.2.4+incompatible
|
||||
github.com/magiconair/properties v1.8.7
|
||||
github.com/mattn/go-runewidth v0.0.14
|
||||
github.com/mattn/go-runewidth v0.0.15
|
||||
github.com/mitchellh/hashstructure/v2 v2.0.2
|
||||
github.com/nacos-group/nacos-sdk-go/v2 v2.2.2
|
||||
github.com/oam-dev/cluster-gateway v1.9.0-alpha.2
|
||||
@@ -54,7 +54,7 @@ require (
|
||||
github.com/openkruise/rollouts v0.3.0
|
||||
github.com/pelletier/go-toml v1.9.5
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/prometheus/client_golang v1.15.1
|
||||
github.com/prometheus/client_golang v1.16.0
|
||||
github.com/prometheus/client_model v0.4.0
|
||||
github.com/rivo/tview v0.0.0-20221128165837-db36428c92d9
|
||||
github.com/rogpeppe/go-internal v1.10.0
|
||||
@@ -67,12 +67,12 @@ require (
|
||||
github.com/xanzy/go-gitlab v0.86.0
|
||||
github.com/xlab/treeprint v1.2.0
|
||||
go.uber.org/multierr v1.11.0
|
||||
golang.org/x/crypto v0.10.0
|
||||
golang.org/x/oauth2 v0.9.0
|
||||
golang.org/x/crypto v0.11.0
|
||||
golang.org/x/oauth2 v0.10.0
|
||||
golang.org/x/sync v0.3.0
|
||||
golang.org/x/term v0.9.0
|
||||
golang.org/x/text v0.10.0
|
||||
golang.org/x/tools v0.10.0
|
||||
golang.org/x/term v0.10.0
|
||||
golang.org/x/text v0.12.0
|
||||
golang.org/x/tools v0.11.0
|
||||
gomodules.xyz/jsonpatch/v2 v2.3.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
helm.sh/helm/v3 v3.11.2
|
||||
@@ -98,6 +98,7 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
dario.cat/mergo v1.0.0 // indirect
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
|
||||
github.com/BurntSushi/toml v1.2.1 // indirect
|
||||
@@ -109,7 +110,7 @@ require (
|
||||
github.com/Masterminds/squirrel v1.5.3 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.1 // indirect
|
||||
github.com/NYTimes/gziphandler v1.1.1 // indirect
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230518184743-7afd39499903 // indirect
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95 // indirect
|
||||
github.com/acomagu/bufpipe v1.0.4 // indirect
|
||||
github.com/agext/levenshtein v1.2.3 // indirect
|
||||
github.com/alessio/shellescape v1.4.1 // indirect
|
||||
@@ -131,9 +132,9 @@ require (
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
||||
github.com/creack/pty v1.1.18 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.2.3 // indirect
|
||||
github.com/docker/cli v23.0.5+incompatible // indirect
|
||||
github.com/docker/cli v24.0.0+incompatible // indirect
|
||||
github.com/docker/distribution v2.8.2+incompatible // indirect
|
||||
github.com/docker/docker v23.0.5+incompatible // indirect
|
||||
github.com/docker/docker v24.0.0+incompatible // indirect
|
||||
github.com/docker/docker-credential-helpers v0.7.0 // indirect
|
||||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
github.com/docker/go-metrics v0.0.1 // indirect
|
||||
@@ -233,7 +234,7 @@ require (
|
||||
github.com/pjbgf/sha1cd v0.3.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/common v0.42.0 // indirect
|
||||
github.com/prometheus/procfs v0.9.0 // indirect
|
||||
github.com/prometheus/procfs v0.10.1 // indirect
|
||||
github.com/protocolbuffers/txtpbfmt v0.0.0-20220428173112-74888fd59c2b // indirect
|
||||
github.com/rivo/uniseg v0.4.3 // indirect
|
||||
github.com/robfig/cron/v3 v3.0.1 // indirect
|
||||
@@ -241,7 +242,7 @@ require (
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/sergi/go-diff v1.1.0 // indirect
|
||||
github.com/shopspring/decimal v1.3.1 // indirect
|
||||
github.com/skeema/knownhosts v1.1.1 // indirect
|
||||
github.com/skeema/knownhosts v1.2.0 // indirect
|
||||
github.com/spf13/cast v1.5.0 // indirect
|
||||
github.com/stoewer/go-strcase v1.2.0 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
@@ -268,14 +269,14 @@ require (
|
||||
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect
|
||||
go.uber.org/atomic v1.9.0 // indirect
|
||||
go.uber.org/zap v1.24.0 // indirect
|
||||
golang.org/x/mod v0.11.0 // indirect
|
||||
golang.org/x/net v0.11.0 // indirect
|
||||
golang.org/x/sys v0.9.0 // indirect
|
||||
golang.org/x/mod v0.12.0 // indirect
|
||||
golang.org/x/net v0.12.0 // indirect
|
||||
golang.org/x/sys v0.10.0 // indirect
|
||||
golang.org/x/time v0.3.0 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect
|
||||
google.golang.org/grpc v1.53.0 // indirect
|
||||
google.golang.org/protobuf v1.30.0 // indirect
|
||||
google.golang.org/protobuf v1.31.0 // indirect
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
|
||||
76
go.sum
76
go.sum
@@ -1,12 +1,14 @@
|
||||
cloud.google.com/go v0.100.2 h1:t9Iw5QH5v4XtlEQaCtUY7x6sCABps8sW0acw7e2WQ6Y=
|
||||
cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A=
|
||||
cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow=
|
||||
cloud.google.com/go/compute v1.19.1 h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY=
|
||||
cloud.google.com/go/compute v1.20.1 h1:6aKEtlUiwEpJzM001l0yFkpXmUVXaN8W+fbkb2AZNbg=
|
||||
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
|
||||
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||
cuelang.org/go v0.5.0 h1:D6N0UgTGJCOxFKU8RU+qYvavKNsVc/+ZobmifStVJzU=
|
||||
cuelang.org/go v0.5.0/go.mod h1:okjJBHFQFer+a41sAe2SaGm1glWS8oEb6CmJvn5Zdws=
|
||||
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
|
||||
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 h1:EKPd1INOIyr5hWOWhvpmQpY6tKjeG0hT1s3AMC/9fic=
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1/go.mod h1:VzwV+t+dZ9j/H867F1M2ziD+yLHtB46oM35FxxMJ4d0=
|
||||
@@ -57,8 +59,8 @@ github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMo
|
||||
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw=
|
||||
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230518184743-7afd39499903 h1:ZK3C5DtzV2nVAQTx5S5jQvMeDqWtD1By5mOoyY/xJek=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230518184743-7afd39499903/go.mod h1:8TI4H3IbrackdNgv+92dI+rhpCaLqM0IfpgCgenFvRE=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95 h1:KLq8BE0KwCL+mmXnjLWEAOYO+2l2AE4YMmqG1ZpZHBs=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
|
||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs=
|
||||
@@ -124,7 +126,7 @@ github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx2
|
||||
github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd h1:rFt+Y/IK1aEZkEHchZRSq9OQbsSzIT/OrI8YFFmRIng=
|
||||
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b h1:otBG+dV+YK+Soembjv71DPz3uX/V/6MMlSyD9JBQ6kQ=
|
||||
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 h1:nvj0OLI3YqYXer/kZD8Ri1aaunCxIEsOst1BVJswV0o=
|
||||
github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
||||
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
||||
github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
|
||||
github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
|
||||
github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
|
||||
@@ -145,7 +147,6 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I=
|
||||
github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs=
|
||||
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
@@ -304,8 +305,8 @@ github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmS
|
||||
github.com/go-git/go-billy/v5 v5.4.1 h1:Uwp5tDRkPr+l/TnbHOQzp+tmJfLceOlbVucgpTz8ix4=
|
||||
github.com/go-git/go-billy/v5 v5.4.1/go.mod h1:vjbugF6Fz7JIflbVpl1hJsGjSHNltrSw45YK/ukIvQg=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20230305113008-0c11038e723f h1:Pz0DHeFij3XFhoBRGUDPzSJ+w2UcK5/0JvF8DRI58r8=
|
||||
github.com/go-git/go-git/v5 v5.7.0 h1:t9AudWVLmqzlo+4bqdf7GY+46SUuRsx59SboFxkq2aE=
|
||||
github.com/go-git/go-git/v5 v5.7.0/go.mod h1:coJHKEOk5kUClpsNlXrUvPrDxY3w3gjHvhcZd8Fodw8=
|
||||
github.com/go-git/go-git/v5 v5.8.1 h1:Zo79E4p7TRk0xoRgMq0RShiTHGKcKI4+DI6BfJc/Q+A=
|
||||
github.com/go-git/go-git/v5 v5.8.1/go.mod h1:FHFuoD6yGz5OSKEBK+aWN9Oah0q54Jxl0abmj6GnqAo=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gorp/gorp/v3 v3.0.5/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw=
|
||||
github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs=
|
||||
@@ -429,8 +430,8 @@ github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8
|
||||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-containerregistry v0.15.2 h1:MMkSh+tjSdnmJZO7ljvEqV1DjfekB6VUEAZgy3a+TQE=
|
||||
github.com/google/go-containerregistry v0.15.2/go.mod h1:wWK+LnOv4jXMM23IT/F1wdYftGWGr47Is8CG+pmHK1Q=
|
||||
github.com/google/go-containerregistry v0.16.1 h1:rUEt426sR6nyrL3gt+18ibRcvYpKYdpsa5ZW7MA08dQ=
|
||||
github.com/google/go-containerregistry v0.16.1/go.mod h1:u0qB2l7mvtWVR5kNcbFIhFY1hLbf8eeGapA+vbFDCtQ=
|
||||
github.com/google/go-github/v32 v32.1.0 h1:GWkQOdXqviCPx7Q7Fj+KyPoGm4SwHRh8rheoPhd27II=
|
||||
github.com/google/go-github/v32 v32.1.0/go.mod h1:rIEpZD9CTDQwDK9GDrtMTycQNA4JU3qBsCizh3q2WCI=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
@@ -599,8 +600,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kubevela/pkg v1.8.1-0.20230522085329-7d5e1241a86d h1:QMmTg33lUZEfTz94eYJKa6Nb7GDcEOmuXsXRt/dA5vk=
|
||||
github.com/kubevela/pkg v1.8.1-0.20230522085329-7d5e1241a86d/go.mod h1:3ZWrl2+zb5ROdC2NJPPrL/4sun4M10wYfRP/9gF9WJE=
|
||||
github.com/kubevela/workflow v0.5.1-0.20230412142834-be9e5a10baf0 h1:/ZPmjKpd/+fpCjJfNfUnE7jdESuCcZeP+fyTUAU9an0=
|
||||
github.com/kubevela/workflow v0.5.1-0.20230412142834-be9e5a10baf0/go.mod h1:0GhIWFIPP+Zt31m4Aslx9mihoyNz3HrOvCV69ljMIBo=
|
||||
github.com/kubevela/workflow v0.6.0 h1:fYXviOYD5zqHs3J61tNbM4HZ85EcZlPm7Fyz8Q5o9Fk=
|
||||
github.com/kubevela/workflow v0.6.0/go.mod h1:sjLcYqKHKeCQ+w77gijoNILwIShJKnCU+e3q7ETtZGI=
|
||||
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
@@ -652,8 +653,9 @@ github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPn
|
||||
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-oci8 v0.1.1/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
|
||||
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI=
|
||||
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
@@ -824,8 +826,8 @@ github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqr
|
||||
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
|
||||
github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
|
||||
github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y=
|
||||
github.com/prometheus/client_golang v1.15.1 h1:8tXpTmJbyH5lydzFPoxSIJ0J46jdh3tylbvM1xCv0LI=
|
||||
github.com/prometheus/client_golang v1.15.1/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk=
|
||||
github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8=
|
||||
github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
@@ -852,8 +854,8 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O
|
||||
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
|
||||
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
|
||||
github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI=
|
||||
github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY=
|
||||
github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg=
|
||||
github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/protocolbuffers/txtpbfmt v0.0.0-20220428173112-74888fd59c2b h1:zd/2RNzIRkoGGMjE+YIsZ85CnDIz672JK2F3Zl4vux4=
|
||||
github.com/protocolbuffers/txtpbfmt v0.0.0-20220428173112-74888fd59c2b/go.mod h1:KjY0wibdYKc4DYkerHSbguaf3JeIPGhNJBp2BNiFH78=
|
||||
@@ -893,8 +895,8 @@ github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic
|
||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/skeema/knownhosts v1.1.1 h1:MTk78x9FPgDFVFkDLTrsnnfCJl7g1C/nnKvePgrIngE=
|
||||
github.com/skeema/knownhosts v1.1.1/go.mod h1:g4fPeYpque7P0xefxtGzV81ihjC8sX2IqpAoNkjxbMo=
|
||||
github.com/skeema/knownhosts v1.2.0 h1:h9r9cf0+u7wSE+M183ZtMGgOJKiL96brpaz5ekfJCpM=
|
||||
github.com/skeema/knownhosts v1.2.0/go.mod h1:g4fPeYpque7P0xefxtGzV81ihjC8sX2IqpAoNkjxbMo=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
@@ -1116,10 +1118,11 @@ golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
||||
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM=
|
||||
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
|
||||
golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA=
|
||||
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
||||
@@ -1142,8 +1145,8 @@ golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
|
||||
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
|
||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -1195,8 +1198,8 @@ golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU=
|
||||
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
|
||||
golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50=
|
||||
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@@ -1208,8 +1211,8 @@ golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
|
||||
golang.org/x/oauth2 v0.9.0 h1:BPpt2kU7oMRq3kCHAA1tbSEshXRw1LpG2ztgDwrzuAs=
|
||||
golang.org/x/oauth2 v0.9.0/go.mod h1:qYgFZaFiu6Wg24azG8bdV52QJXJGbZzIIsRCdVKzbLw=
|
||||
golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8=
|
||||
golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -1276,7 +1279,6 @@ golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211029165221-6e7872819dc8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@@ -1298,8 +1300,8 @@ golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
|
||||
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
|
||||
golang.org/x/sys v0.10.0/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=
|
||||
@@ -1311,8 +1313,8 @@ golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
|
||||
golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||
golang.org/x/term v0.9.0 h1:GRRCnKYhdQrD8kfRAdQ6Zcw1P0OcELxGLKJvtjVMZ28=
|
||||
golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo=
|
||||
golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c=
|
||||
golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
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=
|
||||
@@ -1324,8 +1326,8 @@ golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58=
|
||||
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
|
||||
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
@@ -1364,8 +1366,8 @@ golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.10.0 h1:tvDr/iQoUqNdohiYm0LmmKcBk+q86lb9EprIUFhHHGg=
|
||||
golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM=
|
||||
golang.org/x/tools v0.11.0 h1:EMCa6U9S2LtZXLAMoWiR/R8dAQFRqbAitmbJ2UKhoi8=
|
||||
golang.org/x/tools v0.11.0/go.mod h1:anzJrxPjNtfgiYQYirP2CPGzGLxrH2u2QBhn6Bf3qY8=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -1454,8 +1456,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
||||
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
|
||||
|
||||
@@ -42,7 +42,7 @@ var ComponentDefDirs = []string{"./vela-templates/definitions/internal/component
|
||||
|
||||
// CustomComponentHeaderEN .
|
||||
var CustomComponentHeaderEN = `---
|
||||
title: Built-in Component Type
|
||||
title: Built-in ParsedComponents Type
|
||||
---
|
||||
|
||||
This documentation will walk through all the built-in component types sorted alphabetically.
|
||||
|
||||
@@ -161,7 +161,6 @@ func (i versionedRegistry) loadAddon(ctx context.Context, name, version string)
|
||||
if addonVersion == nil {
|
||||
return nil, errors.Errorf("specified version %s not exist", utils.Sanitize(version))
|
||||
}
|
||||
klog.V(5).Infof("Addon '%s' with version '%s' found from registry '%s'", addonVersion.Name, addonVersion.Version, i.name)
|
||||
for _, chartURL := range addonVersion.URLs {
|
||||
if !utils.IsValidURL(chartURL) {
|
||||
chartURL, err = utils.JoinURL(i.url, chartURL)
|
||||
@@ -186,7 +185,9 @@ func (i versionedRegistry) loadAddon(ctx context.Context, name, version string)
|
||||
addonPkg.AvailableVersions = availableVersions
|
||||
addonPkg.RegistryName = i.name
|
||||
addonPkg.Meta.SystemRequirements = LoadSystemRequirements(addonVersion.Annotations)
|
||||
klog.V(5).Infof("Addon '%s' with version '%s' loaded successfully from registry '%s'", addonVersion.Name, addonVersion.Version, i.name)
|
||||
if addonPkg.Name != "" {
|
||||
klog.V(5).Infof("Addon '%s' with version '%s' loaded successfully from registry '%s'", addonVersion.Name, addonVersion.Version, i.name)
|
||||
}
|
||||
return addonPkg, nil
|
||||
}
|
||||
return nil, ErrFetch
|
||||
|
||||
@@ -74,8 +74,10 @@ const (
|
||||
GitCredentialsSecretReferenceKey = "gitCredentialsSecretReference"
|
||||
)
|
||||
|
||||
// Workload is component
|
||||
type Workload struct {
|
||||
// Component is an internal struct for component in application
|
||||
// User-defined policies are parsed as a Component without any Traits because their purpose is dispatching some resources
|
||||
// Internal policies are NOT parsed as a Component
|
||||
type Component struct {
|
||||
Name string
|
||||
Type string
|
||||
CapabilityCategory types.CapabilityCategory
|
||||
@@ -89,39 +91,39 @@ type Workload struct {
|
||||
}
|
||||
|
||||
// EvalContext eval workload template and set the result to context
|
||||
func (wl *Workload) EvalContext(ctx process.Context) error {
|
||||
return wl.engine.Complete(ctx, wl.FullTemplate.TemplateStr, wl.Params)
|
||||
func (comp *Component) EvalContext(ctx process.Context) error {
|
||||
return comp.engine.Complete(ctx, comp.FullTemplate.TemplateStr, comp.Params)
|
||||
}
|
||||
|
||||
// GetTemplateContext get workload template context, it will be used to eval status and health
|
||||
func (wl *Workload) GetTemplateContext(ctx process.Context, client client.Client, accessor util.NamespaceAccessor) (map[string]interface{}, error) {
|
||||
func (comp *Component) GetTemplateContext(ctx process.Context, client client.Client, accessor util.NamespaceAccessor) (map[string]interface{}, error) {
|
||||
// if the standard workload is managed by trait, just return empty context
|
||||
if wl.SkipApplyWorkload {
|
||||
if comp.SkipApplyWorkload {
|
||||
return nil, nil
|
||||
}
|
||||
templateContext, err := wl.engine.GetTemplateContext(ctx, client, accessor)
|
||||
templateContext, err := comp.engine.GetTemplateContext(ctx, client, accessor)
|
||||
if templateContext != nil {
|
||||
templateContext[velaprocess.ParameterFieldName] = wl.Params
|
||||
templateContext[velaprocess.ParameterFieldName] = comp.Params
|
||||
}
|
||||
return templateContext, err
|
||||
}
|
||||
|
||||
// EvalStatus eval workload status
|
||||
func (wl *Workload) EvalStatus(templateContext map[string]interface{}) (string, error) {
|
||||
func (comp *Component) EvalStatus(templateContext map[string]interface{}) (string, error) {
|
||||
// if the standard workload is managed by trait always return empty message
|
||||
if wl.SkipApplyWorkload {
|
||||
if comp.SkipApplyWorkload {
|
||||
return "", nil
|
||||
}
|
||||
return wl.engine.Status(templateContext, wl.FullTemplate.CustomStatus, wl.Params)
|
||||
return comp.engine.Status(templateContext, comp.FullTemplate.CustomStatus, comp.Params)
|
||||
}
|
||||
|
||||
// EvalHealth eval workload health check
|
||||
func (wl *Workload) EvalHealth(templateContext map[string]interface{}) (bool, error) {
|
||||
func (comp *Component) EvalHealth(templateContext map[string]interface{}) (bool, error) {
|
||||
// if the health of template is not set or standard workload is managed by trait always return true
|
||||
if wl.SkipApplyWorkload {
|
||||
if comp.SkipApplyWorkload {
|
||||
return true, nil
|
||||
}
|
||||
return wl.engine.HealthCheck(templateContext, wl.FullTemplate.Health, wl.Params)
|
||||
return comp.engine.HealthCheck(templateContext, comp.FullTemplate.Health, comp.Params)
|
||||
}
|
||||
|
||||
// Trait is ComponentTrait
|
||||
@@ -168,9 +170,10 @@ func (trait *Trait) EvalHealth(templateContext map[string]interface{}) (bool, er
|
||||
|
||||
// Appfile describes application
|
||||
type Appfile struct {
|
||||
Name string
|
||||
Namespace string
|
||||
Workloads []*Workload
|
||||
Name string
|
||||
Namespace string
|
||||
ParsedComponents []*Component
|
||||
ParsedPolicies []*Component
|
||||
|
||||
AppRevision *v1beta1.ApplicationRevision
|
||||
AppRevisionName string
|
||||
@@ -183,19 +186,17 @@ type Appfile struct {
|
||||
RelatedComponentDefinitions map[string]*v1beta1.ComponentDefinition
|
||||
RelatedWorkflowStepDefinitions map[string]*v1beta1.WorkflowStepDefinition
|
||||
|
||||
Policies []v1beta1.AppPolicy
|
||||
PolicyWorkloads []*Workload
|
||||
Components []common.ApplicationComponent
|
||||
Artifacts []*types.ComponentManifest
|
||||
WorkflowSteps []workflowv1alpha1.WorkflowStep
|
||||
WorkflowMode *workflowv1alpha1.WorkflowExecuteMode
|
||||
Policies []v1beta1.AppPolicy
|
||||
Components []common.ApplicationComponent
|
||||
Artifacts []*types.ComponentManifest
|
||||
WorkflowSteps []workflowv1alpha1.WorkflowStep
|
||||
WorkflowMode *workflowv1alpha1.WorkflowExecuteMode
|
||||
|
||||
ExternalPolicies map[string]*v1alpha1.Policy
|
||||
ExternalWorkflow *workflowv1alpha1.Workflow
|
||||
ReferredObjects []*unstructured.Unstructured
|
||||
|
||||
parser *Parser
|
||||
app *v1beta1.Application
|
||||
app *v1beta1.Application
|
||||
|
||||
Debug bool
|
||||
}
|
||||
@@ -204,7 +205,7 @@ type Appfile struct {
|
||||
// internal policies like apply-once, topology, will not render manifests
|
||||
func (af *Appfile) GeneratePolicyManifests(ctx context.Context) ([]*unstructured.Unstructured, error) {
|
||||
var manifests []*unstructured.Unstructured
|
||||
for _, policy := range af.PolicyWorkloads {
|
||||
for _, policy := range af.ParsedPolicies {
|
||||
un, err := af.generatePolicyUnstructured(policy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -214,7 +215,7 @@ func (af *Appfile) GeneratePolicyManifests(ctx context.Context) ([]*unstructured
|
||||
return manifests, nil
|
||||
}
|
||||
|
||||
func (af *Appfile) generatePolicyUnstructured(workload *Workload) ([]*unstructured.Unstructured, error) {
|
||||
func (af *Appfile) generatePolicyUnstructured(workload *Component) ([]*unstructured.Unstructured, error) {
|
||||
ctxData := GenerateContextDataFromAppFile(af, workload.Name)
|
||||
uns, err := generatePolicyUnstructuredFromCUEModule(workload, af.Artifacts, ctxData)
|
||||
if err != nil {
|
||||
@@ -231,16 +232,16 @@ func (af *Appfile) generatePolicyUnstructured(workload *Workload) ([]*unstructur
|
||||
return uns, nil
|
||||
}
|
||||
|
||||
func generatePolicyUnstructuredFromCUEModule(wl *Workload, artifacts []*types.ComponentManifest, ctxData velaprocess.ContextData) ([]*unstructured.Unstructured, error) {
|
||||
func generatePolicyUnstructuredFromCUEModule(comp *Component, artifacts []*types.ComponentManifest, ctxData velaprocess.ContextData) ([]*unstructured.Unstructured, error) {
|
||||
pCtx := velaprocess.NewContext(ctxData)
|
||||
pCtx.PushData(velaprocess.ContextDataArtifacts, prepareArtifactsData(artifacts))
|
||||
if err := wl.EvalContext(pCtx); err != nil {
|
||||
if err := comp.EvalContext(pCtx); err != nil {
|
||||
return nil, errors.Wrapf(err, "evaluate base template app=%s in namespace=%s", ctxData.AppName, ctxData.Namespace)
|
||||
}
|
||||
base, auxs := pCtx.Output()
|
||||
workload, err := base.Unstructured()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "evaluate base template policy=%s app=%s", wl.Name, ctxData.AppName)
|
||||
return nil, errors.Wrapf(err, "evaluate base template policy=%s app=%s", comp.Name, ctxData.AppName)
|
||||
}
|
||||
commonLabels := definition.GetCommonLabels(definition.GetBaseContextLabels(pCtx))
|
||||
util.AddLabels(workload, commonLabels)
|
||||
@@ -249,7 +250,7 @@ func generatePolicyUnstructuredFromCUEModule(wl *Workload, artifacts []*types.Co
|
||||
for _, assist := range auxs {
|
||||
tr, err := assist.Ins.Unstructured()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "evaluate auxiliary=%s template for policy=%s app=%s", assist.Name, wl.Name, ctxData.AppName)
|
||||
return nil, errors.Wrapf(err, "evaluate auxiliary=%s template for policy=%s app=%s", assist.Name, comp.Name, ctxData.AppName)
|
||||
}
|
||||
util.AddLabels(tr, commonLabels)
|
||||
res = append(res, tr)
|
||||
@@ -283,10 +284,10 @@ func prepareArtifactsData(comps []*types.ComponentManifest) map[string]interface
|
||||
|
||||
// GenerateComponentManifests converts an appFile to a slice of ComponentManifest
|
||||
func (af *Appfile) GenerateComponentManifests() ([]*types.ComponentManifest, error) {
|
||||
compManifests := make([]*types.ComponentManifest, len(af.Workloads))
|
||||
af.Artifacts = make([]*types.ComponentManifest, len(af.Workloads))
|
||||
for i, wl := range af.Workloads {
|
||||
cm, err := af.GenerateComponentManifest(wl, nil)
|
||||
compManifests := make([]*types.ComponentManifest, len(af.ParsedComponents))
|
||||
af.Artifacts = make([]*types.ComponentManifest, len(af.ParsedComponents))
|
||||
for i, comp := range af.ParsedComponents {
|
||||
cm, err := af.GenerateComponentManifest(comp, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -301,21 +302,21 @@ func (af *Appfile) GenerateComponentManifests() ([]*types.ComponentManifest, err
|
||||
}
|
||||
|
||||
// GenerateComponentManifest generate only one ComponentManifest
|
||||
func (af *Appfile) GenerateComponentManifest(wl *Workload, mutate func(*velaprocess.ContextData)) (*types.ComponentManifest, error) {
|
||||
func (af *Appfile) GenerateComponentManifest(comp *Component, mutate func(*velaprocess.ContextData)) (*types.ComponentManifest, error) {
|
||||
if af.Namespace == "" {
|
||||
af.Namespace = corev1.NamespaceDefault
|
||||
}
|
||||
ctxData := GenerateContextDataFromAppFile(af, wl.Name)
|
||||
ctxData := GenerateContextDataFromAppFile(af, comp.Name)
|
||||
if mutate != nil {
|
||||
mutate(&ctxData)
|
||||
}
|
||||
// generate context here to avoid nil pointer panic
|
||||
wl.Ctx = NewBasicContext(ctxData, wl.Params)
|
||||
switch wl.CapabilityCategory {
|
||||
comp.Ctx = NewBasicContext(ctxData, comp.Params)
|
||||
switch comp.CapabilityCategory {
|
||||
case types.TerraformCategory:
|
||||
return generateComponentFromTerraformModule(wl, af.Name, af.Namespace)
|
||||
return generateComponentFromTerraformModule(comp, af.Name, af.Namespace)
|
||||
default:
|
||||
return generateComponentFromCUEModule(wl, ctxData)
|
||||
return generateComponentFromCUEModule(comp, ctxData)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -393,15 +394,15 @@ func (af *Appfile) setNamespace(obj *unstructured.Unstructured) {
|
||||
}
|
||||
}
|
||||
|
||||
func (af *Appfile) assembleWorkload(wl *unstructured.Unstructured, compName string, labels map[string]string) {
|
||||
func (af *Appfile) assembleWorkload(comp *unstructured.Unstructured, compName string, labels map[string]string) {
|
||||
// use component name as workload name if workload name is not specified
|
||||
// don't override the name set in render phase if exist
|
||||
if len(wl.GetName()) == 0 {
|
||||
wl.SetName(compName)
|
||||
if len(comp.GetName()) == 0 {
|
||||
comp.SetName(compName)
|
||||
}
|
||||
af.setNamespace(wl)
|
||||
af.setWorkloadLabels(wl, labels)
|
||||
af.filterAndSetAnnotations(wl)
|
||||
af.setNamespace(comp)
|
||||
af.setWorkloadLabels(comp, labels)
|
||||
af.filterAndSetAnnotations(comp)
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -416,10 +417,10 @@ func (af *Appfile) assembleWorkload(wl *unstructured.Unstructured, compName stri
|
||||
|
||||
// Component Revision name was not added here (app.oam.dev/revision: mycomp-v2)
|
||||
*/
|
||||
func (af *Appfile) setWorkloadLabels(wl *unstructured.Unstructured, commonLabels map[string]string) {
|
||||
func (af *Appfile) setWorkloadLabels(comp *unstructured.Unstructured, commonLabels map[string]string) {
|
||||
// add more workload-specific labels here
|
||||
util.AddLabels(wl, map[string]string{oam.LabelOAMResourceType: oam.ResourceTypeWorkload})
|
||||
util.AddLabels(wl, commonLabels)
|
||||
util.AddLabels(comp, map[string]string{oam.LabelOAMResourceType: oam.ResourceTypeWorkload})
|
||||
util.AddLabels(comp, commonLabels)
|
||||
}
|
||||
|
||||
func (af *Appfile) assembleTrait(trait *unstructured.Unstructured, compName string, labels map[string]string) {
|
||||
@@ -491,14 +492,14 @@ func IsNotFoundInAppFile(err error) bool {
|
||||
}
|
||||
|
||||
// PrepareProcessContext prepares a DSL process Context
|
||||
func PrepareProcessContext(wl *Workload, ctxData velaprocess.ContextData) (process.Context, error) {
|
||||
if wl.Ctx == nil {
|
||||
wl.Ctx = NewBasicContext(ctxData, wl.Params)
|
||||
func PrepareProcessContext(comp *Component, ctxData velaprocess.ContextData) (process.Context, error) {
|
||||
if comp.Ctx == nil {
|
||||
comp.Ctx = NewBasicContext(ctxData, comp.Params)
|
||||
}
|
||||
if err := wl.EvalContext(wl.Ctx); err != nil {
|
||||
if err := comp.EvalContext(comp.Ctx); err != nil {
|
||||
return nil, errors.Wrapf(err, "evaluate base template app=%s in namespace=%s", ctxData.AppName, ctxData.Namespace)
|
||||
}
|
||||
return wl.Ctx, nil
|
||||
return comp.Ctx, nil
|
||||
}
|
||||
|
||||
// NewBasicContext prepares a basic DSL process Context
|
||||
@@ -510,27 +511,27 @@ func NewBasicContext(contextData velaprocess.ContextData, params map[string]inte
|
||||
return pCtx
|
||||
}
|
||||
|
||||
func generateComponentFromCUEModule(wl *Workload, ctxData velaprocess.ContextData) (*types.ComponentManifest, error) {
|
||||
pCtx, err := PrepareProcessContext(wl, ctxData)
|
||||
func generateComponentFromCUEModule(comp *Component, ctxData velaprocess.ContextData) (*types.ComponentManifest, error) {
|
||||
pCtx, err := PrepareProcessContext(comp, ctxData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return baseGenerateComponent(pCtx, wl, ctxData.AppName, ctxData.Namespace)
|
||||
return baseGenerateComponent(pCtx, comp, ctxData.AppName, ctxData.Namespace)
|
||||
}
|
||||
|
||||
func generateComponentFromTerraformModule(wl *Workload, appName, ns string) (*types.ComponentManifest, error) {
|
||||
return baseGenerateComponent(wl.Ctx, wl, appName, ns)
|
||||
func generateComponentFromTerraformModule(comp *Component, appName, ns string) (*types.ComponentManifest, error) {
|
||||
return baseGenerateComponent(comp.Ctx, comp, appName, ns)
|
||||
}
|
||||
|
||||
func baseGenerateComponent(pCtx process.Context, wl *Workload, appName, ns string) (*types.ComponentManifest, error) {
|
||||
func baseGenerateComponent(pCtx process.Context, comp *Component, appName, ns string) (*types.ComponentManifest, error) {
|
||||
var err error
|
||||
pCtx.PushData(velaprocess.ContextComponentType, wl.Type)
|
||||
for _, tr := range wl.Traits {
|
||||
pCtx.PushData(velaprocess.ContextComponentType, comp.Type)
|
||||
for _, tr := range comp.Traits {
|
||||
if err := tr.EvalContext(pCtx); err != nil {
|
||||
return nil, errors.Wrapf(err, "evaluate template trait=%s app=%s", tr.Name, wl.Name)
|
||||
return nil, errors.Wrapf(err, "evaluate template trait=%s app=%s", tr.Name, comp.Name)
|
||||
}
|
||||
}
|
||||
if patcher := wl.Patch; patcher != nil {
|
||||
if patcher := comp.Patch; patcher != nil {
|
||||
workload, auxiliaries := pCtx.Output()
|
||||
if p, err := patcher.LookupValue("workload"); err == nil {
|
||||
if err := workload.Unify(p.CueValue()); err != nil {
|
||||
@@ -545,43 +546,43 @@ func baseGenerateComponent(pCtx process.Context, wl *Workload, appName, ns strin
|
||||
}
|
||||
}
|
||||
}
|
||||
compManifest, err := evalWorkloadWithContext(pCtx, wl, ns, appName)
|
||||
compManifest, err := evalWorkloadWithContext(pCtx, comp, ns, appName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
compManifest.Name = wl.Name
|
||||
compManifest.Name = comp.Name
|
||||
compManifest.Namespace = ns
|
||||
return compManifest, nil
|
||||
}
|
||||
|
||||
// makeWorkloadWithContext evaluate the workload's template to unstructured resource.
|
||||
func makeWorkloadWithContext(pCtx process.Context, wl *Workload, ns, appName string) (*unstructured.Unstructured, error) {
|
||||
func makeWorkloadWithContext(pCtx process.Context, comp *Component, ns, appName string) (*unstructured.Unstructured, error) {
|
||||
var (
|
||||
workload *unstructured.Unstructured
|
||||
err error
|
||||
)
|
||||
base, _ := pCtx.Output()
|
||||
switch wl.CapabilityCategory {
|
||||
switch comp.CapabilityCategory {
|
||||
case types.TerraformCategory:
|
||||
workload, err = generateTerraformConfigurationWorkload(wl, ns)
|
||||
workload, err = generateTerraformConfigurationWorkload(comp, ns)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to generate Terraform Configuration workload for workload %s", wl.Name)
|
||||
return nil, errors.Wrapf(err, "failed to generate Terraform Configuration workload for workload %s", comp.Name)
|
||||
}
|
||||
default:
|
||||
workload, err = base.Unstructured()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "evaluate base template component=%s app=%s", wl.Name, appName)
|
||||
return nil, errors.Wrapf(err, "evaluate base template component=%s app=%s", comp.Name, appName)
|
||||
}
|
||||
}
|
||||
commonLabels := definition.GetCommonLabels(definition.GetBaseContextLabels(pCtx))
|
||||
util.AddLabels(workload, util.MergeMapOverrideWithDst(commonLabels, map[string]string{oam.WorkloadTypeLabel: wl.Type}))
|
||||
util.AddLabels(workload, util.MergeMapOverrideWithDst(commonLabels, map[string]string{oam.WorkloadTypeLabel: comp.Type}))
|
||||
return workload, nil
|
||||
}
|
||||
|
||||
// evalWorkloadWithContext evaluate the workload's template to generate component manifest
|
||||
func evalWorkloadWithContext(pCtx process.Context, wl *Workload, ns, appName string) (*types.ComponentManifest, error) {
|
||||
func evalWorkloadWithContext(pCtx process.Context, comp *Component, ns, appName string) (*types.ComponentManifest, error) {
|
||||
compManifest := &types.ComponentManifest{}
|
||||
workload, err := makeWorkloadWithContext(pCtx, wl, ns, appName)
|
||||
workload, err := makeWorkloadWithContext(pCtx, comp, ns, appName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -593,7 +594,7 @@ func evalWorkloadWithContext(pCtx process.Context, wl *Workload, ns, appName str
|
||||
for i, assist := range assists {
|
||||
tr, err := assist.Ins.Unstructured()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "evaluate trait=%s template for component=%s app=%s", assist.Name, wl.Name, appName)
|
||||
return nil, errors.Wrapf(err, "evaluate trait=%s template for component=%s app=%s", assist.Name, comp.Name, appName)
|
||||
}
|
||||
labels := util.MergeMapOverrideWithDst(commonLabels, map[string]string{oam.TraitTypeLabel: assist.Type})
|
||||
if assist.Name != "" {
|
||||
@@ -605,26 +606,26 @@ func evalWorkloadWithContext(pCtx process.Context, wl *Workload, ns, appName str
|
||||
return compManifest, nil
|
||||
}
|
||||
|
||||
func generateTerraformConfigurationWorkload(wl *Workload, ns string) (*unstructured.Unstructured, error) {
|
||||
if wl.FullTemplate == nil || wl.FullTemplate.Terraform == nil || wl.FullTemplate.Terraform.Configuration == "" {
|
||||
func generateTerraformConfigurationWorkload(comp *Component, ns string) (*unstructured.Unstructured, error) {
|
||||
if comp.FullTemplate == nil || comp.FullTemplate.Terraform == nil || comp.FullTemplate.Terraform.Configuration == "" {
|
||||
return nil, errors.New(errTerraformConfigurationIsNotSet)
|
||||
}
|
||||
params, err := json.Marshal(wl.Params)
|
||||
params, err := json.Marshal(comp.Params)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, errFailToConvertTerraformComponentProperties)
|
||||
}
|
||||
|
||||
if wl.FullTemplate.ComponentDefinition == nil || wl.FullTemplate.ComponentDefinition.Spec.Schematic == nil ||
|
||||
wl.FullTemplate.ComponentDefinition.Spec.Schematic.Terraform == nil {
|
||||
if comp.FullTemplate.ComponentDefinition == nil || comp.FullTemplate.ComponentDefinition.Spec.Schematic == nil ||
|
||||
comp.FullTemplate.ComponentDefinition.Spec.Schematic.Terraform == nil {
|
||||
return nil, errors.New(errTerraformComponentDefinition)
|
||||
}
|
||||
|
||||
configuration := terraformapi.Configuration{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: "terraform.core.oam.dev/v1beta2", Kind: "Configuration"},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: wl.Name,
|
||||
Name: comp.Name,
|
||||
Namespace: ns,
|
||||
Annotations: wl.FullTemplate.ComponentDefinition.Annotations,
|
||||
Annotations: comp.FullTemplate.ComponentDefinition.Annotations,
|
||||
},
|
||||
}
|
||||
// 1. parse the spec of configuration
|
||||
@@ -635,26 +636,26 @@ func generateTerraformConfigurationWorkload(wl *Workload, ns string) (*unstructu
|
||||
configuration.Spec = spec
|
||||
|
||||
if configuration.Spec.WriteConnectionSecretToReference == nil {
|
||||
configuration.Spec.WriteConnectionSecretToReference = wl.FullTemplate.ComponentDefinition.Spec.Schematic.Terraform.WriteConnectionSecretToReference
|
||||
configuration.Spec.WriteConnectionSecretToReference = comp.FullTemplate.ComponentDefinition.Spec.Schematic.Terraform.WriteConnectionSecretToReference
|
||||
}
|
||||
if configuration.Spec.WriteConnectionSecretToReference != nil && configuration.Spec.WriteConnectionSecretToReference.Namespace == "" {
|
||||
configuration.Spec.WriteConnectionSecretToReference.Namespace = ns
|
||||
}
|
||||
|
||||
if configuration.Spec.ProviderReference == nil {
|
||||
configuration.Spec.ProviderReference = wl.FullTemplate.ComponentDefinition.Spec.Schematic.Terraform.ProviderReference
|
||||
configuration.Spec.ProviderReference = comp.FullTemplate.ComponentDefinition.Spec.Schematic.Terraform.ProviderReference
|
||||
}
|
||||
|
||||
if configuration.Spec.GitCredentialsSecretReference == nil {
|
||||
configuration.Spec.GitCredentialsSecretReference = wl.FullTemplate.ComponentDefinition.Spec.Schematic.Terraform.GitCredentialsSecretReference
|
||||
configuration.Spec.GitCredentialsSecretReference = comp.FullTemplate.ComponentDefinition.Spec.Schematic.Terraform.GitCredentialsSecretReference
|
||||
}
|
||||
|
||||
switch wl.FullTemplate.Terraform.Type {
|
||||
switch comp.FullTemplate.Terraform.Type {
|
||||
case "hcl":
|
||||
configuration.Spec.HCL = wl.FullTemplate.Terraform.Configuration
|
||||
configuration.Spec.HCL = comp.FullTemplate.Terraform.Configuration
|
||||
case "remote":
|
||||
configuration.Spec.Remote = wl.FullTemplate.Terraform.Configuration
|
||||
configuration.Spec.Path = wl.FullTemplate.Terraform.Path
|
||||
configuration.Spec.Remote = comp.FullTemplate.Terraform.Configuration
|
||||
configuration.Spec.Path = comp.FullTemplate.Terraform.Path
|
||||
}
|
||||
|
||||
// 2. parse variable
|
||||
|
||||
@@ -135,7 +135,7 @@ variable "password" {
|
||||
`
|
||||
)
|
||||
|
||||
wl := &Workload{
|
||||
wl := &Component{
|
||||
Name: "sample-db",
|
||||
FullTemplate: &Template{
|
||||
Terraform: &common.Terraform{
|
||||
@@ -161,10 +161,10 @@ variable "password" {
|
||||
}
|
||||
|
||||
af := &Appfile{
|
||||
Workloads: []*Workload{wl},
|
||||
Name: appName,
|
||||
AppRevisionName: revision,
|
||||
Namespace: ns,
|
||||
ParsedComponents: []*Component{wl},
|
||||
Name: appName,
|
||||
AppRevisionName: revision,
|
||||
Namespace: ns,
|
||||
}
|
||||
|
||||
variable := map[string]interface{}{"account_name": "oamtest"}
|
||||
@@ -319,13 +319,13 @@ var _ = Describe("Test evalWorkloadWithContext", func() {
|
||||
err error
|
||||
)
|
||||
type appArgs struct {
|
||||
wl *Workload
|
||||
wl *Component
|
||||
appName string
|
||||
revision string
|
||||
}
|
||||
|
||||
args := appArgs{
|
||||
wl: &Workload{
|
||||
wl: &Component{
|
||||
Name: compName,
|
||||
FullTemplate: &Template{
|
||||
Terraform: &common.Terraform{
|
||||
@@ -595,7 +595,7 @@ func TestGenerateTerraformConfigurationWorkload(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
wl := &Workload{
|
||||
wl := &Component{
|
||||
FullTemplate: template,
|
||||
Name: name,
|
||||
Params: tc.args.params,
|
||||
@@ -730,7 +730,7 @@ if context.componentType == "stateless" {
|
||||
publishVersion: context.publishVersion
|
||||
}`,
|
||||
}
|
||||
wl := &Workload{Type: "stateful", Traits: []*Trait{tr}}
|
||||
wl := &Component{Type: "stateful", Traits: []*Trait{tr}}
|
||||
cm, err := baseGenerateComponent(pContext, wl, appName, ns)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, cm.Traits[0].Object["kind"], "StatefulSet")
|
||||
@@ -751,7 +751,7 @@ var _ = Describe("Test use context.appLabels& context.appAnnotations in componen
|
||||
"ak1": "av1",
|
||||
"ak2": "av2",
|
||||
},
|
||||
Workloads: []*Workload{
|
||||
ParsedComponents: []*Component{
|
||||
{
|
||||
Name: "comp1",
|
||||
Type: "deployment",
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
|
||||
"github.com/aryann/difflib"
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/client-go/rest"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/yaml"
|
||||
@@ -40,7 +41,7 @@ import (
|
||||
)
|
||||
|
||||
// NewLiveDiffOption creates a live-diff option
|
||||
func NewLiveDiffOption(c client.Client, cfg *rest.Config, pd *packages.PackageDiscover, as []oam.Object) *LiveDiffOption {
|
||||
func NewLiveDiffOption(c client.Client, cfg *rest.Config, pd *packages.PackageDiscover, as []*unstructured.Unstructured) *LiveDiffOption {
|
||||
parser := appfile.NewApplicationParser(c, pd)
|
||||
return &LiveDiffOption{DryRun: NewDryRunOption(c, cfg, pd, as, false), Parser: parser}
|
||||
}
|
||||
@@ -136,7 +137,7 @@ func (l *LiveDiffOption) RenderlessDiff(ctx context.Context, base, comparor Live
|
||||
m := &manifest{Name: app.Name, Kind: AppKind, Data: string(bs)}
|
||||
if appfileError != nil {
|
||||
m.Data += "Error: " + appfileError.Error() + "\n"
|
||||
return m, nil //nolint
|
||||
return m, nil // nolint
|
||||
}
|
||||
for _, policy := range af.ExternalPolicies {
|
||||
if bs, err = marshalObject(policy); err == nil {
|
||||
|
||||
@@ -56,7 +56,7 @@ type DryRun interface {
|
||||
}
|
||||
|
||||
// NewDryRunOption creates a dry-run option
|
||||
func NewDryRunOption(c client.Client, cfg *rest.Config, pd *packages.PackageDiscover, as []oam.Object, serverSideDryRun bool) *Option {
|
||||
func NewDryRunOption(c client.Client, cfg *rest.Config, pd *packages.PackageDiscover, as []*unstructured.Unstructured, serverSideDryRun bool) *Option {
|
||||
parser := appfile.NewDryRunApplicationParser(c, pd, as)
|
||||
return &Option{c, pd, parser, parser.GenerateAppFileFromApp, cfg, as, serverSideDryRun}
|
||||
}
|
||||
@@ -74,7 +74,7 @@ type Option struct {
|
||||
// Auxiliaries are capability definitions used to parse application.
|
||||
// DryRun will use capabilities in Auxiliaries as higher priority than
|
||||
// getting one from cluster.
|
||||
Auxiliaries []oam.Object
|
||||
Auxiliaries []*unstructured.Unstructured
|
||||
|
||||
// serverSideDryRun If set to true, means will dry run via the apiserver.
|
||||
serverSideDryRun bool
|
||||
|
||||
@@ -25,6 +25,7 @@ import (
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
|
||||
@@ -46,7 +47,6 @@ import (
|
||||
|
||||
coreoam "github.com/oam-dev/kubevela/apis/core.oam.dev"
|
||||
"github.com/oam-dev/kubevela/pkg/appfile"
|
||||
"github.com/oam-dev/kubevela/pkg/oam"
|
||||
oamutil "github.com/oam-dev/kubevela/pkg/oam/util"
|
||||
)
|
||||
|
||||
@@ -113,7 +113,7 @@ var _ = BeforeSuite(func() {
|
||||
wfsd.SetNamespace(types.DefaultKubeVelaNS)
|
||||
Expect(k8sClient.Create(context.TODO(), &wfsd)).Should(BeNil())
|
||||
|
||||
dryrunOpt = NewDryRunOption(k8sClient, cfg, pd, []oam.Object{cdMyWorker, tdMyIngress}, false)
|
||||
dryrunOpt = NewDryRunOption(k8sClient, cfg, pd, []*unstructured.Unstructured{cdMyWorker, tdMyIngress}, false)
|
||||
diffOpt = &LiveDiffOption{DryRun: dryrunOpt, Parser: appfile.NewApplicationParser(k8sClient, pd)}
|
||||
})
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ func NewApplicationParser(cli client.Client, pd *packages.PackageDiscover) *Pars
|
||||
}
|
||||
|
||||
// NewDryRunApplicationParser create an appfile parser for DryRun
|
||||
func NewDryRunApplicationParser(cli client.Client, pd *packages.PackageDiscover, defs []oam.Object) *Parser {
|
||||
func NewDryRunApplicationParser(cli client.Client, pd *packages.PackageDiscover, defs []*unstructured.Unstructured) *Parser {
|
||||
return &Parser{
|
||||
client: cli,
|
||||
pd: pd,
|
||||
@@ -105,8 +105,6 @@ func (p *Parser) GenerateAppFile(ctx context.Context, app *v1beta1.Application)
|
||||
|
||||
// GenerateAppFileFromApp converts an application to an Appfile
|
||||
func (p *Parser) GenerateAppFileFromApp(ctx context.Context, app *v1beta1.Application) (*Appfile, error) {
|
||||
ns := app.Namespace
|
||||
appName := app.Name
|
||||
|
||||
for idx := range app.Spec.Policies {
|
||||
if app.Spec.Policies[idx].Name == "" {
|
||||
@@ -114,62 +112,32 @@ func (p *Parser) GenerateAppFileFromApp(ctx context.Context, app *v1beta1.Applic
|
||||
}
|
||||
}
|
||||
|
||||
appfile := p.newAppFile(appName, ns, app)
|
||||
appFile := newAppFile(app)
|
||||
if app.Status.LatestRevision != nil {
|
||||
appfile.AppRevisionName = app.Status.LatestRevision.Name
|
||||
appFile.AppRevisionName = app.Status.LatestRevision.Name
|
||||
}
|
||||
|
||||
var wds []*Workload
|
||||
for _, comp := range app.Spec.Components {
|
||||
wd, err := p.parseWorkload(ctx, comp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
wds = append(wds, wd)
|
||||
}
|
||||
appfile.Workloads = wds
|
||||
appfile.Components = app.Spec.Components
|
||||
|
||||
var err error
|
||||
if err = p.parseWorkflowSteps(ctx, appfile); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parseWorkflowSteps")
|
||||
if err = p.parseComponents(ctx, appFile); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parseComponents")
|
||||
}
|
||||
if err = p.parsePolicies(ctx, appfile); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parsePolicies")
|
||||
if err = p.parseWorkflowSteps(ctx, appFile); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parseWorkflowSteps")
|
||||
}
|
||||
if err = p.parseReferredObjects(ctx, appfile); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parseReferredObjects")
|
||||
if err = p.parsePolicies(ctx, appFile); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parsePolicies")
|
||||
}
|
||||
if err = p.parseReferredObjects(ctx, appFile); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parseReferredObjects")
|
||||
}
|
||||
|
||||
for _, w := range wds {
|
||||
if w == nil {
|
||||
continue
|
||||
}
|
||||
if w.FullTemplate.ComponentDefinition != nil {
|
||||
cd := w.FullTemplate.ComponentDefinition.DeepCopy()
|
||||
cd.Status = v1beta1.ComponentDefinitionStatus{}
|
||||
appfile.RelatedComponentDefinitions[w.FullTemplate.ComponentDefinition.Name] = cd
|
||||
}
|
||||
for _, t := range w.Traits {
|
||||
if t == nil {
|
||||
continue
|
||||
}
|
||||
if t.FullTemplate.TraitDefinition != nil {
|
||||
td := t.FullTemplate.TraitDefinition.DeepCopy()
|
||||
td.Status = v1beta1.TraitDefinitionStatus{}
|
||||
appfile.RelatedTraitDefinitions[t.FullTemplate.TraitDefinition.Name] = td
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return appfile, nil
|
||||
return appFile, nil
|
||||
}
|
||||
|
||||
func (p *Parser) newAppFile(appName, ns string, app *v1beta1.Application) *Appfile {
|
||||
func newAppFile(app *v1beta1.Application) *Appfile {
|
||||
file := &Appfile{
|
||||
Name: appName,
|
||||
Namespace: ns,
|
||||
Name: app.Name,
|
||||
Namespace: app.Namespace,
|
||||
|
||||
AppLabels: make(map[string]string),
|
||||
AppAnnotations: make(map[string]string),
|
||||
@@ -179,8 +147,7 @@ func (p *Parser) newAppFile(appName, ns string, app *v1beta1.Application) *Appfi
|
||||
|
||||
ExternalPolicies: make(map[string]*v1alpha1.Policy),
|
||||
|
||||
parser: p,
|
||||
app: app,
|
||||
app: app,
|
||||
}
|
||||
for k, v := range app.Annotations {
|
||||
file.AppAnnotations[k] = v
|
||||
@@ -246,10 +213,8 @@ func (p *Parser) GenerateAppFileFromRevision(appRev *v1beta1.ApplicationRevision
|
||||
|
||||
inheritLabelAndAnnotationFromAppRev(appRev)
|
||||
|
||||
app := appRev.Spec.Application.DeepCopy()
|
||||
ns := app.Namespace
|
||||
appName := app.Name
|
||||
appfile := p.newAppFile(appName, ns, app)
|
||||
ctx := context.Background()
|
||||
appfile := newAppFile(appRev.Spec.Application.DeepCopy())
|
||||
appfile.AppRevision = appRev
|
||||
appfile.AppRevisionName = appRev.Name
|
||||
appfile.AppRevisionHash = appRev.Labels[oam.LabelAppRevisionHash]
|
||||
@@ -259,62 +224,52 @@ func (p *Parser) GenerateAppFileFromRevision(appRev *v1beta1.ApplicationRevision
|
||||
}
|
||||
appfile.ExternalWorkflow = appRev.Spec.Workflow
|
||||
|
||||
var wds []*Workload
|
||||
for _, comp := range app.Spec.Components {
|
||||
wd, err := p.ParseWorkloadFromRevision(comp, appRev)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
wds = append(wds, wd)
|
||||
if err := p.parseComponentsFromRevision(appfile); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parseComponentsFromRevision")
|
||||
}
|
||||
appfile.Workloads = wds
|
||||
appfile.Components = app.Spec.Components
|
||||
if err := p.parseWorkflowStepsFromRevision(context.Background(), appfile); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parseWorkflowStepsFromRevision")
|
||||
if err := p.parseWorkflowStepsFromRevision(ctx, appfile); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parseWorkflowStepsFromRevision")
|
||||
}
|
||||
if err := p.parsePoliciesFromRevision(context.Background(), appfile); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parsePolicies")
|
||||
if err := p.parsePoliciesFromRevision(ctx, appfile); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parsePolicies")
|
||||
}
|
||||
if err := p.parseReferredObjectsFromRevision(appfile); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parseReferredObjects")
|
||||
}
|
||||
|
||||
for k, v := range appRev.Spec.ComponentDefinitions {
|
||||
appfile.RelatedComponentDefinitions[k] = v.DeepCopy()
|
||||
}
|
||||
for k, v := range appRev.Spec.TraitDefinitions {
|
||||
appfile.RelatedTraitDefinitions[k] = v.DeepCopy()
|
||||
}
|
||||
for k, v := range appRev.Spec.WorkflowStepDefinitions {
|
||||
appfile.RelatedWorkflowStepDefinitions[k] = v.DeepCopy()
|
||||
return nil, errors.Wrap(err, "failed to parseReferredObjects")
|
||||
}
|
||||
|
||||
// add compatible code for upgrading to v1.3 as the workflow steps were not recorded before v1.2
|
||||
if len(appfile.RelatedWorkflowStepDefinitions) == 0 && len(appfile.WorkflowSteps) > 0 {
|
||||
ctx := context.Background()
|
||||
for _, workflowStep := range appfile.WorkflowSteps {
|
||||
if step.IsBuiltinWorkflowStepType(workflowStep.Type) {
|
||||
continue
|
||||
}
|
||||
if _, found := appfile.RelatedWorkflowStepDefinitions[workflowStep.Type]; found {
|
||||
continue
|
||||
}
|
||||
def := &v1beta1.WorkflowStepDefinition{}
|
||||
if err := util.GetCapabilityDefinition(ctx, p.client, def, workflowStep.Type); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to get workflow step definition %s", workflowStep.Type)
|
||||
}
|
||||
appfile.RelatedWorkflowStepDefinitions[workflowStep.Type] = def
|
||||
}
|
||||
|
||||
appRev.Spec.WorkflowStepDefinitions = make(map[string]*v1beta1.WorkflowStepDefinition)
|
||||
for name, def := range appfile.RelatedWorkflowStepDefinitions {
|
||||
appRev.Spec.WorkflowStepDefinitions[name] = def
|
||||
if err := p.parseWorkflowStepsForLegacyRevision(ctx, appfile); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parseWorkflowStepsForLegacyRevision")
|
||||
}
|
||||
}
|
||||
|
||||
return appfile, nil
|
||||
}
|
||||
|
||||
// parseWorkflowStepsForLegacyRevision compatible for upgrading to v1.3 as the workflow steps were not recorded before v1.2
|
||||
func (p *Parser) parseWorkflowStepsForLegacyRevision(ctx context.Context, af *Appfile) error {
|
||||
for _, workflowStep := range af.WorkflowSteps {
|
||||
if step.IsBuiltinWorkflowStepType(workflowStep.Type) {
|
||||
continue
|
||||
}
|
||||
if _, found := af.RelatedWorkflowStepDefinitions[workflowStep.Type]; found {
|
||||
continue
|
||||
}
|
||||
def := &v1beta1.WorkflowStepDefinition{}
|
||||
if err := util.GetCapabilityDefinition(ctx, p.client, def, workflowStep.Type); err != nil {
|
||||
return errors.Wrapf(err, "failed to get workflow step definition %s", workflowStep.Type)
|
||||
}
|
||||
af.RelatedWorkflowStepDefinitions[workflowStep.Type] = def
|
||||
}
|
||||
|
||||
af.AppRevision.Spec.WorkflowStepDefinitions = make(map[string]*v1beta1.WorkflowStepDefinition)
|
||||
for name, def := range af.RelatedWorkflowStepDefinitions {
|
||||
af.AppRevision.Spec.WorkflowStepDefinitions[name] = def
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parser) parseReferredObjectsFromRevision(af *Appfile) error {
|
||||
af.ReferredObjects = []*unstructured.Unstructured{}
|
||||
for _, obj := range af.AppRevision.Spec.ReferredObjects {
|
||||
@@ -389,11 +344,11 @@ func (p *Parser) parsePoliciesFromRevision(ctx context.Context, af *Appfile) (er
|
||||
case v1alpha1.DebugPolicyType:
|
||||
af.Debug = true
|
||||
default:
|
||||
w, err := p.makeWorkloadFromRevision(policy.Name, policy.Type, types.TypePolicy, policy.Properties, af.AppRevision)
|
||||
w, err := p.makeComponentFromRevision(policy.Name, policy.Type, types.TypePolicy, policy.Properties, af.AppRevision)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
af.PolicyWorkloads = append(af.PolicyWorkloads, w)
|
||||
af.ParsedPolicies = append(af.ParsedPolicies, w)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@@ -432,11 +387,11 @@ func (p *Parser) parsePolicies(ctx context.Context, af *Appfile) (err error) {
|
||||
af.RelatedTraitDefinitions[def.Name] = def
|
||||
}
|
||||
default:
|
||||
w, err := p.makeWorkload(ctx, policy.Name, policy.Type, types.TypePolicy, policy.Properties)
|
||||
w, err := p.makeComponent(ctx, policy.Name, policy.Type, types.TypePolicy, policy.Properties)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
af.PolicyWorkloads = append(af.PolicyWorkloads, w)
|
||||
af.ParsedPolicies = append(af.ParsedPolicies, w)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@@ -480,7 +435,14 @@ func (p *Parser) loadWorkflowToAppfile(ctx context.Context, af *Appfile) error {
|
||||
}
|
||||
|
||||
func (p *Parser) parseWorkflowStepsFromRevision(ctx context.Context, af *Appfile) error {
|
||||
return p.loadWorkflowToAppfile(ctx, af)
|
||||
if err := p.loadWorkflowToAppfile(ctx, af); err != nil {
|
||||
return err
|
||||
}
|
||||
// Definitions are already in AppRevision
|
||||
for k, v := range af.AppRevision.Spec.WorkflowStepDefinitions {
|
||||
af.RelatedWorkflowStepDefinitions[k] = v.DeepCopy()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parser) parseWorkflowSteps(ctx context.Context, af *Appfile) error {
|
||||
@@ -488,14 +450,14 @@ func (p *Parser) parseWorkflowSteps(ctx context.Context, af *Appfile) error {
|
||||
return err
|
||||
}
|
||||
for _, workflowStep := range af.WorkflowSteps {
|
||||
err := p.parseWorkflowStep(ctx, af, workflowStep.Type)
|
||||
err := p.fetchAndSetWorkflowStepDefinition(ctx, af, workflowStep.Type)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if workflowStep.SubSteps != nil {
|
||||
for _, workflowSubStep := range workflowStep.SubSteps {
|
||||
err := p.parseWorkflowStep(ctx, af, workflowSubStep.Type)
|
||||
err := p.fetchAndSetWorkflowStepDefinition(ctx, af, workflowSubStep.Type)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -505,7 +467,7 @@ func (p *Parser) parseWorkflowSteps(ctx context.Context, af *Appfile) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parser) parseWorkflowStep(ctx context.Context, af *Appfile, workflowStepType string) error {
|
||||
func (p *Parser) fetchAndSetWorkflowStepDefinition(ctx context.Context, af *Appfile, workflowStepType string) error {
|
||||
if step.IsBuiltinWorkflowStepType(workflowStepType) {
|
||||
return nil
|
||||
}
|
||||
@@ -520,36 +482,36 @@ func (p *Parser) parseWorkflowStep(ctx context.Context, af *Appfile, workflowSte
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parser) makeWorkload(ctx context.Context, name, typ string, capType types.CapType, props *runtime.RawExtension) (*Workload, error) {
|
||||
func (p *Parser) makeComponent(ctx context.Context, name, typ string, capType types.CapType, props *runtime.RawExtension) (*Component, error) {
|
||||
templ, err := p.tmplLoader.LoadTemplate(ctx, p.client, typ, capType)
|
||||
if err != nil {
|
||||
return nil, errors.WithMessagef(err, "fetch component/policy type of %s", name)
|
||||
}
|
||||
return p.convertTemplate2Workload(name, typ, props, templ)
|
||||
return p.convertTemplate2Component(name, typ, props, templ)
|
||||
}
|
||||
|
||||
func (p *Parser) makeWorkloadFromRevision(name, typ string, capType types.CapType, props *runtime.RawExtension, appRev *v1beta1.ApplicationRevision) (*Workload, error) {
|
||||
func (p *Parser) makeComponentFromRevision(name, typ string, capType types.CapType, props *runtime.RawExtension, appRev *v1beta1.ApplicationRevision) (*Component, error) {
|
||||
templ, err := LoadTemplateFromRevision(typ, capType, appRev, p.client.RESTMapper())
|
||||
if err != nil {
|
||||
return nil, errors.WithMessagef(err, "fetch component/policy type of %s from revision", name)
|
||||
}
|
||||
|
||||
return p.convertTemplate2Workload(name, typ, props, templ)
|
||||
return p.convertTemplate2Component(name, typ, props, templ)
|
||||
}
|
||||
|
||||
func (p *Parser) convertTemplate2Workload(name, typ string, props *runtime.RawExtension, templ *Template) (*Workload, error) {
|
||||
func (p *Parser) convertTemplate2Component(name, typ string, props *runtime.RawExtension, templ *Template) (*Component, error) {
|
||||
settings, err := util.RawExtension2Map(props)
|
||||
if err != nil {
|
||||
return nil, errors.WithMessagef(err, "fail to parse settings for %s", name)
|
||||
}
|
||||
wlType, err := util.ConvertDefinitionRevName(typ)
|
||||
cpType, err := util.ConvertDefinitionRevName(typ)
|
||||
if err != nil {
|
||||
wlType = typ
|
||||
cpType = typ
|
||||
}
|
||||
return &Workload{
|
||||
return &Component{
|
||||
Traits: []*Trait{},
|
||||
Name: name,
|
||||
Type: wlType,
|
||||
Type: cpType,
|
||||
CapabilityCategory: templ.CapabilityCategory,
|
||||
FullTemplate: templ,
|
||||
Params: settings,
|
||||
@@ -557,10 +519,61 @@ func (p *Parser) convertTemplate2Workload(name, typ string, props *runtime.RawEx
|
||||
}, nil
|
||||
}
|
||||
|
||||
// parseWorkload resolve an ApplicationComponent and generate a Workload
|
||||
// parseComponents resolve an Application Components and Traits to generate Component
|
||||
func (p *Parser) parseComponents(ctx context.Context, af *Appfile) error {
|
||||
var comps []*Component
|
||||
for _, c := range af.app.Spec.Components {
|
||||
comp, err := p.parseComponent(ctx, c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
comps = append(comps, comp)
|
||||
}
|
||||
|
||||
af.ParsedComponents = comps
|
||||
af.Components = af.app.Spec.Components
|
||||
setComponentDefinitions(af, comps)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func setComponentDefinitions(af *Appfile, comps []*Component) {
|
||||
for _, comp := range comps {
|
||||
if comp == nil {
|
||||
continue
|
||||
}
|
||||
if comp.FullTemplate.ComponentDefinition != nil {
|
||||
cd := comp.FullTemplate.ComponentDefinition.DeepCopy()
|
||||
cd.Status = v1beta1.ComponentDefinitionStatus{}
|
||||
af.RelatedComponentDefinitions[comp.FullTemplate.ComponentDefinition.Name] = cd
|
||||
}
|
||||
for _, t := range comp.Traits {
|
||||
if t == nil {
|
||||
continue
|
||||
}
|
||||
if t.FullTemplate.TraitDefinition != nil {
|
||||
td := t.FullTemplate.TraitDefinition.DeepCopy()
|
||||
td.Status = v1beta1.TraitDefinitionStatus{}
|
||||
af.RelatedTraitDefinitions[t.FullTemplate.TraitDefinition.Name] = td
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// setComponentDefinitionsFromRevision can set related definitions directly from app revision
|
||||
func setComponentDefinitionsFromRevision(af *Appfile) {
|
||||
for k, v := range af.AppRevision.Spec.ComponentDefinitions {
|
||||
af.RelatedComponentDefinitions[k] = v.DeepCopy()
|
||||
}
|
||||
for k, v := range af.AppRevision.Spec.TraitDefinitions {
|
||||
af.RelatedTraitDefinitions[k] = v.DeepCopy()
|
||||
}
|
||||
}
|
||||
|
||||
// parseComponent resolve an ApplicationComponent and generate a Component
|
||||
// containing ALL information required by an Appfile.
|
||||
func (p *Parser) parseWorkload(ctx context.Context, comp common.ApplicationComponent) (*Workload, error) {
|
||||
workload, err := p.makeWorkload(ctx, comp.Name, comp.Type, types.TypeComponentDefinition, comp.Properties)
|
||||
func (p *Parser) parseComponent(ctx context.Context, comp common.ApplicationComponent) (*Component, error) {
|
||||
workload, err := p.makeComponent(ctx, comp.Name, comp.Type, types.TypeComponentDefinition, comp.Properties)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -571,7 +584,7 @@ func (p *Parser) parseWorkload(ctx context.Context, comp common.ApplicationCompo
|
||||
return workload, nil
|
||||
}
|
||||
|
||||
func (p *Parser) parseTraits(ctx context.Context, workload *Workload, comp common.ApplicationComponent) error {
|
||||
func (p *Parser) parseTraits(ctx context.Context, workload *Component, comp common.ApplicationComponent) error {
|
||||
for _, traitValue := range comp.Traits {
|
||||
properties, err := util.RawExtension2Map(traitValue.Properties)
|
||||
if err != nil {
|
||||
@@ -587,10 +600,26 @@ func (p *Parser) parseTraits(ctx context.Context, workload *Workload, comp commo
|
||||
return nil
|
||||
}
|
||||
|
||||
// ParseWorkloadFromRevision resolve an ApplicationComponent and generate a Workload
|
||||
func (p *Parser) parseComponentsFromRevision(af *Appfile) error {
|
||||
var comps []*Component
|
||||
for _, c := range af.app.Spec.Components {
|
||||
comp, err := p.ParseComponentFromRevision(c, af.AppRevision)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
comps = append(comps, comp)
|
||||
}
|
||||
af.ParsedComponents = comps
|
||||
af.Components = af.app.Spec.Components
|
||||
// Definitions are already in AppRevision
|
||||
setComponentDefinitionsFromRevision(af)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ParseComponentFromRevision resolve an ApplicationComponent and generate a Component
|
||||
// containing ALL information required by an Appfile from app revision.
|
||||
func (p *Parser) ParseWorkloadFromRevision(comp common.ApplicationComponent, appRev *v1beta1.ApplicationRevision) (*Workload, error) {
|
||||
workload, err := p.makeWorkloadFromRevision(comp.Name, comp.Type, types.TypeComponentDefinition, comp.Properties, appRev)
|
||||
func (p *Parser) ParseComponentFromRevision(comp common.ApplicationComponent, appRev *v1beta1.ApplicationRevision) (*Component, error) {
|
||||
workload, err := p.makeComponentFromRevision(comp.Name, comp.Type, types.TypeComponentDefinition, comp.Properties, appRev)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -602,7 +631,7 @@ func (p *Parser) ParseWorkloadFromRevision(comp common.ApplicationComponent, app
|
||||
return workload, nil
|
||||
}
|
||||
|
||||
func (p *Parser) parseTraitsFromRevision(comp common.ApplicationComponent, appRev *v1beta1.ApplicationRevision, workload *Workload) error {
|
||||
func (p *Parser) parseTraitsFromRevision(comp common.ApplicationComponent, appRev *v1beta1.ApplicationRevision, workload *Component) error {
|
||||
for _, traitValue := range comp.Traits {
|
||||
properties, err := util.RawExtension2Map(traitValue.Properties)
|
||||
if err != nil {
|
||||
@@ -618,35 +647,35 @@ func (p *Parser) parseTraitsFromRevision(comp common.ApplicationComponent, appRe
|
||||
return nil
|
||||
}
|
||||
|
||||
// ParseWorkloadFromRevisionAndClient resolve an ApplicationComponent and generate a Workload
|
||||
// ParseComponentFromRevisionAndClient resolve an ApplicationComponent and generate a Component
|
||||
// containing ALL information required by an Appfile from app revision, and will fall back to
|
||||
// load external definitions if not found
|
||||
func (p *Parser) ParseWorkloadFromRevisionAndClient(ctx context.Context, comp common.ApplicationComponent, appRev *v1beta1.ApplicationRevision) (*Workload, error) {
|
||||
workload, err := p.makeWorkloadFromRevision(comp.Name, comp.Type, types.TypeComponentDefinition, comp.Properties, appRev)
|
||||
func (p *Parser) ParseComponentFromRevisionAndClient(ctx context.Context, c common.ApplicationComponent, appRev *v1beta1.ApplicationRevision) (*Component, error) {
|
||||
comp, err := p.makeComponentFromRevision(c.Name, c.Type, types.TypeComponentDefinition, c.Properties, appRev)
|
||||
if IsNotFoundInAppRevision(err) {
|
||||
workload, err = p.makeWorkload(ctx, comp.Name, comp.Type, types.TypeComponentDefinition, comp.Properties)
|
||||
comp, err = p.makeComponent(ctx, c.Name, c.Type, types.TypeComponentDefinition, c.Properties)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, traitValue := range comp.Traits {
|
||||
for _, traitValue := range c.Traits {
|
||||
properties, err := util.RawExtension2Map(traitValue.Properties)
|
||||
if err != nil {
|
||||
return nil, errors.Errorf("fail to parse properties of %s for %s", traitValue.Type, comp.Name)
|
||||
return nil, errors.Errorf("fail to parse properties of %s for %s", traitValue.Type, c.Name)
|
||||
}
|
||||
trait, err := p.parseTraitFromRevision(traitValue.Type, properties, appRev)
|
||||
if IsNotFoundInAppRevision(err) {
|
||||
trait, err = p.parseTrait(ctx, traitValue.Type, properties)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, errors.WithMessagef(err, "component(%s) parse trait(%s)", comp.Name, traitValue.Type)
|
||||
return nil, errors.WithMessagef(err, "component(%s) parse trait(%s)", c.Name, traitValue.Type)
|
||||
}
|
||||
|
||||
workload.Traits = append(workload.Traits, trait)
|
||||
comp.Traits = append(comp.Traits, trait)
|
||||
}
|
||||
|
||||
return workload, nil
|
||||
return comp, nil
|
||||
}
|
||||
|
||||
func (p *Parser) parseTrait(ctx context.Context, name string, properties map[string]interface{}) (*Trait, error) {
|
||||
@@ -685,7 +714,7 @@ func (p *Parser) convertTemplate2Trait(name string, properties map[string]interf
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ValidateComponentNames validate all component names whether repeat in cluster and template
|
||||
// ValidateComponentNames validate all component names whether repeat in app
|
||||
func (p *Parser) ValidateComponentNames(app *v1beta1.Application) (int, error) {
|
||||
compNames := map[string]struct{}{}
|
||||
for idx, comp := range app.Spec.Components {
|
||||
|
||||
@@ -46,7 +46,7 @@ import (
|
||||
|
||||
var expectedExceptApp = &Appfile{
|
||||
Name: "application-sample",
|
||||
Workloads: []*Workload{
|
||||
ParsedComponents: []*Component{
|
||||
{
|
||||
Name: "myweb",
|
||||
Type: "worker",
|
||||
@@ -286,11 +286,11 @@ var _ = Describe("Test application parser", func() {
|
||||
})
|
||||
|
||||
func equal(af, dest *Appfile) bool {
|
||||
if af.Name != dest.Name || len(af.Workloads) != len(dest.Workloads) {
|
||||
if af.Name != dest.Name || len(af.ParsedComponents) != len(dest.ParsedComponents) {
|
||||
return false
|
||||
}
|
||||
for i, wd := range af.Workloads {
|
||||
destWd := dest.Workloads[i]
|
||||
for i, wd := range af.ParsedComponents {
|
||||
destWd := dest.ParsedComponents[i]
|
||||
if wd.Name != destWd.Name || len(wd.Traits) != len(destWd.Traits) {
|
||||
return false
|
||||
}
|
||||
@@ -327,7 +327,7 @@ var _ = Describe("Test application parser", func() {
|
||||
// prepare verify data
|
||||
expectedExceptAppfile = &Appfile{
|
||||
Name: "backport-1-2-test-demo",
|
||||
Workloads: []*Workload{
|
||||
ParsedComponents: []*Component{
|
||||
{
|
||||
Name: "backport-1-2-test-demo",
|
||||
Type: "webservice",
|
||||
@@ -502,14 +502,17 @@ patch: spec: replicas: parameter.replicas
|
||||
|
||||
_, err := NewApplicationParser(&mockClient, pd).GenerateAppFile(context.TODO(), &app)
|
||||
Expect(err).Should(HaveOccurred())
|
||||
Expect(err.Error() == "failed to get workflow step definition apply-application-unknown: not found").Should(BeTrue())
|
||||
Expect(err.Error()).Should(SatisfyAll(
|
||||
ContainSubstring("failed to get workflow step definition apply-application-unknown: not found"),
|
||||
ContainSubstring("failed to parseWorkflowStepsForLegacyRevision")),
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
func TestParser_parseTraits(t *testing.T) {
|
||||
type args struct {
|
||||
workload *Workload
|
||||
workload *Component
|
||||
comp common.ApplicationComponent
|
||||
}
|
||||
tests := []struct {
|
||||
@@ -517,7 +520,7 @@ func TestParser_parseTraits(t *testing.T) {
|
||||
args args
|
||||
wantErr assert.ErrorAssertionFunc
|
||||
mockTemplateLoaderFn TemplateLoaderFn
|
||||
validateFunc func(w *Workload) bool
|
||||
validateFunc func(w *Component) bool
|
||||
}{
|
||||
{
|
||||
name: "test empty traits",
|
||||
@@ -574,7 +577,7 @@ func TestParser_parseTraits(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
workload: &Workload{},
|
||||
workload: &Component{},
|
||||
},
|
||||
wantErr: assert.NoError,
|
||||
mockTemplateLoaderFn: func(ctx context.Context, reader client.Client, s string, capType types.CapType) (*Template, error) {
|
||||
@@ -585,7 +588,7 @@ func TestParser_parseTraits(t *testing.T) {
|
||||
CustomStatus: "healthy",
|
||||
}, nil
|
||||
},
|
||||
validateFunc: func(w *Workload) bool {
|
||||
validateFunc: func(w *Component) bool {
|
||||
return w != nil && len(w.Traits) != 0 && w.Traits[0].Name == "expose" && w.Traits[0].Template == "template"
|
||||
},
|
||||
},
|
||||
@@ -608,12 +611,12 @@ func TestParser_parseTraitsFromRevision(t *testing.T) {
|
||||
type args struct {
|
||||
comp common.ApplicationComponent
|
||||
appRev *v1beta1.ApplicationRevision
|
||||
workload *Workload
|
||||
workload *Component
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
validateFunc func(w *Workload) bool
|
||||
validateFunc func(w *Component) bool
|
||||
wantErr assert.ErrorAssertionFunc
|
||||
}{
|
||||
{
|
||||
@@ -634,7 +637,7 @@ func TestParser_parseTraitsFromRevision(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
workload: &Workload{},
|
||||
workload: &Component{},
|
||||
},
|
||||
wantErr: assert.Error,
|
||||
},
|
||||
@@ -656,7 +659,7 @@ func TestParser_parseTraitsFromRevision(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
workload: &Workload{},
|
||||
workload: &Component{},
|
||||
},
|
||||
wantErr: assert.Error,
|
||||
},
|
||||
@@ -685,10 +688,10 @@ func TestParser_parseTraitsFromRevision(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
workload: &Workload{},
|
||||
workload: &Component{},
|
||||
},
|
||||
wantErr: assert.NoError,
|
||||
validateFunc: func(w *Workload) bool {
|
||||
validateFunc: func(w *Component) bool {
|
||||
return w != nil && len(w.Traits) == 1 && w.Traits[0].Name == "expose"
|
||||
},
|
||||
},
|
||||
|
||||
@@ -34,7 +34,6 @@ import (
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
|
||||
"github.com/oam-dev/kubevela/apis/types"
|
||||
"github.com/oam-dev/kubevela/pkg/oam"
|
||||
oamutil "github.com/oam-dev/kubevela/pkg/oam/util"
|
||||
)
|
||||
|
||||
@@ -252,35 +251,33 @@ func verifyRevisionName(capName string, capType types.CapType, apprev *v1beta1.A
|
||||
// DryRunTemplateLoader return a function that do the same work as
|
||||
// LoadTemplate, but load template from provided ones before loading from
|
||||
// cluster through LoadTemplate
|
||||
func DryRunTemplateLoader(defs []oam.Object) TemplateLoaderFn {
|
||||
func DryRunTemplateLoader(defs []*unstructured.Unstructured) TemplateLoaderFn {
|
||||
return func(ctx context.Context, r client.Client, capName string, capType types.CapType) (*Template, error) {
|
||||
// retrieve provided cap definitions
|
||||
for _, def := range defs {
|
||||
if unstructDef, ok := def.(*unstructured.Unstructured); ok {
|
||||
if unstructDef.GetKind() == v1beta1.ComponentDefinitionKind &&
|
||||
capType == types.TypeComponentDefinition && unstructDef.GetName() == capName {
|
||||
compDef := &v1beta1.ComponentDefinition{}
|
||||
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(unstructDef.Object, compDef); err != nil {
|
||||
return nil, errors.Wrap(err, "invalid component definition")
|
||||
}
|
||||
tmpl, err := newTemplateOfCompDefinition(compDef)
|
||||
if err != nil {
|
||||
return nil, errors.WithMessagef(err, "cannot load template of component definition %q", capName)
|
||||
}
|
||||
return tmpl, nil
|
||||
if def.GetKind() == v1beta1.ComponentDefinitionKind &&
|
||||
capType == types.TypeComponentDefinition && def.GetName() == capName {
|
||||
compDef := &v1beta1.ComponentDefinition{}
|
||||
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(def.Object, compDef); err != nil {
|
||||
return nil, errors.Wrap(err, "invalid component definition")
|
||||
}
|
||||
if unstructDef.GetKind() == v1beta1.TraitDefinitionKind &&
|
||||
capType == types.TypeTrait && unstructDef.GetName() == capName {
|
||||
traitDef := &v1beta1.TraitDefinition{}
|
||||
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(unstructDef.Object, traitDef); err != nil {
|
||||
return nil, errors.Wrap(err, "invalid trait definition")
|
||||
}
|
||||
tmpl, err := newTemplateOfTraitDefinition(traitDef)
|
||||
if err != nil {
|
||||
return nil, errors.WithMessagef(err, "cannot load template of trait definition %q", capName)
|
||||
}
|
||||
return tmpl, nil
|
||||
tmpl, err := newTemplateOfCompDefinition(compDef)
|
||||
if err != nil {
|
||||
return nil, errors.WithMessagef(err, "cannot load template of component definition %q", capName)
|
||||
}
|
||||
return tmpl, nil
|
||||
}
|
||||
if def.GetKind() == v1beta1.TraitDefinitionKind &&
|
||||
capType == types.TypeTrait && def.GetName() == capName {
|
||||
traitDef := &v1beta1.TraitDefinition{}
|
||||
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(def.Object, traitDef); err != nil {
|
||||
return nil, errors.Wrap(err, "invalid trait definition")
|
||||
}
|
||||
tmpl, err := newTemplateOfTraitDefinition(traitDef)
|
||||
if err != nil {
|
||||
return nil, errors.WithMessagef(err, "cannot load template of trait definition %q", capName)
|
||||
}
|
||||
return tmpl, nil
|
||||
}
|
||||
}
|
||||
// not found in provided cap definitions
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
"github.com/crossplane/crossplane-runtime/pkg/test"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
ktypes "k8s.io/apimachinery/pkg/types"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
@@ -31,7 +32,6 @@ import (
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
|
||||
"github.com/oam-dev/kubevela/apis/types"
|
||||
"github.com/oam-dev/kubevela/pkg/oam"
|
||||
oamutil "github.com/oam-dev/kubevela/pkg/oam/util"
|
||||
)
|
||||
|
||||
@@ -362,7 +362,7 @@ spec:
|
||||
TraitDefinition: traitDef,
|
||||
}
|
||||
|
||||
dryRunLoadTemplate := DryRunTemplateLoader([]oam.Object{unstrctCompDef, unstrctTraitDef})
|
||||
dryRunLoadTemplate := DryRunTemplateLoader([]*unstructured.Unstructured{unstrctCompDef, unstrctTraitDef})
|
||||
compTmpl, err := dryRunLoadTemplate(nil, nil, "myworker", types.TypeComponentDefinition)
|
||||
if err != nil {
|
||||
t.Error("failed load template of component defintion", err)
|
||||
|
||||
@@ -38,7 +38,7 @@ func TestIsNotFoundInAppRevision(t *testing.T) {
|
||||
require.True(t, IsNotFoundInAppRevision(fmt.Errorf("ComponentDefinition XXX not found in app revision")))
|
||||
}
|
||||
|
||||
func TestParseWorkloadFromRevisionAndClient(t *testing.T) {
|
||||
func TestParseComponentFromRevisionAndClient(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
cli := fake.NewClientBuilder().WithScheme(scheme).Build()
|
||||
p := &Parser{
|
||||
@@ -63,21 +63,21 @@ func TestParseWorkloadFromRevisionAndClient(t *testing.T) {
|
||||
require.NoError(t, cli.Create(ctx, cd))
|
||||
require.NoError(t, cli.Create(ctx, td))
|
||||
appRev.Spec.TraitDefinitions = map[string]*v1beta1.TraitDefinition{"internal": {}}
|
||||
_, err := p.ParseWorkloadFromRevisionAndClient(ctx, comp, appRev)
|
||||
_, err := p.ParseComponentFromRevisionAndClient(ctx, comp, appRev)
|
||||
require.NoError(t, err)
|
||||
|
||||
_comp1 := comp.DeepCopy()
|
||||
_comp1.Type = "bad"
|
||||
_, err = p.ParseWorkloadFromRevisionAndClient(ctx, *_comp1, appRev)
|
||||
_, err = p.ParseComponentFromRevisionAndClient(ctx, *_comp1, appRev)
|
||||
require.Error(t, err)
|
||||
|
||||
_comp2 := comp.DeepCopy()
|
||||
_comp2.Traits[0].Type = "bad"
|
||||
_, err = p.ParseWorkloadFromRevisionAndClient(ctx, *_comp2, appRev)
|
||||
_, err = p.ParseComponentFromRevisionAndClient(ctx, *_comp2, appRev)
|
||||
require.Error(t, err)
|
||||
|
||||
_comp3 := comp.DeepCopy()
|
||||
_comp3.Traits[0].Properties = &runtime.RawExtension{Raw: []byte(`bad`)}
|
||||
_, err = p.ParseWorkloadFromRevisionAndClient(ctx, *_comp3, appRev)
|
||||
_, err = p.ParseComponentFromRevisionAndClient(ctx, *_comp3, appRev)
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ import (
|
||||
|
||||
// ValidateCUESchematicAppfile validates CUE schematic workloads in an Appfile
|
||||
func (p *Parser) ValidateCUESchematicAppfile(a *Appfile) error {
|
||||
for _, wl := range a.Workloads {
|
||||
for _, wl := range a.ParsedComponents {
|
||||
// because helm & kube schematic has no CUE template
|
||||
// it only validates CUE schematic workload
|
||||
if wl.CapabilityCategory != types.CUECategory || wl.Type == v1alpha1.RefObjectsComponentType {
|
||||
@@ -53,7 +53,7 @@ func (p *Parser) ValidateCUESchematicAppfile(a *Appfile) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func newValidationProcessContext(wl *Workload, ctxData velaprocess.ContextData) (process.Context, error) {
|
||||
func newValidationProcessContext(c *Component, ctxData velaprocess.ContextData) (process.Context, error) {
|
||||
baseHooks := []process.BaseHook{
|
||||
// add more hook funcs here to validate CUE base
|
||||
}
|
||||
@@ -65,7 +65,7 @@ func newValidationProcessContext(wl *Workload, ctxData velaprocess.ContextData)
|
||||
ctxData.BaseHooks = baseHooks
|
||||
ctxData.AuxiliaryHooks = auxiliaryHooks
|
||||
pCtx := velaprocess.NewContext(ctxData)
|
||||
if err := wl.EvalContext(pCtx); err != nil {
|
||||
if err := c.EvalContext(pCtx); err != nil {
|
||||
return nil, errors.Wrapf(err, "evaluate base template app=%s in namespace=%s", ctxData.AppName, ctxData.Namespace)
|
||||
}
|
||||
return pCtx, nil
|
||||
|
||||
@@ -34,7 +34,7 @@ var _ = Describe("Test validate CUE schematic Appfile", func() {
|
||||
|
||||
DescribeTable("Test validate outputs name unique", func(tc SubTestCase) {
|
||||
Expect("").Should(BeEmpty())
|
||||
wl := &Workload{
|
||||
wl := &Component{
|
||||
Name: "myweb",
|
||||
Type: "worker",
|
||||
CapabilityCategory: types.CUECategory,
|
||||
|
||||
@@ -46,9 +46,6 @@ type Args struct {
|
||||
// AutoGenWorkloadDefinition indicates whether automatic generated workloadDefinition which componentDefinition refers to
|
||||
AutoGenWorkloadDefinition bool
|
||||
|
||||
// EnableCompatibility indicates that will change some functions of controller to adapt to multiple platforms, such as asi.
|
||||
EnableCompatibility bool
|
||||
|
||||
// IgnoreAppWithoutControllerRequirement indicates that application controller will not process the app without 'app.oam.dev/controller-version-require' annotation.
|
||||
IgnoreAppWithoutControllerRequirement bool
|
||||
|
||||
@@ -66,7 +63,6 @@ func (a *Args) AddFlags(fs *pflag.FlagSet, c *Args) {
|
||||
"definition-revision-limit is the maximum number of component/trait definition useless revisions that will be maintained, if the useless revisions exceed this number, older ones will be GCed first.The default value is 20.")
|
||||
fs.BoolVar(&a.AutoGenWorkloadDefinition, "autogen-workload-definition", c.AutoGenWorkloadDefinition, "Automatic generated workloadDefinition which componentDefinition refers to.")
|
||||
fs.IntVar(&a.ConcurrentReconciles, "concurrent-reconciles", c.ConcurrentReconciles, "concurrent-reconciles is the concurrent reconcile number of the controller. The default value is 4")
|
||||
fs.BoolVar(&a.EnableCompatibility, "enable-asi-compatibility", c.EnableCompatibility, "enable compatibility for asi")
|
||||
fs.BoolVar(&a.IgnoreAppWithoutControllerRequirement, "ignore-app-without-controller-version", c.IgnoreAppWithoutControllerRequirement, "If true, application controller will not process the app without 'app.oam.dev/controller-version-require' annotation")
|
||||
fs.BoolVar(&a.IgnoreDefinitionWithoutControllerRequirement, "ignore-definition-without-controller-version", c.IgnoreDefinitionWithoutControllerRequirement, "If true, trait/component/workflowstep definition controller will not process the definition without 'definition.oam.dev/controller-version-require' annotation")
|
||||
}
|
||||
|
||||
@@ -95,7 +95,6 @@ type Reconciler struct {
|
||||
type options struct {
|
||||
appRevisionLimit int
|
||||
concurrentReconciles int
|
||||
disableStatusUpdate bool
|
||||
ignoreAppNoCtrlReq bool
|
||||
controllerVersion string
|
||||
}
|
||||
@@ -141,7 +140,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
|
||||
logCtx.AddTag("publish_version", app.GetAnnotations()[oam.AnnotationPublishVersion])
|
||||
|
||||
appParser := appfile.NewApplicationParser(r.Client, r.pd)
|
||||
handler, err := NewAppHandler(logCtx, r, app, appParser)
|
||||
handler, err := NewAppHandler(logCtx, r, app)
|
||||
if err != nil {
|
||||
return r.endWithNegativeCondition(logCtx, app, condition.ReconcileError(err), common.ApplicationStarting)
|
||||
}
|
||||
@@ -179,14 +178,14 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
|
||||
app.Status.SetConditions(condition.ReadyCondition("Revision"))
|
||||
r.Recorder.Event(app, event.Normal(velatypes.ReasonRevisoned, velatypes.MessageRevisioned))
|
||||
|
||||
if err := handler.UpdateAppLatestRevisionStatus(logCtx); err != nil {
|
||||
if err := handler.UpdateAppLatestRevisionStatus(logCtx, r.patchStatus); err != nil {
|
||||
logCtx.Error(err, "Failed to update application status")
|
||||
return r.endWithNegativeCondition(logCtx, app, condition.ReconcileError(err), common.ApplicationRendering)
|
||||
}
|
||||
logCtx.Info("Successfully apply application revision")
|
||||
|
||||
if err := handler.ApplyPolicies(logCtx, appFile); err != nil {
|
||||
logCtx.Error(err, "[Handle ApplyPolicies]")
|
||||
logCtx.Error(err, "[handle ApplyPolicies]")
|
||||
r.Recorder.Event(app, event.Warning(velatypes.ReasonFailedApply, err))
|
||||
return r.endWithNegativeCondition(logCtx, app, condition.ErrorCondition(common.PolicyCondition.String(), errors.WithMessage(err, "ApplyPolices")), common.ApplicationPolicyGenerating)
|
||||
}
|
||||
@@ -258,7 +257,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
|
||||
}
|
||||
|
||||
var phase = common.ApplicationRunning
|
||||
if !hasHealthCheckPolicy(appFile.PolicyWorkloads) {
|
||||
if !hasHealthCheckPolicy(appFile.ParsedPolicies) {
|
||||
app.Status.Services = handler.services
|
||||
if !isHealthy(handler.services) {
|
||||
phase = common.ApplicationUnhealthy
|
||||
@@ -440,23 +439,26 @@ func (r *Reconciler) endWithNegativeCondition(ctx context.Context, app *v1beta1.
|
||||
return r.result(fmt.Errorf("object level reconcile error, type: %q, msg: %q", string(condition.Type), condition.Message)).ret()
|
||||
}
|
||||
|
||||
// Application status can be updated by two methods: patch and update.
|
||||
type method int
|
||||
|
||||
const (
|
||||
patch = iota
|
||||
update
|
||||
)
|
||||
|
||||
type statusPatcher func(ctx context.Context, app *v1beta1.Application, phase common.ApplicationPhase) error
|
||||
|
||||
func (r *Reconciler) patchStatus(ctx context.Context, app *v1beta1.Application, phase common.ApplicationPhase) error {
|
||||
app.Status.Phase = phase
|
||||
updateObservedGeneration(app)
|
||||
if oldApp, ok := originalAppFrom(ctx); ok && oldApp != nil && equality.Semantic.DeepEqual(oldApp.Status, app.Status) {
|
||||
return nil
|
||||
}
|
||||
ctx, cancel := ctrlrec.NewReconcileTerminationContext(ctx)
|
||||
defer cancel()
|
||||
if err := r.Status().Patch(ctx, app, client.Merge); err != nil {
|
||||
// set to -1 to re-run workflow if status is failed to patch
|
||||
executor.StepStatusCache.Store(fmt.Sprintf("%s-%s", app.Name, app.Namespace), -1)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return r.writeStatusByMethod(ctx, patch, app, phase)
|
||||
}
|
||||
|
||||
func (r *Reconciler) updateStatus(ctx context.Context, app *v1beta1.Application, phase common.ApplicationPhase) error {
|
||||
return r.writeStatusByMethod(ctx, update, app, phase)
|
||||
}
|
||||
|
||||
func (r *Reconciler) writeStatusByMethod(ctx context.Context, method method, app *v1beta1.Application, phase common.ApplicationPhase) error {
|
||||
// pre-check if the status is changed
|
||||
app.Status.Phase = phase
|
||||
updateObservedGeneration(app)
|
||||
if oldApp, ok := originalAppFrom(ctx); ok && oldApp != nil && equality.Semantic.DeepEqual(oldApp.Status, app.Status) {
|
||||
@@ -464,15 +466,17 @@ func (r *Reconciler) updateStatus(ctx context.Context, app *v1beta1.Application,
|
||||
}
|
||||
ctx, cancel := ctrlrec.NewReconcileTerminationContext(ctx)
|
||||
defer cancel()
|
||||
if !r.disableStatusUpdate {
|
||||
return r.Status().Update(ctx, app)
|
||||
var f func() error
|
||||
switch method {
|
||||
case patch:
|
||||
f = func() error { return r.Status().Patch(ctx, app, client.Merge) }
|
||||
case update:
|
||||
f = func() error { return r.Status().Update(ctx, app) }
|
||||
default:
|
||||
// Should never happen
|
||||
panic("unknown method")
|
||||
}
|
||||
obj, err := app.Unstructured()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := r.Status().Update(ctx, obj); err != nil {
|
||||
// set to -1 to re-run workflow if status is failed to update
|
||||
if err := f(); err != nil {
|
||||
executor.StepStatusCache.Store(fmt.Sprintf("%s-%s", app.Name, app.Namespace), -1)
|
||||
return err
|
||||
}
|
||||
@@ -498,7 +502,7 @@ func (r *Reconciler) doWorkflowFinish(logCtx monitorContext.Context, app *v1beta
|
||||
logCtx.Info("Application manifests has applied by workflow successfully")
|
||||
}
|
||||
|
||||
func hasHealthCheckPolicy(policies []*appfile.Workload) bool {
|
||||
func hasHealthCheckPolicy(policies []*appfile.Component) bool {
|
||||
for _, p := range policies {
|
||||
if p.FullTemplate != nil && p.FullTemplate.PolicyDefinition != nil &&
|
||||
p.FullTemplate.PolicyDefinition.Spec.ManageHealthCheck {
|
||||
@@ -648,7 +652,6 @@ func timeReconcile(app *v1beta1.Application) func() {
|
||||
|
||||
func parseOptions(args core.Args) options {
|
||||
return options{
|
||||
disableStatusUpdate: args.EnableCompatibility,
|
||||
appRevisionLimit: args.AppRevisionLimit,
|
||||
concurrentReconciles: args.ConcurrentReconciles,
|
||||
ignoreAppNoCtrlReq: args.IgnoreAppWithoutControllerRequirement,
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"github.com/kubevela/workflow/pkg/cue/packages"
|
||||
"github.com/pkg/errors"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
kerrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
@@ -45,7 +46,9 @@ import (
|
||||
|
||||
// AppHandler handles application reconcile
|
||||
type AppHandler struct {
|
||||
r *Reconciler
|
||||
client.Client
|
||||
pd *packages.PackageDiscover
|
||||
|
||||
app *v1beta1.Application
|
||||
currentAppRev *v1beta1.ApplicationRevision
|
||||
latestAppRev *v1beta1.ApplicationRevision
|
||||
@@ -57,13 +60,12 @@ type AppHandler struct {
|
||||
services []common.ApplicationComponentStatus
|
||||
appliedResources []common.ClusterObjectReference
|
||||
deletedResources []common.ClusterObjectReference
|
||||
parser *appfile.Parser
|
||||
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
// NewAppHandler create new app handler
|
||||
func NewAppHandler(ctx context.Context, r *Reconciler, app *v1beta1.Application, parser *appfile.Parser) (*AppHandler, error) {
|
||||
func NewAppHandler(ctx context.Context, r *Reconciler, app *v1beta1.Application) (*AppHandler, error) {
|
||||
if ctx, ok := ctx.(monitorContext.Context); ok {
|
||||
subCtx := ctx.Fork("create-app-handler", monitorContext.DurationMetric(func(v float64) {
|
||||
metrics.AppReconcileStageDurationHistogram.WithLabelValues("create-app-handler").Observe(v)
|
||||
@@ -75,10 +77,10 @@ func NewAppHandler(ctx context.Context, r *Reconciler, app *v1beta1.Application,
|
||||
return nil, errors.Wrapf(err, "failed to create resourceKeeper")
|
||||
}
|
||||
return &AppHandler{
|
||||
r: r,
|
||||
Client: r.Client,
|
||||
pd: r.pd,
|
||||
app: app,
|
||||
resourceKeeper: resourceHandler,
|
||||
parser: parser,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -227,13 +229,13 @@ func (h *AppHandler) ProduceArtifacts(ctx context.Context, comps []*types.Compon
|
||||
}
|
||||
|
||||
// collectTraitHealthStatus collect trait health status
|
||||
func (h *AppHandler) collectTraitHealthStatus(wl *appfile.Workload, tr *appfile.Trait, appRev *v1beta1.ApplicationRevision, overrideNamespace string) (common.ApplicationTraitStatus, []*unstructured.Unstructured, error) {
|
||||
func (h *AppHandler) collectTraitHealthStatus(comp *appfile.Component, tr *appfile.Trait, appRev *v1beta1.ApplicationRevision, overrideNamespace string) (common.ApplicationTraitStatus, []*unstructured.Unstructured, error) {
|
||||
defer func(clusterName string) {
|
||||
wl.Ctx.SetCtx(pkgmulticluster.WithCluster(wl.Ctx.GetCtx(), clusterName))
|
||||
}(multicluster.ClusterNameInContext(wl.Ctx.GetCtx()))
|
||||
comp.Ctx.SetCtx(pkgmulticluster.WithCluster(comp.Ctx.GetCtx(), clusterName))
|
||||
}(multicluster.ClusterNameInContext(comp.Ctx.GetCtx()))
|
||||
|
||||
var (
|
||||
pCtx = wl.Ctx
|
||||
pCtx = comp.Ctx
|
||||
appName = appRev.Spec.Application.Name
|
||||
traitStatus = common.ApplicationTraitStatus{
|
||||
Type: tr.Name,
|
||||
@@ -247,57 +249,57 @@ func (h *AppHandler) collectTraitHealthStatus(wl *appfile.Workload, tr *appfile.
|
||||
pCtx.SetCtx(pkgmulticluster.WithCluster(pCtx.GetCtx(), pkgmulticluster.Local))
|
||||
}
|
||||
_accessor := util.NewApplicationResourceNamespaceAccessor(h.app.Namespace, traitOverrideNamespace)
|
||||
templateContext, err := tr.GetTemplateContext(pCtx, h.r.Client, _accessor)
|
||||
templateContext, err := tr.GetTemplateContext(pCtx, h.Client, _accessor)
|
||||
if err != nil {
|
||||
return common.ApplicationTraitStatus{}, nil, errors.WithMessagef(err, "app=%s, comp=%s, trait=%s, get template context error", appName, wl.Name, tr.Name)
|
||||
return common.ApplicationTraitStatus{}, nil, errors.WithMessagef(err, "app=%s, comp=%s, trait=%s, get template context error", appName, comp.Name, tr.Name)
|
||||
}
|
||||
if ok, err := tr.EvalHealth(templateContext); !ok || err != nil {
|
||||
traitStatus.Healthy = false
|
||||
}
|
||||
traitStatus.Message, err = tr.EvalStatus(templateContext)
|
||||
if err != nil {
|
||||
return common.ApplicationTraitStatus{}, nil, errors.WithMessagef(err, "app=%s, comp=%s, trait=%s, evaluate status message error", appName, wl.Name, tr.Name)
|
||||
return common.ApplicationTraitStatus{}, nil, errors.WithMessagef(err, "app=%s, comp=%s, trait=%s, evaluate status message error", appName, comp.Name, tr.Name)
|
||||
}
|
||||
return traitStatus, extractOutputs(templateContext), nil
|
||||
}
|
||||
|
||||
// collectWorkloadHealthStatus collect workload health status
|
||||
func (h *AppHandler) collectWorkloadHealthStatus(ctx context.Context, wl *appfile.Workload, appRev *v1beta1.ApplicationRevision, status *common.ApplicationComponentStatus, accessor util.NamespaceAccessor) (bool, *unstructured.Unstructured, []*unstructured.Unstructured, error) {
|
||||
func (h *AppHandler) collectWorkloadHealthStatus(ctx context.Context, comp *appfile.Component, appRev *v1beta1.ApplicationRevision, status *common.ApplicationComponentStatus, accessor util.NamespaceAccessor) (bool, *unstructured.Unstructured, []*unstructured.Unstructured, error) {
|
||||
var output *unstructured.Unstructured
|
||||
var outputs []*unstructured.Unstructured
|
||||
var (
|
||||
appName = appRev.Spec.Application.Name
|
||||
isHealth = true
|
||||
)
|
||||
if wl.CapabilityCategory == types.TerraformCategory {
|
||||
if comp.CapabilityCategory == types.TerraformCategory {
|
||||
var configuration terraforv1beta2.Configuration
|
||||
if err := h.r.Client.Get(ctx, client.ObjectKey{Name: wl.Name, Namespace: accessor.Namespace()}, &configuration); err != nil {
|
||||
if err := h.Client.Get(ctx, client.ObjectKey{Name: comp.Name, Namespace: accessor.Namespace()}, &configuration); err != nil {
|
||||
if kerrors.IsNotFound(err) {
|
||||
var legacyConfiguration terraforv1beta1.Configuration
|
||||
if err := h.r.Client.Get(ctx, client.ObjectKey{Name: wl.Name, Namespace: accessor.Namespace()}, &legacyConfiguration); err != nil {
|
||||
return false, nil, nil, errors.WithMessagef(err, "app=%s, comp=%s, check health error", appName, wl.Name)
|
||||
if err := h.Client.Get(ctx, client.ObjectKey{Name: comp.Name, Namespace: accessor.Namespace()}, &legacyConfiguration); err != nil {
|
||||
return false, nil, nil, errors.WithMessagef(err, "app=%s, comp=%s, check health error", appName, comp.Name)
|
||||
}
|
||||
isHealth = setStatus(status, legacyConfiguration.Status.ObservedGeneration, legacyConfiguration.Generation,
|
||||
legacyConfiguration.GetLabels(), appRev.Name, legacyConfiguration.Status.Apply.State, legacyConfiguration.Status.Apply.Message)
|
||||
} else {
|
||||
return false, nil, nil, errors.WithMessagef(err, "app=%s, comp=%s, check health error", appName, wl.Name)
|
||||
return false, nil, nil, errors.WithMessagef(err, "app=%s, comp=%s, check health error", appName, comp.Name)
|
||||
}
|
||||
} else {
|
||||
isHealth = setStatus(status, configuration.Status.ObservedGeneration, configuration.Generation, configuration.GetLabels(),
|
||||
appRev.Name, configuration.Status.Apply.State, configuration.Status.Apply.Message)
|
||||
}
|
||||
} else {
|
||||
templateContext, err := wl.GetTemplateContext(wl.Ctx, h.r.Client, accessor)
|
||||
templateContext, err := comp.GetTemplateContext(comp.Ctx, h.Client, accessor)
|
||||
if err != nil {
|
||||
return false, nil, nil, errors.WithMessagef(err, "app=%s, comp=%s, get template context error", appName, wl.Name)
|
||||
return false, nil, nil, errors.WithMessagef(err, "app=%s, comp=%s, get template context error", appName, comp.Name)
|
||||
}
|
||||
if ok, err := wl.EvalHealth(templateContext); !ok || err != nil {
|
||||
if ok, err := comp.EvalHealth(templateContext); !ok || err != nil {
|
||||
isHealth = false
|
||||
}
|
||||
status.Healthy = isHealth
|
||||
status.Message, err = wl.EvalStatus(templateContext)
|
||||
status.Message, err = comp.EvalStatus(templateContext)
|
||||
if err != nil {
|
||||
return false, nil, nil, errors.WithMessagef(err, "app=%s, comp=%s, evaluate workload status message error", appName, wl.Name)
|
||||
return false, nil, nil, errors.WithMessagef(err, "app=%s, comp=%s, evaluate workload status message error", appName, comp.Name)
|
||||
}
|
||||
output, outputs = extractOutputAndOutputs(templateContext)
|
||||
}
|
||||
@@ -306,14 +308,14 @@ func (h *AppHandler) collectWorkloadHealthStatus(ctx context.Context, wl *appfil
|
||||
|
||||
// nolint
|
||||
// collectHealthStatus will collect health status of component, including component itself and traits.
|
||||
func (h *AppHandler) collectHealthStatus(ctx context.Context, wl *appfile.Workload, appRev *v1beta1.ApplicationRevision, overrideNamespace string, skipWorkload bool, traitFilters ...TraitFilter) (*common.ApplicationComponentStatus, *unstructured.Unstructured, []*unstructured.Unstructured, bool, error) {
|
||||
func (h *AppHandler) collectHealthStatus(ctx context.Context, comp *appfile.Component, appRev *v1beta1.ApplicationRevision, overrideNamespace string, skipWorkload bool, traitFilters ...TraitFilter) (*common.ApplicationComponentStatus, *unstructured.Unstructured, []*unstructured.Unstructured, bool, error) {
|
||||
output := new(unstructured.Unstructured)
|
||||
outputs := make([]*unstructured.Unstructured, 0)
|
||||
accessor := util.NewApplicationResourceNamespaceAccessor(h.app.Namespace, overrideNamespace)
|
||||
var (
|
||||
status = common.ApplicationComponentStatus{
|
||||
Name: wl.Name,
|
||||
WorkloadDefinition: wl.FullTemplate.Reference.Definition,
|
||||
Name: comp.Name,
|
||||
WorkloadDefinition: comp.FullTemplate.Reference.Definition,
|
||||
Healthy: true,
|
||||
Namespace: accessor.Namespace(),
|
||||
Cluster: multicluster.ClusterNameInContext(ctx),
|
||||
@@ -324,7 +326,7 @@ func (h *AppHandler) collectHealthStatus(ctx context.Context, wl *appfile.Worklo
|
||||
|
||||
status = h.getServiceStatus(status)
|
||||
if !skipWorkload {
|
||||
isHealth, output, outputs, err = h.collectWorkloadHealthStatus(ctx, wl, appRev, &status, accessor)
|
||||
isHealth, output, outputs, err = h.collectWorkloadHealthStatus(ctx, comp, appRev, &status, accessor)
|
||||
if err != nil {
|
||||
return nil, nil, nil, false, err
|
||||
}
|
||||
@@ -332,7 +334,7 @@ func (h *AppHandler) collectHealthStatus(ctx context.Context, wl *appfile.Worklo
|
||||
|
||||
var traitStatusList []common.ApplicationTraitStatus
|
||||
collectNext:
|
||||
for _, tr := range wl.Traits {
|
||||
for _, tr := range comp.Traits {
|
||||
for _, filter := range traitFilters {
|
||||
// If filtered out by one of the filters
|
||||
if filter(*tr) {
|
||||
@@ -340,7 +342,7 @@ collectNext:
|
||||
}
|
||||
}
|
||||
|
||||
traitStatus, _outputs, err := h.collectTraitHealthStatus(wl, tr, appRev, overrideNamespace)
|
||||
traitStatus, _outputs, err := h.collectTraitHealthStatus(comp, tr, appRev, overrideNamespace)
|
||||
if err != nil {
|
||||
return nil, nil, nil, false, err
|
||||
}
|
||||
@@ -389,6 +391,7 @@ func setStatus(status *common.ApplicationComponentStatus, observedGeneration, ge
|
||||
}
|
||||
|
||||
// ApplyPolicies will render policies into manifests from appfile and dispatch them
|
||||
// Note the builtin policy like apply-once, shared-resource, etc. is not handled here.
|
||||
func (h *AppHandler) ApplyPolicies(ctx context.Context, af *appfile.Appfile) error {
|
||||
if ctx, ok := ctx.(monitorContext.Context); ok {
|
||||
subCtx := ctx.Fork("apply-policies", monitorContext.DurationMetric(func(v float64) {
|
||||
|
||||
@@ -224,7 +224,7 @@ var _ = Describe("Test deleter resource", func() {
|
||||
},
|
||||
},
|
||||
}
|
||||
h, err := NewAppHandler(ctx, reconciler, &v1beta1.Application{ObjectMeta: metav1.ObjectMeta{Name: "example", Namespace: "default"}}, nil)
|
||||
h, err := NewAppHandler(ctx, reconciler, &v1beta1.Application{ObjectMeta: metav1.ObjectMeta{Name: "example", Namespace: "default"}})
|
||||
Expect(err).Should(Succeed())
|
||||
h.appliedResources = appliedRsc
|
||||
Expect(h.Delete(ctx, "", common.WorkflowResourceCreator, &u))
|
||||
|
||||
@@ -18,47 +18,15 @@ package assemble
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
|
||||
"github.com/oam-dev/kubevela/apis/types"
|
||||
"github.com/oam-dev/kubevela/pkg/appfile"
|
||||
"github.com/oam-dev/kubevela/pkg/oam"
|
||||
"github.com/oam-dev/kubevela/pkg/oam/util"
|
||||
)
|
||||
|
||||
// NewAppManifests create a AppManifests
|
||||
func NewAppManifests(appRevision *v1beta1.ApplicationRevision, parser *appfile.Parser) *AppManifests {
|
||||
return &AppManifests{AppRevision: appRevision, parser: parser}
|
||||
}
|
||||
|
||||
// AppManifests contains configuration to assemble resources recorded in the ApplicationRevision.
|
||||
// 'Assemble' means expand Application(Component and Trait) into K8s resource and get them ready to go, to be emitted
|
||||
// into K8s
|
||||
type AppManifests struct {
|
||||
AppRevision *v1beta1.ApplicationRevision
|
||||
WorkloadOptions []WorkloadOption
|
||||
|
||||
componentManifests []*types.ComponentManifest
|
||||
appName string
|
||||
appNamespace string
|
||||
appLabels map[string]string
|
||||
appAnnotations map[string]string
|
||||
appOwnerRef *metav1.OwnerReference
|
||||
|
||||
assembledWorkloads map[string]*unstructured.Unstructured
|
||||
assembledTraits map[string][]*unstructured.Unstructured
|
||||
// key is workload reference, values are the references of scopes the workload belongs to
|
||||
skipWorkloadApplyComp map[string]bool
|
||||
|
||||
finalized bool
|
||||
err error
|
||||
|
||||
parser *appfile.Parser
|
||||
}
|
||||
|
||||
// WorkloadOption will be applied to each workloads AFTER it has been assembled by generic rules shown below:
|
||||
// 1) use component name as workload name
|
||||
// 2) use application namespace as workload namespace if unspecified
|
||||
@@ -75,78 +43,6 @@ type WorkloadOption interface {
|
||||
ApplyToWorkload(*unstructured.Unstructured, *v1beta1.ComponentDefinition, []*unstructured.Unstructured) error
|
||||
}
|
||||
|
||||
// WithWorkloadOption add a WorkloadOption to plug in custom logic applied to each workload
|
||||
func (am *AppManifests) WithWorkloadOption(wo WorkloadOption) *AppManifests {
|
||||
if am.WorkloadOptions == nil {
|
||||
am.WorkloadOptions = make([]WorkloadOption, 0)
|
||||
}
|
||||
am.WorkloadOptions = append(am.WorkloadOptions, wo)
|
||||
return am
|
||||
}
|
||||
|
||||
// WithComponentManifests set component manifests with the given one
|
||||
func (am *AppManifests) WithComponentManifests(componentManifests []*types.ComponentManifest) *AppManifests {
|
||||
am.componentManifests = componentManifests
|
||||
return am
|
||||
}
|
||||
|
||||
// AssembledManifests do assemble and merge all assembled resources(except referenced scopes) into one array
|
||||
// The result guarantee the order of resources as defined in application originally.
|
||||
// If it contains more than one component, the resources are well-orderred and also grouped.
|
||||
// For example, if app = comp1 (wl1 + trait1 + trait2) + comp2 (wl2 + trait3 +trait4),
|
||||
// the result is [wl1, trait1, trait2, wl2, trait3, trait4]
|
||||
func (am *AppManifests) AssembledManifests() ([]*unstructured.Unstructured, error) {
|
||||
if !am.finalized {
|
||||
am.assemble()
|
||||
}
|
||||
if am.err != nil {
|
||||
return nil, am.err
|
||||
}
|
||||
r := make([]*unstructured.Unstructured, 0)
|
||||
for compName, wl := range am.assembledWorkloads {
|
||||
skipApplyWorkload := false
|
||||
ts := am.assembledTraits[compName]
|
||||
for _, t := range ts {
|
||||
r = append(r, t.DeepCopy())
|
||||
if v := t.GetLabels()[oam.LabelManageWorkloadTrait]; v == "true" {
|
||||
skipApplyWorkload = true
|
||||
}
|
||||
}
|
||||
if !skipApplyWorkload {
|
||||
r = append(r, wl.DeepCopy())
|
||||
} else {
|
||||
klog.InfoS("assemble meet a managedByTrait workload, so skip apply it",
|
||||
"namespace", am.AppRevision.Namespace, "appRev", am.AppRevision.Name)
|
||||
}
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// GroupAssembledManifests do assemble and return all resources grouped by components
|
||||
func (am *AppManifests) GroupAssembledManifests() (
|
||||
map[string]*unstructured.Unstructured,
|
||||
map[string][]*unstructured.Unstructured,
|
||||
error) {
|
||||
if !am.finalized {
|
||||
am.assemble()
|
||||
}
|
||||
if am.err != nil {
|
||||
return nil, nil, am.err
|
||||
}
|
||||
workloads := make(map[string]*unstructured.Unstructured)
|
||||
for k, wl := range am.assembledWorkloads {
|
||||
workloads[k] = wl.DeepCopy()
|
||||
}
|
||||
traits := make(map[string][]*unstructured.Unstructured)
|
||||
for k, ts := range am.assembledTraits {
|
||||
traits[k] = make([]*unstructured.Unstructured, len(ts))
|
||||
for i, t := range ts {
|
||||
traits[k][i] = t.DeepCopy()
|
||||
}
|
||||
}
|
||||
return workloads, traits, nil
|
||||
}
|
||||
|
||||
// checkAutoDetectComponent will check if the standardWorkload is empty,
|
||||
// currently only Helm-based component is possible to be auto-detected
|
||||
// TODO implement auto-detect mechanism
|
||||
@@ -154,35 +50,6 @@ func checkAutoDetectComponent(wl *unstructured.Unstructured) bool {
|
||||
return wl == nil || (len(wl.GetAPIVersion()) == 0 && len(wl.GetKind()) == 0)
|
||||
}
|
||||
|
||||
func (am *AppManifests) assemble() {
|
||||
if err := am.complete(); err != nil {
|
||||
am.finalizeAssemble(err)
|
||||
return
|
||||
}
|
||||
|
||||
klog.InfoS("Assemble manifests for application", "name", am.appName, "revision", am.AppRevision.GetName())
|
||||
if err := am.validate(); err != nil {
|
||||
am.finalizeAssemble(err)
|
||||
return
|
||||
}
|
||||
for _, comp := range am.componentManifests {
|
||||
klog.InfoS("Assemble manifests for component", "name", comp.Name)
|
||||
wl, traits, err := PrepareBeforeApply(comp, am.AppRevision, am.WorkloadOptions)
|
||||
if err != nil {
|
||||
am.finalizeAssemble(err)
|
||||
return
|
||||
}
|
||||
if wl == nil {
|
||||
klog.Warningf("component without specify workloadDef can not attach traits currently")
|
||||
continue
|
||||
}
|
||||
|
||||
am.assembledWorkloads[comp.Name] = wl
|
||||
am.assembledTraits[comp.Name] = traits
|
||||
}
|
||||
am.finalizeAssemble(nil)
|
||||
}
|
||||
|
||||
// PrepareBeforeApply will prepare for some necessary info before apply
|
||||
func PrepareBeforeApply(comp *types.ComponentManifest, appRev *v1beta1.ApplicationRevision, workloadOpt []WorkloadOption) (*unstructured.Unstructured, []*unstructured.Unstructured, error) {
|
||||
if checkAutoDetectComponent(comp.StandardWorkload) {
|
||||
@@ -211,55 +78,6 @@ func PrepareBeforeApply(comp *types.ComponentManifest, appRev *v1beta1.Applicati
|
||||
return wl, assembledTraits, nil
|
||||
}
|
||||
|
||||
func (am *AppManifests) complete() error {
|
||||
if len(am.componentManifests) == 0 {
|
||||
var err error
|
||||
af, err := am.parser.GenerateAppFileFromRevision(am.AppRevision)
|
||||
if err != nil {
|
||||
return errors.WithMessage(err, "fail to generate appfile from revision for app manifests complete")
|
||||
}
|
||||
am.componentManifests, err = af.GenerateComponentManifests()
|
||||
if err != nil {
|
||||
return errors.WithMessage(err, "fail to complete manifests as generate from app revision failed")
|
||||
}
|
||||
}
|
||||
am.appNamespace = am.AppRevision.GetNamespace()
|
||||
am.appLabels = am.AppRevision.GetLabels()
|
||||
am.appName = am.AppRevision.GetLabels()[oam.LabelAppName]
|
||||
am.appAnnotations = am.AppRevision.GetAnnotations()
|
||||
am.appOwnerRef = metav1.GetControllerOf(am.AppRevision)
|
||||
|
||||
am.assembledWorkloads = make(map[string]*unstructured.Unstructured)
|
||||
am.assembledTraits = make(map[string][]*unstructured.Unstructured)
|
||||
am.skipWorkloadApplyComp = make(map[string]bool)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (am *AppManifests) finalizeAssemble(err error) {
|
||||
am.finalized = true
|
||||
if err == nil {
|
||||
klog.InfoS("Successfully assemble manifests for application", "name", am.appName, "revision", am.AppRevision.GetName(), "namespace", am.appNamespace)
|
||||
return
|
||||
}
|
||||
klog.ErrorS(err, "Failed assembling manifests for application", "name", am.appName, "revision", am.AppRevision.GetName())
|
||||
am.err = errors.WithMessagef(err, "cannot assemble resources' manifests for application %q", am.appName)
|
||||
}
|
||||
|
||||
// AssembleOptions is highly coulped with AppRevision, should check the AppRevision provides all info
|
||||
// required by AssembleOptions
|
||||
func (am *AppManifests) validate() error {
|
||||
if am.appOwnerRef == nil {
|
||||
return errors.New("AppRevision must have an Application as owner")
|
||||
}
|
||||
if len(am.AppRevision.Labels[oam.LabelAppName]) == 0 {
|
||||
return errors.New("AppRevision must have app name in the label")
|
||||
}
|
||||
if len(am.AppRevision.Labels[oam.LabelAppRevisionHash]) == 0 {
|
||||
return errors.New("AppRevision must have revision hash in the label")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func assembleWorkload(compName string, wl *unstructured.Unstructured,
|
||||
labels map[string]string, resources []*unstructured.Unstructured, appRev *v1beta1.ApplicationRevision, wop []WorkloadOption) (*unstructured.Unstructured, error) {
|
||||
// use component name as workload name if workload name is not specified
|
||||
|
||||
@@ -15,99 +15,3 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
package assemble
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
|
||||
"github.com/oam-dev/kubevela/pkg/oam"
|
||||
)
|
||||
|
||||
var _ = Describe("Test Assemble Options", func() {
|
||||
It("test assemble", func() {
|
||||
var (
|
||||
compName = "test-comp"
|
||||
namespace = "default"
|
||||
)
|
||||
|
||||
appRev := &v1beta1.ApplicationRevision{}
|
||||
b, err := os.ReadFile("./testdata/apprevision.yaml")
|
||||
/* appRevision test data is generated based on below application
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: test-assemble
|
||||
spec:
|
||||
components:
|
||||
- name: test-comp
|
||||
type: webservice
|
||||
properties:
|
||||
image: crccheck/hello-world
|
||||
port: 8000
|
||||
traits:
|
||||
- type: ingress
|
||||
properties:
|
||||
domain: localhost
|
||||
http:
|
||||
"/": 8000
|
||||
*/
|
||||
Expect(err).Should(BeNil())
|
||||
err = yaml.Unmarshal(b, appRev)
|
||||
Expect(err).Should(BeNil())
|
||||
|
||||
ao := NewAppManifests(appRev, appParser)
|
||||
workloads, traits, err := ao.GroupAssembledManifests()
|
||||
Expect(err).Should(BeNil())
|
||||
|
||||
By("Verify amount of result resources")
|
||||
allResources, err := ao.AssembledManifests()
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(len(allResources)).Should(Equal(3))
|
||||
|
||||
By("Verify amount of result grouped resources")
|
||||
Expect(len(workloads)).Should(Equal(1))
|
||||
Expect(len(traits[compName])).Should(Equal(2))
|
||||
|
||||
By("Verify workload metadata (name, namespace, labels, annotations, ownerRef)")
|
||||
wl := workloads[compName]
|
||||
Expect(wl.GetName()).Should(Equal(compName))
|
||||
Expect(wl.GetNamespace()).Should(Equal(namespace))
|
||||
labels := wl.GetLabels()
|
||||
labelKeys := make([]string, 0, len(labels))
|
||||
for k := range labels {
|
||||
labelKeys = append(labelKeys, k)
|
||||
}
|
||||
Expect(labelKeys).Should(ContainElements(
|
||||
oam.LabelAppName,
|
||||
oam.LabelAppRevision,
|
||||
oam.LabelAppRevisionHash,
|
||||
oam.LabelAppComponent,
|
||||
oam.LabelAppComponentRevision,
|
||||
oam.WorkloadTypeLabel,
|
||||
oam.LabelOAMResourceType))
|
||||
Expect(len(wl.GetAnnotations())).Should(Equal(1))
|
||||
|
||||
By("Verify trait metadata (name, namespace, labels, annotations, ownerRef)")
|
||||
trait := traits[compName][0]
|
||||
Expect(trait.GetName()).Should(ContainSubstring(compName))
|
||||
Expect(trait.GetNamespace()).Should(Equal(namespace))
|
||||
labels = trait.GetLabels()
|
||||
labelKeys = make([]string, 0, len(labels))
|
||||
for k := range labels {
|
||||
labelKeys = append(labelKeys, k)
|
||||
}
|
||||
Expect(labelKeys).Should(ContainElements(
|
||||
oam.LabelAppName,
|
||||
oam.LabelAppRevision,
|
||||
oam.LabelAppRevisionHash,
|
||||
oam.LabelAppComponent,
|
||||
oam.LabelAppComponentRevision,
|
||||
oam.TraitTypeLabel,
|
||||
oam.LabelOAMResourceType))
|
||||
Expect(len(wl.GetAnnotations())).Should(Equal(1))
|
||||
})
|
||||
})
|
||||
|
||||
@@ -108,8 +108,8 @@ func ByTraitType(readyTraits, checkTraits []*unstructured.Unstructured) TraitFil
|
||||
|
||||
// manifestDispatcher is a manifest dispatcher
|
||||
type manifestDispatcher struct {
|
||||
run func(ctx context.Context, wl *appfile.Workload, appRev *v1beta1.ApplicationRevision, clusterName string) (bool, error)
|
||||
healthCheck func(ctx context.Context, wl *appfile.Workload, appRev *v1beta1.ApplicationRevision) (bool, error)
|
||||
run func(ctx context.Context, c *appfile.Component, appRev *v1beta1.ApplicationRevision, clusterName string) (bool, error)
|
||||
healthCheck func(ctx context.Context, c *appfile.Component, appRev *v1beta1.ApplicationRevision) (bool, error)
|
||||
}
|
||||
|
||||
func (h *AppHandler) generateDispatcher(appRev *v1beta1.ApplicationRevision, readyWorkload *unstructured.Unstructured, readyTraits []*unstructured.Unstructured, overrideNamespace string) ([]*manifestDispatcher, error) {
|
||||
@@ -124,25 +124,25 @@ func (h *AppHandler) generateDispatcher(appRev *v1beta1.ApplicationRevision, rea
|
||||
}
|
||||
|
||||
dispatcher := new(manifestDispatcher)
|
||||
dispatcher.healthCheck = func(ctx context.Context, wl *appfile.Workload, appRev *v1beta1.ApplicationRevision) (bool, error) {
|
||||
skipWorkload, manifests := assembleManifestFn(wl.SkipApplyWorkload)
|
||||
dispatcher.healthCheck = func(ctx context.Context, comp *appfile.Component, appRev *v1beta1.ApplicationRevision) (bool, error) {
|
||||
skipWorkload, manifests := assembleManifestFn(comp.SkipApplyWorkload)
|
||||
if !h.resourceKeeper.ContainsResources(manifests) {
|
||||
return false, nil
|
||||
}
|
||||
_, _, _, isHealth, err := h.collectHealthStatus(ctx, wl, appRev, options.OverrideNamespace, skipWorkload,
|
||||
_, _, _, isHealth, err := h.collectHealthStatus(ctx, comp, appRev, options.OverrideNamespace, skipWorkload,
|
||||
ByTraitType(readyTraits, options.Traits))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return isHealth, nil
|
||||
}
|
||||
dispatcher.run = func(ctx context.Context, wl *appfile.Workload, appRev *v1beta1.ApplicationRevision, clusterName string) (bool, error) {
|
||||
skipWorkload, dispatchManifests := assembleManifestFn(wl.SkipApplyWorkload)
|
||||
if isHealth, err := dispatcher.healthCheck(ctx, wl, appRev); !isHealth || err != nil {
|
||||
dispatcher.run = func(ctx context.Context, comp *appfile.Component, appRev *v1beta1.ApplicationRevision, clusterName string) (bool, error) {
|
||||
skipWorkload, dispatchManifests := assembleManifestFn(comp.SkipApplyWorkload)
|
||||
if isHealth, err := dispatcher.healthCheck(ctx, comp, appRev); !isHealth || err != nil {
|
||||
if err := h.Dispatch(ctx, clusterName, common.WorkflowResourceCreator, dispatchManifests...); err != nil {
|
||||
return false, errors.WithMessage(err, "Dispatch")
|
||||
}
|
||||
status, _, _, isHealth, err := h.collectHealthStatus(ctx, wl, appRev, options.OverrideNamespace, skipWorkload,
|
||||
status, _, _, isHealth, err := h.collectHealthStatus(ctx, comp, appRev, options.OverrideNamespace, skipWorkload,
|
||||
ByTraitType(readyTraits, options.Traits))
|
||||
if err != nil {
|
||||
return false, errors.WithMessage(err, "CollectHealthStatus")
|
||||
@@ -179,7 +179,7 @@ func (h *AppHandler) generateDispatcher(appRev *v1beta1.ApplicationRevision, rea
|
||||
traitType = splitName
|
||||
}
|
||||
}
|
||||
stageType, err = getTraitDispatchStage(h.r.Client, traitType, appRev)
|
||||
stageType, err = getTraitDispatchStage(h.Client, traitType, appRev)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -95,37 +95,37 @@ func (h *AppHandler) GenerateApplicationSteps(ctx monitorContext.Context,
|
||||
oam.LabelAppNamespace: app.Namespace,
|
||||
}
|
||||
handlerProviders := providers.NewProviders()
|
||||
kube.Install(handlerProviders, h.r.Client, appLabels, &kube.Handlers{
|
||||
kube.Install(handlerProviders, h.Client, appLabels, &kube.Handlers{
|
||||
Apply: h.Dispatch,
|
||||
Delete: h.Delete,
|
||||
})
|
||||
configprovider.Install(handlerProviders, h.r.Client, func(ctx context.Context, resources []*unstructured.Unstructured, applyOptions []apply.ApplyOption) error {
|
||||
configprovider.Install(handlerProviders, h.Client, func(ctx context.Context, resources []*unstructured.Unstructured, applyOptions []apply.ApplyOption) error {
|
||||
for _, res := range resources {
|
||||
res.SetLabels(util.MergeMapOverrideWithDst(res.GetLabels(), appLabels))
|
||||
}
|
||||
return h.resourceKeeper.Dispatch(ctx, resources, applyOptions)
|
||||
})
|
||||
oamProvider.Install(handlerProviders, app, af, h.r.Client, h.applyComponentFunc(
|
||||
oamProvider.Install(handlerProviders, app, af, h.Client, h.applyComponentFunc(
|
||||
appParser, appRev, af), h.renderComponentFunc(appParser, appRev, af))
|
||||
pCtx := velaprocess.NewContext(generateContextDataFromApp(app, appRev.Name))
|
||||
renderer := func(ctx context.Context, comp common.ApplicationComponent) (*appfile.Workload, error) {
|
||||
return appParser.ParseWorkloadFromRevisionAndClient(ctx, comp, appRev)
|
||||
renderer := func(ctx context.Context, comp common.ApplicationComponent) (*appfile.Component, error) {
|
||||
return appParser.ParseComponentFromRevisionAndClient(ctx, comp, appRev)
|
||||
}
|
||||
multiclusterProvider.Install(handlerProviders, h.r.Client, app, af,
|
||||
multiclusterProvider.Install(handlerProviders, h.Client, app, af,
|
||||
h.applyComponentFunc(appParser, appRev, af),
|
||||
h.checkComponentHealth(appParser, appRev, af),
|
||||
renderer)
|
||||
terraformProvider.Install(handlerProviders, app, renderer)
|
||||
query.Install(handlerProviders, h.r.Client, nil)
|
||||
query.Install(handlerProviders, h.Client, nil)
|
||||
|
||||
instance := generateWorkflowInstance(af, app)
|
||||
executor.InitializeWorkflowInstance(instance)
|
||||
runners, err := generator.GenerateRunners(ctx, instance, wfTypes.StepGeneratorOptions{
|
||||
Providers: handlerProviders,
|
||||
PackageDiscover: h.r.pd,
|
||||
PackageDiscover: h.pd,
|
||||
ProcessCtx: pCtx,
|
||||
TemplateLoader: template.NewWorkflowStepTemplateRevisionLoader(appRev, h.r.Client.RESTMapper()),
|
||||
Client: h.r.Client,
|
||||
TemplateLoader: template.NewWorkflowStepTemplateRevisionLoader(appRev, h.Client.RESTMapper()),
|
||||
Client: h.Client,
|
||||
StepConvertor: map[string]func(step workflowv1alpha1.WorkflowStep) (workflowv1alpha1.WorkflowStep, error){
|
||||
wfTypes.WorkflowStepTypeApplyComponent: func(lstep workflowv1alpha1.WorkflowStep) (workflowv1alpha1.WorkflowStep, error) {
|
||||
copierStep := lstep.DeepCopy()
|
||||
@@ -319,7 +319,7 @@ func (h *AppHandler) renderComponentFunc(appParser *appfile.Parser, appRev *v1be
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return renderComponentsAndTraits(h.r.Client, manifest, appRev, clusterName, overrideNamespace)
|
||||
return renderComponentsAndTraits(h.Client, manifest, appRev, clusterName, overrideNamespace)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,7 +335,7 @@ func (h *AppHandler) checkComponentHealth(appParser *appfile.Parser, appRev *v1b
|
||||
}
|
||||
wl.Ctx.SetCtx(auth.ContextWithUserInfo(ctx, h.app))
|
||||
|
||||
readyWorkload, readyTraits, err := renderComponentsAndTraits(h.r.Client, manifest, appRev, clusterName, overrideNamespace)
|
||||
readyWorkload, readyTraits, err := renderComponentsAndTraits(h.Client, manifest, appRev, clusterName, overrideNamespace)
|
||||
if err != nil {
|
||||
return false, nil, nil, err
|
||||
}
|
||||
@@ -378,7 +378,7 @@ func (h *AppHandler) applyComponentFunc(appParser *appfile.Parser, appRev *v1bet
|
||||
}
|
||||
wl.Ctx.SetCtx(auth.ContextWithUserInfo(ctx, h.app))
|
||||
|
||||
readyWorkload, readyTraits, err := renderComponentsAndTraits(h.r.Client, manifest, appRev, clusterName, overrideNamespace)
|
||||
readyWorkload, readyTraits, err := renderComponentsAndTraits(h.Client, manifest, appRev, clusterName, overrideNamespace)
|
||||
if err != nil {
|
||||
return nil, nil, false, err
|
||||
}
|
||||
@@ -414,7 +414,7 @@ func (h *AppHandler) applyComponentFunc(appParser *appfile.Parser, appRev *v1bet
|
||||
if DisableResourceApplyDoubleCheck {
|
||||
return readyWorkload, readyTraits, isHealth, nil
|
||||
}
|
||||
workload, traits, err := getComponentResources(auth.ContextWithUserInfo(ctx, h.app), manifest, wl.SkipApplyWorkload, h.r.Client)
|
||||
workload, traits, err := getComponentResources(auth.ContextWithUserInfo(ctx, h.app), manifest, wl.SkipApplyWorkload, h.Client)
|
||||
return workload, traits, isHealth, err
|
||||
}
|
||||
}
|
||||
@@ -439,8 +439,8 @@ func (h *AppHandler) prepareWorkloadAndManifests(ctx context.Context,
|
||||
comp common.ApplicationComponent,
|
||||
appRev *v1beta1.ApplicationRevision,
|
||||
patcher *value.Value,
|
||||
af *appfile.Appfile) (*appfile.Workload, *types.ComponentManifest, error) {
|
||||
wl, err := appParser.ParseWorkloadFromRevisionAndClient(ctx, comp, appRev)
|
||||
af *appfile.Appfile) (*appfile.Component, *types.ComponentManifest, error) {
|
||||
wl, err := appParser.ParseComponentFromRevisionAndClient(ctx, comp, appRev)
|
||||
if err != nil {
|
||||
return nil, nil, errors.WithMessage(err, "ParseWorkload")
|
||||
}
|
||||
@@ -457,7 +457,7 @@ func (h *AppHandler) prepareWorkloadAndManifests(ctx context.Context,
|
||||
ctxData.Cluster = cluster
|
||||
}
|
||||
// cluster info are secrets stored in the control plane cluster
|
||||
ctxData.ClusterVersion = multicluster.GetVersionInfoFromObject(pkgmulticluster.WithCluster(ctx, types.ClusterLocalName), h.r.Client, ctxData.Cluster)
|
||||
ctxData.ClusterVersion = multicluster.GetVersionInfoFromObject(pkgmulticluster.WithCluster(ctx, types.ClusterLocalName), h.Client, ctxData.Cluster)
|
||||
ctxData.CompRevision, _ = ctrlutil.ComputeSpecHash(comp)
|
||||
})
|
||||
if err != nil {
|
||||
@@ -490,10 +490,10 @@ func renderComponentsAndTraits(client client.Client, manifest *types.ComponentMa
|
||||
return readyWorkload, readyTraits, nil
|
||||
}
|
||||
|
||||
func checkSkipApplyWorkload(wl *appfile.Workload) {
|
||||
for _, trait := range wl.Traits {
|
||||
func checkSkipApplyWorkload(comp *appfile.Component) {
|
||||
for _, trait := range comp.Traits {
|
||||
if trait.FullTemplate.TraitDefinition.Spec.ManageWorkload {
|
||||
wl.SkipApplyWorkload = true
|
||||
comp.SkipApplyWorkload = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ var _ = Describe("Test Application workflow generator", func() {
|
||||
_, err = af.GeneratePolicyManifests(context.Background())
|
||||
Expect(err).Should(BeNil())
|
||||
|
||||
handler, err := NewAppHandler(ctx, reconciler, app, appParser)
|
||||
handler, err := NewAppHandler(ctx, reconciler, app)
|
||||
Expect(err).Should(Succeed())
|
||||
|
||||
logCtx := monitorContext.NewTraceContext(ctx, "")
|
||||
@@ -157,7 +157,7 @@ var _ = Describe("Test Application workflow generator", func() {
|
||||
_, err = af.GeneratePolicyManifests(context.Background())
|
||||
Expect(err).Should(BeNil())
|
||||
|
||||
handler, err := NewAppHandler(ctx, reconciler, app, appParser)
|
||||
handler, err := NewAppHandler(ctx, reconciler, app)
|
||||
Expect(err).Should(Succeed())
|
||||
|
||||
logCtx := monitorContext.NewTraceContext(ctx, "")
|
||||
@@ -199,7 +199,7 @@ var _ = Describe("Test Application workflow generator", func() {
|
||||
af, err := appParser.GenerateAppFile(ctx, app)
|
||||
Expect(err).Should(BeNil())
|
||||
|
||||
handler, err := NewAppHandler(ctx, reconciler, app, appParser)
|
||||
handler, err := NewAppHandler(ctx, reconciler, app)
|
||||
Expect(err).Should(Succeed())
|
||||
|
||||
logCtx := monitorContext.NewTraceContext(ctx, "")
|
||||
@@ -241,7 +241,7 @@ var _ = Describe("Test Application workflow generator", func() {
|
||||
af, err := appParser.GenerateAppFile(ctx, app)
|
||||
Expect(err).Should(BeNil())
|
||||
|
||||
handler, err := NewAppHandler(ctx, reconciler, app, appParser)
|
||||
handler, err := NewAppHandler(ctx, reconciler, app)
|
||||
Expect(err).Should(Succeed())
|
||||
|
||||
logCtx := monitorContext.NewTraceContext(ctx, "")
|
||||
@@ -280,7 +280,7 @@ var _ = Describe("Test Application workflow generator", func() {
|
||||
af, err := appParser.GenerateAppFile(ctx, app)
|
||||
Expect(err).Should(BeNil())
|
||||
|
||||
handler, err := NewAppHandler(ctx, reconciler, app, appParser)
|
||||
handler, err := NewAppHandler(ctx, reconciler, app)
|
||||
Expect(err).Should(Succeed())
|
||||
|
||||
logCtx := monitorContext.NewTraceContext(ctx, "")
|
||||
|
||||
@@ -114,14 +114,14 @@ func (h *AppHandler) createResourcesConfigMap(ctx context.Context,
|
||||
ConfigMapKeyPolicy: string(util.MustJSONMarshal(policies)),
|
||||
},
|
||||
}
|
||||
err := h.r.Client.Get(ctx, client.ObjectKey{Name: appRev.Name, Namespace: appRev.Namespace}, &corev1.ConfigMap{})
|
||||
err := h.Client.Get(ctx, client.ObjectKey{Name: appRev.Name, Namespace: appRev.Namespace}, &corev1.ConfigMap{})
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
if err != nil && !apierrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
return h.r.Client.Create(ctx, cm)
|
||||
return h.Client.Create(ctx, cm)
|
||||
}
|
||||
|
||||
// SprintComponentManifest formats and returns the resulting string.
|
||||
@@ -213,7 +213,7 @@ func (h *AppHandler) gatherRevisionSpec(af *appfile.Appfile) (*v1beta1.Applicati
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, w := range af.Workloads {
|
||||
for _, w := range af.ParsedComponents {
|
||||
if w == nil {
|
||||
continue
|
||||
}
|
||||
@@ -238,7 +238,7 @@ func (h *AppHandler) gatherRevisionSpec(af *appfile.Appfile) (*v1beta1.Applicati
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, p := range af.PolicyWorkloads {
|
||||
for _, p := range af.ParsedPolicies {
|
||||
if p == nil || p.FullTemplate == nil {
|
||||
continue
|
||||
}
|
||||
@@ -283,7 +283,7 @@ func (h *AppHandler) getLatestAppRevision(ctx context.Context) error {
|
||||
}
|
||||
latestRevName := h.app.Status.LatestRevision.Name
|
||||
latestAppRev := &v1beta1.ApplicationRevision{}
|
||||
if err := h.r.Get(ctx, client.ObjectKey{Name: latestRevName, Namespace: h.app.Namespace}, latestAppRev); err != nil {
|
||||
if err := h.Get(ctx, client.ObjectKey{Name: latestRevName, Namespace: h.app.Namespace}, latestAppRev); err != nil {
|
||||
klog.ErrorS(err, "Failed to get latest app revision", "appRevisionName", latestRevName)
|
||||
return errors.Wrapf(err, "fail to get latest app revision %s", latestRevName)
|
||||
}
|
||||
@@ -403,7 +403,7 @@ func (h *AppHandler) currentAppRevIsNew(ctx context.Context) (bool, bool, error)
|
||||
return false, false, nil
|
||||
}
|
||||
|
||||
revs, err := GetAppRevisions(ctx, h.r.Client, h.app.Name, h.app.Namespace)
|
||||
revs, err := GetAppRevisions(ctx, h.Client, h.app.Name, h.app.Namespace)
|
||||
if err != nil {
|
||||
klog.ErrorS(err, "Failed to list app revision", "appName", h.app.Name)
|
||||
return false, false, errors.Wrap(err, "failed to list app revision")
|
||||
@@ -567,9 +567,9 @@ func (h *AppHandler) FinalizeAndApplyAppRevision(ctx context.Context) error {
|
||||
sharding.PropagateScheduledShardIDLabel(h.app, appRev)
|
||||
|
||||
gotAppRev := &v1beta1.ApplicationRevision{}
|
||||
if err := h.r.Get(ctx, client.ObjectKey{Name: appRev.Name, Namespace: appRev.Namespace}, gotAppRev); err != nil {
|
||||
if err := h.Get(ctx, client.ObjectKey{Name: appRev.Name, Namespace: appRev.Namespace}, gotAppRev); err != nil {
|
||||
if apierrors.IsNotFound(err) {
|
||||
return h.r.Create(ctx, appRev)
|
||||
return h.Create(ctx, appRev)
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -588,12 +588,12 @@ func (h *AppHandler) FinalizeAndApplyAppRevision(ctx context.Context) error {
|
||||
appRev.Spec.Compression.SetType(compression.Zstd)
|
||||
}
|
||||
|
||||
return h.r.Update(ctx, appRev)
|
||||
return h.Update(ctx, appRev)
|
||||
}
|
||||
|
||||
// UpdateAppLatestRevisionStatus only call to update app's latest revision status after applying manifests successfully
|
||||
// otherwise it will override previous revision which is used during applying to do GC jobs
|
||||
func (h *AppHandler) UpdateAppLatestRevisionStatus(ctx context.Context) error {
|
||||
func (h *AppHandler) UpdateAppLatestRevisionStatus(ctx context.Context, patchStatus statusPatcher) error {
|
||||
if DisableAllApplicationRevision {
|
||||
return nil
|
||||
}
|
||||
@@ -614,7 +614,7 @@ func (h *AppHandler) UpdateAppLatestRevisionStatus(ctx context.Context) error {
|
||||
Revision: int64(revNum),
|
||||
RevisionHash: h.currentRevHash,
|
||||
}
|
||||
if err := h.r.patchStatus(ctx, h.app, common.ApplicationRendering); err != nil {
|
||||
if err := patchStatus(ctx, h.app, common.ApplicationRendering); err != nil {
|
||||
klog.InfoS("Failed to update the latest appConfig revision to status", "application", klog.KObj(h.app),
|
||||
"latest revision", revName, "err", err)
|
||||
return err
|
||||
@@ -635,13 +635,13 @@ func (h *AppHandler) UpdateApplicationRevisionStatus(ctx context.Context, appRev
|
||||
// Versioned the context backend values.
|
||||
if wfStatus.ContextBackend != nil {
|
||||
var cm corev1.ConfigMap
|
||||
if err := h.r.Client.Get(ctx, ktypes.NamespacedName{Namespace: wfStatus.ContextBackend.Namespace, Name: wfStatus.ContextBackend.Name}, &cm); err != nil {
|
||||
if err := h.Client.Get(ctx, ktypes.NamespacedName{Namespace: wfStatus.ContextBackend.Namespace, Name: wfStatus.ContextBackend.Name}, &cm); err != nil {
|
||||
klog.Error(err, "[UpdateApplicationRevisionStatus] failed to load the context values", "ApplicationRevision", appRev.Name)
|
||||
}
|
||||
appRev.Status.WorkflowContext = cm.Data
|
||||
}
|
||||
|
||||
if err := h.r.Client.Status().Update(ctx, appRev); err != nil {
|
||||
if err := h.Client.Status().Update(ctx, appRev); err != nil {
|
||||
if logCtx, ok := ctx.(monitorContext.Context); ok {
|
||||
logCtx.Error(err, "[UpdateApplicationRevisionStatus] failed to update application revision status", "ApplicationRevision", appRev.Name)
|
||||
} else {
|
||||
|
||||
@@ -117,7 +117,7 @@ var _ = Describe("test generate revision ", func() {
|
||||
appRevision2 = *appRevision1.DeepCopy()
|
||||
appRevision2.Name = "appRevision2"
|
||||
|
||||
_handler, err := NewAppHandler(ctx, reconciler, &app, nil)
|
||||
_handler, err := NewAppHandler(ctx, reconciler, &app)
|
||||
Expect(err).Should(Succeed())
|
||||
handler = _handler
|
||||
})
|
||||
@@ -177,7 +177,7 @@ var _ = Describe("test generate revision ", func() {
|
||||
Expect(handler.FinalizeAndApplyAppRevision(ctx)).Should(Succeed())
|
||||
prevHash := generatedAppfile.AppRevisionHash
|
||||
handler.app.Status.LatestRevision = &common.Revision{Name: generatedAppfile.AppRevisionName, Revision: 1, RevisionHash: generatedAppfile.AppRevisionHash}
|
||||
generatedAppfile.Workloads[0].FullTemplate.ComponentDefinition = nil
|
||||
generatedAppfile.ParsedComponents[0].FullTemplate.ComponentDefinition = nil
|
||||
generatedAppfile.RelatedComponentDefinitions = map[string]*v1beta1.ComponentDefinition{}
|
||||
Expect(handler.PrepareCurrentAppRevision(ctx, generatedAppfile)).Should(Succeed())
|
||||
nonChangeHash := generatedAppfile.AppRevisionHash
|
||||
@@ -201,12 +201,12 @@ var _ = Describe("test generate revision ", func() {
|
||||
Expect(handler.PrepareCurrentAppRevision(ctx, generatedAppfile)).Should(Succeed())
|
||||
Expect(handler.FinalizeAndApplyAppRevision(ctx)).Should(Succeed())
|
||||
Expect(handler.ProduceArtifacts(context.Background(), comps, nil)).Should(Succeed())
|
||||
Expect(handler.UpdateAppLatestRevisionStatus(ctx)).Should(Succeed())
|
||||
Expect(handler.UpdateAppLatestRevisionStatus(ctx, reconciler.patchStatus)).Should(Succeed())
|
||||
|
||||
curApp := &v1beta1.Application{}
|
||||
Eventually(
|
||||
func() error {
|
||||
return handler.r.Get(ctx,
|
||||
return handler.Get(ctx,
|
||||
types.NamespacedName{Namespace: ns.Name, Name: app.Name},
|
||||
curApp)
|
||||
},
|
||||
@@ -216,7 +216,7 @@ var _ = Describe("test generate revision ", func() {
|
||||
curAppRevision := &v1beta1.ApplicationRevision{}
|
||||
Eventually(
|
||||
func() error {
|
||||
return handler.r.Get(ctx,
|
||||
return handler.Get(ctx,
|
||||
types.NamespacedName{Namespace: ns.Name, Name: curApp.Status.LatestRevision.Name},
|
||||
curAppRevision)
|
||||
},
|
||||
@@ -241,7 +241,7 @@ var _ = Describe("test generate revision ", func() {
|
||||
Expect(handler.ProduceArtifacts(context.Background(), comps, nil)).Should(Succeed())
|
||||
Eventually(
|
||||
func() error {
|
||||
return handler.r.Get(ctx,
|
||||
return handler.Get(ctx,
|
||||
types.NamespacedName{Namespace: ns.Name, Name: app.Name},
|
||||
curApp)
|
||||
},
|
||||
@@ -254,7 +254,7 @@ var _ = Describe("test generate revision ", func() {
|
||||
curAppRevision = &v1beta1.ApplicationRevision{}
|
||||
Eventually(
|
||||
func() error {
|
||||
return handler.r.Get(ctx,
|
||||
return handler.Get(ctx,
|
||||
types.NamespacedName{Namespace: ns.Name, Name: lastRevision},
|
||||
curAppRevision)
|
||||
},
|
||||
@@ -278,10 +278,10 @@ var _ = Describe("test generate revision ", func() {
|
||||
Expect(handler.PrepareCurrentAppRevision(ctx, generatedAppfile)).Should(Succeed())
|
||||
Expect(handler.FinalizeAndApplyAppRevision(ctx)).Should(Succeed())
|
||||
Expect(handler.ProduceArtifacts(context.Background(), comps, nil)).Should(Succeed())
|
||||
Expect(handler.UpdateAppLatestRevisionStatus(ctx)).Should(Succeed())
|
||||
Expect(handler.UpdateAppLatestRevisionStatus(ctx, reconciler.patchStatus)).Should(Succeed())
|
||||
Eventually(
|
||||
func() error {
|
||||
return handler.r.Get(ctx,
|
||||
return handler.Get(ctx,
|
||||
types.NamespacedName{Namespace: ns.Name, Name: app.Name},
|
||||
curApp)
|
||||
},
|
||||
@@ -295,7 +295,7 @@ var _ = Describe("test generate revision ", func() {
|
||||
curAppRevision = &v1beta1.ApplicationRevision{}
|
||||
Eventually(
|
||||
func() error {
|
||||
return handler.r.Get(ctx,
|
||||
return handler.Get(ctx,
|
||||
types.NamespacedName{Namespace: ns.Name, Name: curApp.Status.LatestRevision.Name},
|
||||
curAppRevision)
|
||||
},
|
||||
@@ -322,10 +322,10 @@ var _ = Describe("test generate revision ", func() {
|
||||
Expect(handler.PrepareCurrentAppRevision(ctx, generatedAppfile)).Should(Succeed())
|
||||
Expect(handler.FinalizeAndApplyAppRevision(ctx)).Should(Succeed())
|
||||
Expect(handler.ProduceArtifacts(context.Background(), comps, nil)).Should(Succeed())
|
||||
Expect(handler.UpdateAppLatestRevisionStatus(ctx)).Should(Succeed())
|
||||
Expect(handler.UpdateAppLatestRevisionStatus(ctx, reconciler.patchStatus)).Should(Succeed())
|
||||
Eventually(
|
||||
func() error {
|
||||
return handler.r.Get(ctx,
|
||||
return handler.Get(ctx,
|
||||
types.NamespacedName{Namespace: ns.Name, Name: app.Name},
|
||||
curApp)
|
||||
},
|
||||
@@ -339,7 +339,7 @@ var _ = Describe("test generate revision ", func() {
|
||||
curAppRevision = &v1beta1.ApplicationRevision{}
|
||||
Eventually(
|
||||
func() error {
|
||||
return handler.r.Get(ctx,
|
||||
return handler.Get(ctx,
|
||||
types.NamespacedName{Namespace: ns.Name, Name: curApp.Status.LatestRevision.Name},
|
||||
curAppRevision)
|
||||
},
|
||||
@@ -366,19 +366,19 @@ var _ = Describe("test generate revision ", func() {
|
||||
Expect(handler.PrepareCurrentAppRevision(ctx, generatedAppfile)).Should(Succeed())
|
||||
Expect(handler.FinalizeAndApplyAppRevision(ctx)).Should(Succeed())
|
||||
Expect(handler.ProduceArtifacts(context.Background(), comps, nil)).Should(Succeed())
|
||||
Expect(handler.UpdateAppLatestRevisionStatus(ctx)).Should(Succeed())
|
||||
Expect(handler.UpdateAppLatestRevisionStatus(ctx, reconciler.patchStatus)).Should(Succeed())
|
||||
|
||||
curApp := &v1beta1.Application{}
|
||||
Eventually(
|
||||
func() error {
|
||||
return handler.r.Get(ctx, types.NamespacedName{Namespace: ns.Name, Name: app.Name}, curApp)
|
||||
return handler.Get(ctx, types.NamespacedName{Namespace: ns.Name, Name: app.Name}, curApp)
|
||||
}, time.Second*10, time.Millisecond*500).Should(BeNil())
|
||||
Expect(curApp.Status.LatestRevision.Revision).Should(BeEquivalentTo(1))
|
||||
By("Verify the created appRevision is exactly what it is")
|
||||
curAppRevision := &v1beta1.ApplicationRevision{}
|
||||
Eventually(
|
||||
func() error {
|
||||
return handler.r.Get(ctx,
|
||||
return handler.Get(ctx,
|
||||
types.NamespacedName{Namespace: ns.Name, Name: curApp.Status.LatestRevision.Name},
|
||||
curAppRevision)
|
||||
},
|
||||
@@ -399,7 +399,7 @@ var _ = Describe("test generate revision ", func() {
|
||||
Expect(handler.ProduceArtifacts(context.Background(), comps, nil)).Should(Succeed())
|
||||
Eventually(
|
||||
func() error {
|
||||
return handler.r.Get(ctx, types.NamespacedName{Namespace: ns.Name, Name: app.Name}, curApp)
|
||||
return handler.Get(ctx, types.NamespacedName{Namespace: ns.Name, Name: app.Name}, curApp)
|
||||
}, time.Second*10, time.Millisecond*500).Should(BeNil())
|
||||
// no new revision should be created
|
||||
Expect(curApp.Status.LatestRevision.Name).Should(Equal(lastRevision))
|
||||
@@ -409,7 +409,7 @@ var _ = Describe("test generate revision ", func() {
|
||||
curAppRevision = &v1beta1.ApplicationRevision{}
|
||||
Eventually(
|
||||
func() error {
|
||||
return handler.r.Get(ctx, types.NamespacedName{Namespace: ns.Name, Name: lastRevision}, curAppRevision)
|
||||
return handler.Get(ctx, types.NamespacedName{Namespace: ns.Name, Name: lastRevision}, curAppRevision)
|
||||
}, time.Second*5, time.Millisecond*500).Should(BeNil())
|
||||
Expect(err).Should(Succeed())
|
||||
Expect(curAppRevision.GetLabels()[oam.LabelAppRevisionHash]).Should(Equal(appHash1))
|
||||
@@ -734,7 +734,7 @@ status: {}
|
||||
Expect(k8sClient.Create(ctx, &apprev)).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{}))
|
||||
|
||||
// prepare handler
|
||||
_handler, err := NewAppHandler(ctx, reconciler, &app, nil)
|
||||
_handler, err := NewAppHandler(ctx, reconciler, &app)
|
||||
Expect(err).Should(Succeed())
|
||||
handler = _handler
|
||||
|
||||
|
||||
@@ -35,6 +35,9 @@ import (
|
||||
pkgdef "github.com/oam-dev/kubevela/pkg/definition"
|
||||
)
|
||||
|
||||
// GoProxyEnvKey with the environment variable name that defines the GOPROXY preferences.
|
||||
const GoProxyEnvKey = "GOPROXY"
|
||||
|
||||
var (
|
||||
mainModuleVersionKey langArgKey = "MainModuleVersion"
|
||||
goProxyKey langArgKey = "GoProxy"
|
||||
@@ -48,11 +51,13 @@ var (
|
||||
goProxy = LangArg{
|
||||
Name: goProxyKey,
|
||||
Desc: "The proxy for go get/go mod tidy command",
|
||||
Default: "https://goproxy.cn,direct",
|
||||
Default: "",
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
// Propagate the environment GOPROXY variable to the tests that are executed through external containers.
|
||||
goProxy.Default = os.Getenv(GoProxyEnvKey)
|
||||
registerLangArg("go", mainModuleVersion, goProxy)
|
||||
}
|
||||
|
||||
|
||||
@@ -23,8 +23,6 @@ const (
|
||||
LabelAppName = "app.oam.dev/name"
|
||||
// LabelAppRevision records the name of Application, it's equal to name of AppConfig created by Application
|
||||
LabelAppRevision = "app.oam.dev/appRevision"
|
||||
// LabelAppDeployment records the name of AppDeployment.
|
||||
LabelAppDeployment = "app.oam.dev/appDeployment"
|
||||
// LabelAppComponent records the name of Component
|
||||
LabelAppComponent = "app.oam.dev/component"
|
||||
// LabelReplicaKey records the replica key of Component
|
||||
@@ -62,11 +60,6 @@ const (
|
||||
|
||||
// LabelControllerRevisionComponent indicate which component the revision belong to
|
||||
LabelControllerRevisionComponent = "controller.oam.dev/component"
|
||||
// LabelComponentRevisionHash records the hash value of a component
|
||||
LabelComponentRevisionHash = "app.oam.dev/component-revision-hash"
|
||||
|
||||
// LabelAddonsName records the name of initializer stored in configMap
|
||||
LabelAddonsName = "addons.oam.dev/type"
|
||||
|
||||
// LabelAddonName indicates the name of the corresponding Addon
|
||||
LabelAddonName = "addons.oam.dev/name"
|
||||
@@ -142,13 +135,6 @@ const (
|
||||
// its controller should not try to reconcile it
|
||||
AnnotationAppRevision = "app.oam.dev/app-revision"
|
||||
|
||||
// AnnotationAppRevisionOnly the Application update should only generate revision,
|
||||
// not any appContexts or components.
|
||||
AnnotationAppRevisionOnly = "app.oam.dev/revision-only"
|
||||
|
||||
// AnnotationWorkflowContext is used to pass in the workflow context marshalled in json format.
|
||||
AnnotationWorkflowContext = "app.oam.dev/workflow-context"
|
||||
|
||||
// AnnotationKubeVelaVersion is used to record current KubeVela version
|
||||
AnnotationKubeVelaVersion = "oam.dev/kubevela-version"
|
||||
|
||||
@@ -158,15 +144,9 @@ const (
|
||||
// AnnotationFilterLabelKeys is used to filter labels passed to workload and trait, split by comma
|
||||
AnnotationFilterLabelKeys = "filter.oam.dev/label-keys"
|
||||
|
||||
// AnnotationSkipGC is used to tell application to skip gc workload/trait
|
||||
AnnotationSkipGC = "app.oam.dev/skipGC"
|
||||
|
||||
// AnnotationDefinitionRevisionName is used to specify the name of DefinitionRevision in component/trait definition
|
||||
AnnotationDefinitionRevisionName = "definitionrevision.oam.dev/name"
|
||||
|
||||
// AnnotationAddonsName records the name of initializer stored in configMap
|
||||
AnnotationAddonsName = "addons.oam.dev/name"
|
||||
|
||||
// AnnotationLastAppliedConfiguration is kubectl annotations for 3-way merge
|
||||
AnnotationLastAppliedConfiguration = "kubectl.kubernetes.io/last-applied-configuration"
|
||||
|
||||
@@ -189,12 +169,6 @@ const (
|
||||
// AnnotationAppAlias specifies the alias for application in db.
|
||||
AnnotationAppAlias = "app.oam.dev/appAlias"
|
||||
|
||||
// AnnotationWorkloadGVK indicates the managed workload's GVK by trait
|
||||
AnnotationWorkloadGVK = "trait.oam.dev/workload-gvk"
|
||||
|
||||
// AnnotationWorkloadName indicates the managed workload's name by trait
|
||||
AnnotationWorkloadName = "trait.oam.dev/workload-name"
|
||||
|
||||
// AnnotationControllerRequirement indicates the controller version that can process the application/definition.
|
||||
AnnotationControllerRequirement = "app.oam.dev/controller-version-require"
|
||||
|
||||
|
||||
@@ -32,8 +32,6 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/client/fake"
|
||||
|
||||
"github.com/kubevela/workflow/pkg/cue/packages"
|
||||
|
||||
"github.com/oam-dev/kubevela/pkg/oam"
|
||||
)
|
||||
|
||||
// Args is args for controller-runtime client
|
||||
@@ -125,7 +123,7 @@ func (a *Args) GetClient() (client.Client, error) {
|
||||
}
|
||||
|
||||
// GetFakeClient returns a fake client with the definition objects preloaded
|
||||
func (a *Args) GetFakeClient(defs []oam.Object) (client.Client, error) {
|
||||
func (a *Args) GetFakeClient(defs []*unstructured.Unstructured) (client.Client, error) {
|
||||
if a.client != nil {
|
||||
return a.client, nil
|
||||
}
|
||||
@@ -136,9 +134,7 @@ func (a *Args) GetFakeClient(defs []oam.Object) (client.Client, error) {
|
||||
}
|
||||
objs := make([]client.Object, 0, len(defs))
|
||||
for _, def := range defs {
|
||||
if unstructDef, ok := def.(*unstructured.Unstructured); ok {
|
||||
objs = append(objs, unstructDef)
|
||||
}
|
||||
objs = append(objs, def)
|
||||
}
|
||||
return fake.NewClientBuilder().WithObjects(objs...).WithScheme(a.Schema).Build(), nil
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ type ComponentRender func(ctx context.Context, comp common.ApplicationComponent,
|
||||
type ComponentHealthCheck func(ctx context.Context, comp common.ApplicationComponent, patcher *value.Value, clusterName string, overrideNamespace string) (bool, *unstructured.Unstructured, []*unstructured.Unstructured, error)
|
||||
|
||||
// WorkloadRenderer renderer to render application component into workload
|
||||
type WorkloadRenderer func(ctx context.Context, comp common.ApplicationComponent) (*appfile.Workload, error)
|
||||
type WorkloadRenderer func(ctx context.Context, comp common.ApplicationComponent) (*appfile.Component, error)
|
||||
|
||||
type provider struct {
|
||||
render ComponentRender
|
||||
|
||||
@@ -33,14 +33,14 @@ import (
|
||||
"github.com/oam-dev/kubevela/pkg/appfile"
|
||||
)
|
||||
|
||||
func fakeWorkloadRenderer(_ context.Context, comp apicommon.ApplicationComponent) (*appfile.Workload, error) {
|
||||
func fakeWorkloadRenderer(_ context.Context, comp apicommon.ApplicationComponent) (*appfile.Component, error) {
|
||||
if strings.HasPrefix(comp.Name, "error") {
|
||||
return nil, errors.New(comp.Name)
|
||||
}
|
||||
if strings.HasPrefix(comp.Name, "terraform") {
|
||||
return &appfile.Workload{CapabilityCategory: types.TerraformCategory}, nil
|
||||
return &appfile.Component{CapabilityCategory: types.TerraformCategory}, nil
|
||||
}
|
||||
return &appfile.Workload{CapabilityCategory: types.CUECategory}, nil
|
||||
return &appfile.Component{CapabilityCategory: types.CUECategory}, nil
|
||||
}
|
||||
|
||||
func TestLoadTerraformComponents(t *testing.T) {
|
||||
|
||||
@@ -174,7 +174,7 @@ func (g *DeployWorkflowStepGenerator) Generate(app *v1beta1.Application, existin
|
||||
steps = append(steps, workflowv1alpha1.WorkflowStep{
|
||||
WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{
|
||||
Name: "deploy",
|
||||
Type: "deploy",
|
||||
Type: DeployWorkflowStep,
|
||||
Properties: util.Object2RawExtension(map[string]interface{}{"policies": append([]string{}, overrides...)}),
|
||||
},
|
||||
})
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
@@ -290,3 +291,10 @@ func TestWorkflowStepGenerator(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsBuiltinWorkflowStepType(t *testing.T) {
|
||||
assert.True(t, IsBuiltinWorkflowStepType("suspend"))
|
||||
assert.True(t, IsBuiltinWorkflowStepType("apply-component"))
|
||||
assert.True(t, IsBuiltinWorkflowStepType("step-group"))
|
||||
assert.True(t, IsBuiltinWorkflowStepType("builtin-apply-component"))
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ func ApplyTerraform(app *v1beta1.Application, k8sClient client.Client, ioStream
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for i, wl := range appFile.Workloads {
|
||||
for i, wl := range appFile.ParsedComponents {
|
||||
switch wl.CapabilityCategory {
|
||||
case types.TerraformCategory:
|
||||
name := wl.Name
|
||||
@@ -191,8 +191,8 @@ func generateSecretFromTerraformOutput(k8sClient client.Client, outputList []str
|
||||
}
|
||||
|
||||
// getTerraformJSONFiles gets Terraform JSON files or modules from workload
|
||||
func getTerraformJSONFiles(wl *appfile.Workload, ctxData process.ContextData) ([]byte, error) {
|
||||
pCtx, err := appfile.PrepareProcessContext(wl, ctxData)
|
||||
func getTerraformJSONFiles(comp *appfile.Component, ctxData process.ContextData) ([]byte, error) {
|
||||
pCtx, err := appfile.PrepareProcessContext(comp, ctxData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ func PrintComponentListFromRegistry(registry Registry, ioStreams cmdutil.IOStrea
|
||||
|
||||
// InstallCompByNameFromRegistry will install given componentName comp to cluster from registry
|
||||
func InstallCompByNameFromRegistry(args common2.Args, ioStream cmdutil.IOStreams, compName string, registry Registry) error {
|
||||
capObj, data, err := registry.GetCap(compName)
|
||||
_, data, err := registry.GetCap(compName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -200,7 +200,7 @@ func InstallCompByNameFromRegistry(args common2.Args, ioStream cmdutil.IOStreams
|
||||
return err
|
||||
}
|
||||
|
||||
err = common.InstallComponentDefinition(k8sClient, data, ioStream, &capObj)
|
||||
err = common.InstallComponentDefinition(k8sClient, data, ioStream)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -42,7 +42,6 @@ import (
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/types"
|
||||
"github.com/oam-dev/kubevela/pkg/appfile/dryrun"
|
||||
"github.com/oam-dev/kubevela/pkg/oam"
|
||||
"github.com/oam-dev/kubevela/pkg/utils/common"
|
||||
cmdutil "github.com/oam-dev/kubevela/pkg/utils/util"
|
||||
)
|
||||
@@ -119,7 +118,7 @@ func (d *debugOpts) debugApplication(ctx context.Context, wargs *WorkflowArgs, c
|
||||
return d.debugWorkflow(ctx, wargs, cli, pd, ioStreams)
|
||||
}
|
||||
|
||||
dryRunOpt := dryrun.NewDryRunOption(cli, config, pd, []oam.Object{}, false)
|
||||
dryRunOpt := dryrun.NewDryRunOption(cli, config, pd, []*unstructured.Unstructured{}, false)
|
||||
comps, _, err := dryRunOpt.ExecuteDryRun(ctx, app)
|
||||
if err != nil {
|
||||
ioStreams.Info(color.RedString("%s%s", emojiFail, err.Error()))
|
||||
|
||||
@@ -26,17 +26,17 @@ import (
|
||||
"strings"
|
||||
|
||||
wfv1alpha1 "github.com/kubevela/workflow/api/v1alpha1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha1"
|
||||
"github.com/oam-dev/kubevela/pkg/workflow/step"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
apicommon "github.com/oam-dev/kubevela/apis/core.oam.dev/common"
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha1"
|
||||
corev1beta1 "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
|
||||
"github.com/oam-dev/kubevela/apis/types"
|
||||
"github.com/oam-dev/kubevela/pkg/appfile/dryrun"
|
||||
@@ -46,6 +46,7 @@ import (
|
||||
"github.com/oam-dev/kubevela/pkg/utils"
|
||||
"github.com/oam-dev/kubevela/pkg/utils/common"
|
||||
cmdutil "github.com/oam-dev/kubevela/pkg/utils/util"
|
||||
"github.com/oam-dev/kubevela/pkg/workflow/step"
|
||||
)
|
||||
|
||||
// DryRunCmdOptions contains dry-run cmd options
|
||||
@@ -130,7 +131,7 @@ func DryRunApplication(cmdOption *DryRunCmdOptions, c common.Args, namespace str
|
||||
var err error
|
||||
var buff = bytes.Buffer{}
|
||||
|
||||
var objs []oam.Object
|
||||
var objs []*unstructured.Unstructured
|
||||
if cmdOption.DefinitionFile != "" {
|
||||
objs, err = ReadDefinitionsFromFile(cmdOption.DefinitionFile)
|
||||
if err != nil {
|
||||
@@ -142,6 +143,7 @@ func DryRunApplication(cmdOption *DryRunCmdOptions, c common.Args, namespace str
|
||||
var newClient client.Client
|
||||
if cmdOption.OfflineMode {
|
||||
// We will load a fake client with all the objects present in the definitions file preloaded
|
||||
objs = includeBuiltinWorkflowStepDefinition(objs)
|
||||
newClient, err = c.GetFakeClient(objs)
|
||||
} else {
|
||||
// Load an actual client here
|
||||
@@ -185,7 +187,7 @@ func DryRunApplication(cmdOption *DryRunCmdOptions, c common.Args, namespace str
|
||||
return buff, nil
|
||||
}
|
||||
|
||||
func readObj(path string) (oam.Object, error) {
|
||||
func readObj(path string) (*unstructured.Unstructured, error) {
|
||||
switch {
|
||||
case strings.HasSuffix(path, ".cue"):
|
||||
def := pkgdef.Definition{Unstructured: unstructured.Unstructured{}}
|
||||
@@ -209,7 +211,7 @@ func readObj(path string) (oam.Object, error) {
|
||||
}
|
||||
|
||||
// ReadDefinitionsFromFile will read objects from file or dir in the format of yaml
|
||||
func ReadDefinitionsFromFile(path string) ([]oam.Object, error) {
|
||||
func ReadDefinitionsFromFile(path string) ([]*unstructured.Unstructured, error) {
|
||||
fi, err := os.Stat(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -219,10 +221,10 @@ func ReadDefinitionsFromFile(path string) ([]oam.Object, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []oam.Object{obj}, nil
|
||||
return []*unstructured.Unstructured{obj}, nil
|
||||
}
|
||||
|
||||
var objs []oam.Object
|
||||
var objs []*unstructured.Unstructured
|
||||
//nolint:gosec
|
||||
fis, err := os.ReadDir(path)
|
||||
if err != nil {
|
||||
@@ -401,3 +403,45 @@ func getPolicyNameFromWorkflow(wf *wfv1alpha1.Workflow, policyNameMap map[string
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// includeBuiltinWorkflowStepDefinition adds builtin workflow step definition to the given objects
|
||||
// A few builtin workflow steps have cue definition. They should be included when building offline fake client.
|
||||
func includeBuiltinWorkflowStepDefinition(objs []*unstructured.Unstructured) []*unstructured.Unstructured {
|
||||
deployUnstructured, _ := oamutil.Object2Unstructured(deployDefinition)
|
||||
return append(objs, deployUnstructured)
|
||||
}
|
||||
|
||||
// deployDefinition is the definition of deploy step
|
||||
// Copied it here to make dry-run work in offline mode.
|
||||
var deployDefinition = &corev1beta1.WorkflowStepDefinition{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: corev1beta1.WorkflowStepDefinitionKind,
|
||||
APIVersion: corev1beta1.SchemeGroupVersion.String(),
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "deploy",
|
||||
Namespace: oam.SystemDefinitionNamespace,
|
||||
},
|
||||
Spec: corev1beta1.WorkflowStepDefinitionSpec{
|
||||
Schematic: &apicommon.Schematic{
|
||||
CUE: &apicommon.CUE{Template: `
|
||||
import (
|
||||
"vela/op"
|
||||
)
|
||||
|
||||
"deploy": {
|
||||
type: "workflow-step"
|
||||
annotations: {
|
||||
"category": "Application Delivery"
|
||||
}
|
||||
labels: {
|
||||
"scope": "Application"
|
||||
}
|
||||
description: "A powerful and unified deploy step for components multi-cluster delivery with policies."
|
||||
}
|
||||
// Ignore the template field for it's useless in dry-run.
|
||||
template: {}`,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -224,10 +224,7 @@ var _ = Describe("Testing dry-run", func() {
|
||||
})
|
||||
|
||||
It("Testing dry-run offline", func() {
|
||||
|
||||
c := common2.Args{}
|
||||
c.SetConfig(cfg)
|
||||
c.SetClient(k8sClient)
|
||||
opt := DryRunCmdOptions{ApplicationFiles: []string{"test-data/dry-run/testing-dry-run-6.yaml"}, DefinitionFile: "test-data/dry-run/testing-worker-def.yaml", OfflineMode: true}
|
||||
buff, err := DryRunApplication(&opt, c, "")
|
||||
Expect(err).Should(BeNil())
|
||||
@@ -237,6 +234,18 @@ var _ = Describe("Testing dry-run", func() {
|
||||
Expect(buff.String()).Should(ContainSubstring("workload.oam.dev/type: myworker"))
|
||||
})
|
||||
|
||||
It("Testing dry-run offline with deploy workflow step", func() {
|
||||
c := common2.Args{}
|
||||
opt := DryRunCmdOptions{ApplicationFiles: []string{"test-data/dry-run/testing-dry-run-7.yaml"}, DefinitionFile: "test-data/dry-run/testing-worker-def.yaml", OfflineMode: true}
|
||||
buff, err := DryRunApplication(&opt, c, "")
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(buff.String()).Should(ContainSubstring("# Application(testing-app with topology target-prod)"))
|
||||
Expect(buff.String()).Should(ContainSubstring("# Application(testing-app with topology target-default)"))
|
||||
Expect(buff.String()).Should(ContainSubstring("name: testing-dryrun"))
|
||||
Expect(buff.String()).Should(ContainSubstring("kind: Deployment"))
|
||||
Expect(buff.String()).Should(ContainSubstring("workload.oam.dev/type: myworker"))
|
||||
})
|
||||
|
||||
It("Testing dry-run with default application namespace", func() {
|
||||
c := common2.Args{}
|
||||
c.SetConfig(cfg)
|
||||
|
||||
@@ -24,12 +24,12 @@ import (
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
|
||||
"github.com/oam-dev/kubevela/apis/types"
|
||||
"github.com/oam-dev/kubevela/pkg/appfile/dryrun"
|
||||
"github.com/oam-dev/kubevela/pkg/oam"
|
||||
"github.com/oam-dev/kubevela/pkg/utils/common"
|
||||
cmdutil "github.com/oam-dev/kubevela/pkg/utils/util"
|
||||
)
|
||||
@@ -101,7 +101,7 @@ func LiveDiffApplication(cmdOption *LiveDiffCmdOptions, c common.Args) (bytes.Bu
|
||||
if err != nil {
|
||||
return buff, err
|
||||
}
|
||||
objs := []oam.Object{}
|
||||
var objs []*unstructured.Unstructured
|
||||
if cmdOption.DefinitionFile != "" {
|
||||
objs, err = ReadDefinitionsFromFile(cmdOption.DefinitionFile)
|
||||
if err != nil {
|
||||
|
||||
31
references/cli/test-data/dry-run/testing-dry-run-7.yaml
Normal file
31
references/cli/test-data/dry-run/testing-dry-run-7.yaml
Normal file
@@ -0,0 +1,31 @@
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: testing-app
|
||||
spec:
|
||||
components:
|
||||
- name: testing-dryrun
|
||||
type: myworker
|
||||
properties:
|
||||
image: oamdev/hello-world:v1
|
||||
policies:
|
||||
- name: target-default
|
||||
type: topology
|
||||
properties:
|
||||
clusters: [ "local" ]
|
||||
namespace: "default"
|
||||
- name: target-prod
|
||||
type: topology
|
||||
properties:
|
||||
clusters: [ "local" ]
|
||||
namespace: "prod"
|
||||
workflow:
|
||||
steps:
|
||||
- name: deploy2default
|
||||
type: deploy
|
||||
properties:
|
||||
policies: [ "target-default" ]
|
||||
- name: deploy2prod
|
||||
type: deploy
|
||||
properties:
|
||||
policies: [ "target-prod" ]
|
||||
@@ -189,7 +189,7 @@ func PrintTraitListFromRegistry(registry Registry, ioStreams cmdutil.IOStreams,
|
||||
|
||||
// InstallTraitByNameFromRegistry will install given traitName trait to cluster
|
||||
func InstallTraitByNameFromRegistry(args common2.Args, ioStream cmdutil.IOStreams, traitName string, registry Registry) error {
|
||||
capObj, data, err := registry.GetCap(traitName)
|
||||
_, data, err := registry.GetCap(traitName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -199,7 +199,7 @@ func InstallTraitByNameFromRegistry(args common2.Args, ioStream cmdutil.IOStream
|
||||
return err
|
||||
}
|
||||
|
||||
err = common.InstallTraitDefinition(k8sClient, data, ioStream, &capObj)
|
||||
err = common.InstallTraitDefinition(k8sClient, data, ioStream)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -23,19 +23,17 @@ import (
|
||||
|
||||
"github.com/pkg/errors"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"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"
|
||||
cmdutil "github.com/oam-dev/kubevela/pkg/utils/util"
|
||||
)
|
||||
|
||||
// InstallComponentDefinition will add a component into K8s cluster and install its controller
|
||||
func InstallComponentDefinition(client client.Client, componentData []byte, ioStreams cmdutil.IOStreams, tp *types.Capability) error {
|
||||
func InstallComponentDefinition(client client.Client, componentData []byte, ioStreams cmdutil.IOStreams) error {
|
||||
var cd v1beta1.ComponentDefinition
|
||||
var err error
|
||||
if componentData == nil {
|
||||
@@ -46,12 +44,6 @@ func InstallComponentDefinition(client client.Client, componentData []byte, ioSt
|
||||
}
|
||||
cd.Namespace = types.DefaultKubeVelaNS
|
||||
ioStreams.Info("Installing component: " + cd.Name)
|
||||
if cd.Spec.Workload.Type == "" {
|
||||
tp.CrdInfo = &types.CRDInfo{
|
||||
APIVersion: cd.Spec.Workload.Definition.APIVersion,
|
||||
Kind: cd.Spec.Workload.Definition.Kind,
|
||||
}
|
||||
}
|
||||
if err = client.Create(context.Background(), &cd); err != nil && !apierrors.IsAlreadyExists(err) {
|
||||
return err
|
||||
}
|
||||
@@ -59,7 +51,7 @@ func InstallComponentDefinition(client client.Client, componentData []byte, ioSt
|
||||
}
|
||||
|
||||
// InstallTraitDefinition will add a trait into K8s cluster and install it's controller
|
||||
func InstallTraitDefinition(client client.Client, traitdata []byte, ioStreams cmdutil.IOStreams, cap *types.Capability) error {
|
||||
func InstallTraitDefinition(client client.Client, traitdata []byte, ioStreams cmdutil.IOStreams) error {
|
||||
var td v1beta1.TraitDefinition
|
||||
var err error
|
||||
if err = yaml.Unmarshal(traitdata, &td); err != nil {
|
||||
@@ -67,17 +59,6 @@ func InstallTraitDefinition(client client.Client, traitdata []byte, ioStreams cm
|
||||
}
|
||||
td.Namespace = types.DefaultKubeVelaNS
|
||||
ioStreams.Info("Installing trait " + td.Name)
|
||||
gvk, err := util.GetGVKFromDefinition(client.RESTMapper(), td.Spec.Reference)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cap.CrdInfo = &types.CRDInfo{
|
||||
APIVersion: v1.GroupVersion{
|
||||
Group: gvk.Group,
|
||||
Version: gvk.Version,
|
||||
}.String(),
|
||||
Kind: gvk.Kind,
|
||||
}
|
||||
if err = client.Create(context.Background(), &td); err != nil && !apierrors.IsAlreadyExists(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
kerrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/klog/v2"
|
||||
@@ -171,7 +170,7 @@ func GetComponentsFromClusterWithValidateOption(ctx context.Context, namespace s
|
||||
continue
|
||||
}
|
||||
if validateFlag && defRef.Name != types.AutoDetectWorkloadDefinition {
|
||||
if err = validateCapabilities(tmp, newClient.RESTMapper(), cd.Name, defRef); err != nil {
|
||||
if err = validateCapabilities(newClient.RESTMapper(), cd.Name, defRef); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
@@ -214,7 +213,7 @@ func GetTraitsFromClusterWithValidateOption(ctx context.Context, namespace strin
|
||||
}
|
||||
tmp.Namespace = namespace
|
||||
if validateFlag {
|
||||
if err = validateCapabilities(tmp, newClient.RESTMapper(), td.Name, td.Spec.Reference); err != nil {
|
||||
if err = validateCapabilities(newClient.RESTMapper(), td.Name, td.Spec.Reference); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
@@ -285,22 +284,16 @@ func GetPolicies(ctx context.Context, namespace string, c common.Args) ([]types.
|
||||
}
|
||||
|
||||
// validateCapabilities validates whether GVK are successfully retrieved.
|
||||
func validateCapabilities(tmp *types.Capability, mapper meta.RESTMapper, definitionName string, reference commontypes.DefinitionReference) error {
|
||||
var err error
|
||||
gvk, err := util.GetGVKFromDefinition(mapper, reference)
|
||||
func validateCapabilities(mapper meta.RESTMapper, definitionName string, reference commontypes.DefinitionReference) error {
|
||||
_, err := util.GetGVKFromDefinition(mapper, reference)
|
||||
if err != nil {
|
||||
errMsg := err.Error()
|
||||
var substr = "no matches for "
|
||||
if strings.Contains(errMsg, substr) {
|
||||
err = fmt.Errorf("expected provider: %s", strings.Split(errMsg, substr)[1])
|
||||
return fmt.Errorf("expected provider: %s", strings.Split(errMsg, substr)[1])
|
||||
}
|
||||
return fmt.Errorf("installing capability '%s'... %w", definitionName, err)
|
||||
}
|
||||
tmp.CrdInfo = &types.CRDInfo{
|
||||
APIVersion: metav1.GroupVersion{Group: gvk.Group, Version: gvk.Version}.String(),
|
||||
Kind: gvk.Kind,
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -77,10 +77,6 @@ var _ = Describe("DefinitionFiles", func() {
|
||||
Name: "env",
|
||||
},
|
||||
},
|
||||
CrdInfo: &types.CRDInfo{
|
||||
APIVersion: "apps/v1",
|
||||
Kind: "Deployment",
|
||||
},
|
||||
Labels: map[string]string{"usecase": "forplugintest"},
|
||||
}
|
||||
|
||||
@@ -110,11 +106,7 @@ var _ = Describe("DefinitionFiles", func() {
|
||||
},
|
||||
},
|
||||
CrdName: "deployments.apps",
|
||||
CrdInfo: &types.CRDInfo{
|
||||
APIVersion: "apps/v1",
|
||||
Kind: "Deployment",
|
||||
},
|
||||
Labels: map[string]string{"usecase": "forplugintest"},
|
||||
Labels: map[string]string{"usecase": "forplugintest"},
|
||||
}
|
||||
|
||||
req, _ := labels.NewRequirement("usecase", selection.Equals, []string{"forplugintest"})
|
||||
|
||||
36
references/docgen/def-doc/trait/container-ports.eg.md
Normal file
36
references/docgen/def-doc/trait/container-ports.eg.md
Normal file
@@ -0,0 +1,36 @@
|
||||
It's used to define Pod networks directly. hostPort routes the container's port directly to the port on the scheduled node, so that you can access the Pod through the host's IP plus hostPort.
|
||||
Don't specify a hostPort for a Pod unless it is absolutely necessary(run `DaemonSet` service). When you bind a Pod to a hostPort, it limits the number of places the Pod can be scheduled, because each <hostIP, hostPort, protocol> combination must be unique. If you don't specify the hostIP and protocol explicitly, Kubernetes will use 0.0.0.0 as the default hostIP and TCP as the default protocol.
|
||||
If you explicitly need to expose a Pod's port on the node, consider using `expose` or `gateway` trait, or exposeType and ports parameter of `webservice` component before resorting to `container-ports` trait.
|
||||
```yaml
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: busybox
|
||||
spec:
|
||||
components:
|
||||
- name: busybox
|
||||
type: webservice
|
||||
properties:
|
||||
cpu: "0.5"
|
||||
exposeType: ClusterIP
|
||||
image: busybox
|
||||
memory: 1024Mi
|
||||
ports:
|
||||
- expose: false
|
||||
port: 80
|
||||
protocol: TCP
|
||||
- expose: false
|
||||
port: 801
|
||||
protocol: TCP
|
||||
traits:
|
||||
- type: container-ports
|
||||
properties:
|
||||
# you can use container-ports to control multiple containers by filling `containers`
|
||||
# NOTE: in containers, you must set the container name for each container
|
||||
containers:
|
||||
- containerName: busybox
|
||||
ports:
|
||||
- containerPort: 80
|
||||
protocol: TCP
|
||||
hostPort: 8080
|
||||
```
|
||||
132
vela-templates/definitions/internal/trait/container-ports.cue
Normal file
132
vela-templates/definitions/internal/trait/container-ports.cue
Normal file
@@ -0,0 +1,132 @@
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
"container-ports": {
|
||||
type: "trait"
|
||||
annotations: {}
|
||||
labels: {}
|
||||
description: "Expose on the host and bind the external port to host to enable web traffic for your component."
|
||||
attributes: {
|
||||
podDisruptive: true
|
||||
appliesToWorkloads: ["deployments.apps", "statefulsets.apps", "daemonsets.apps", "jobs.batch"]
|
||||
}
|
||||
}
|
||||
|
||||
template: {
|
||||
#PatchParams: {
|
||||
// +usage=Specify the name of the target container, if not set, use the component name
|
||||
containerName: *"" | string
|
||||
// +usage=Specify ports you want customer traffic sent to
|
||||
ports: *[] | [...{
|
||||
// +usage=Number of port to expose on the pod's IP address
|
||||
containerPort: int
|
||||
// +usage=Protocol for port. Must be UDP, TCP, or SCTP
|
||||
protocol: *"TCP" | "UDP" | "SCTP"
|
||||
// +usage=Number of port to expose on the host
|
||||
hostPort?: int
|
||||
// +usage=What host IP to bind the external port to.
|
||||
hostIP?: string
|
||||
}]
|
||||
}
|
||||
|
||||
PatchContainer: {
|
||||
_params: #PatchParams
|
||||
name: _params.containerName
|
||||
_baseContainers: context.output.spec.template.spec.containers
|
||||
_matchContainers_: [ for _container_ in _baseContainers if _container_.name == name {_container_}]
|
||||
_baseContainer: *_|_ | {...}
|
||||
if len(_matchContainers_) == 0 {
|
||||
err: "container \(name) not found"
|
||||
}
|
||||
if len(_matchContainers_) > 0 {
|
||||
_baseContainer: _matchContainers_[0]
|
||||
_basePorts: _baseContainer.ports
|
||||
if _basePorts == _|_ {
|
||||
// +patchStrategy=replace
|
||||
ports: [ for port in _params.ports {
|
||||
containerPort: port.containerPort
|
||||
protocol: port.protocol
|
||||
if port.hostPort != _|_ {
|
||||
hostPort: port.hostPort
|
||||
}
|
||||
if port.hostIP != _|_ {
|
||||
hostIP: port.hostIP
|
||||
}
|
||||
}]
|
||||
}
|
||||
if _basePorts != _|_ {
|
||||
_basePortsMap: {for _basePort in _basePorts {(strings.ToLower(_basePort.protocol) + strconv.FormatInt(_basePort.containerPort, 10)): _basePort}}
|
||||
_portsMap: {for port in _params.ports {(strings.ToLower(port.protocol) + strconv.FormatInt(port.containerPort, 10)): port}}
|
||||
// +patchStrategy=replace
|
||||
ports: [ for portVar in _basePorts {
|
||||
containerPort: portVar.containerPort
|
||||
protocol: portVar.protocol
|
||||
_uniqueKey: strings.ToLower(portVar.protocol) + strconv.FormatInt(portVar.containerPort, 10)
|
||||
if _portsMap[_uniqueKey] != _|_ {
|
||||
if _portsMap[_uniqueKey].hostPort != _|_ {
|
||||
hostPort: _portsMap[_uniqueKey].hostPort
|
||||
}
|
||||
if _portsMap[_uniqueKey].hostIP != _|_ {
|
||||
hostIP: _portsMap[_uniqueKey].hostIP
|
||||
}
|
||||
}
|
||||
if _portsMap[_uniqueKey] == _|_ {
|
||||
if portVar.name != _|_ {
|
||||
name: portVar.name
|
||||
}
|
||||
}
|
||||
}] + [ for port in _params.ports if _basePortsMap[strings.ToLower(port.protocol)+strconv.FormatInt(port.containerPort, 10)] == _|_ {
|
||||
if port.containerPort != _|_ {
|
||||
containerPort: port.containerPort
|
||||
}
|
||||
if port.protocol != _|_ {
|
||||
protocol: port.protocol
|
||||
}
|
||||
if port.hostPort != _|_ {
|
||||
hostPort: port.hostPort
|
||||
}
|
||||
if port.hostIP != _|_ {
|
||||
hostIP: port.hostIP
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
patch: spec: template: spec: {
|
||||
if parameter.containers == _|_ {
|
||||
// +patchKey=name
|
||||
containers: [{
|
||||
PatchContainer & {_params: {
|
||||
if parameter.containerName == "" {
|
||||
containerName: context.name
|
||||
}
|
||||
if parameter.containerName != "" {
|
||||
containerName: parameter.containerName
|
||||
}
|
||||
ports: parameter.ports
|
||||
}}
|
||||
}]
|
||||
}
|
||||
if parameter.containers != _|_ {
|
||||
// +patchKey=name
|
||||
containers: [ for c in parameter.containers {
|
||||
if c.containerName == "" {
|
||||
err: "container name must be set for containers"
|
||||
}
|
||||
if c.containerName != "" {
|
||||
PatchContainer & {_params: c}
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
parameter: *#PatchParams | close({
|
||||
// +usage=Specify the container ports for multiple containers
|
||||
containers: [...#PatchParams]
|
||||
})
|
||||
|
||||
errs: [ for c in patch.spec.template.spec.containers if c.err != _|_ {c.err}]
|
||||
}
|
||||
Reference in New Issue
Block a user