Compare commits

...

18 Commits

Author SHA1 Message Date
Tianxin Dong
4209080adc Fix: add volume bottom check in resource topology rule (#5835)
Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2023-04-13 10:56:46 +08:00
github-actions[bot]
61348b9d45 Fix: use step id to filter the log data and fix the regex (#5813)
Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
(cherry picked from commit 308093159f)

Co-authored-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2023-04-07 10:40:41 +08:00
github-actions[bot]
aa5e825683 Fix: fix step id to name in workflow logs (#5807)
Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
(cherry picked from commit 6b1f57e877)

Co-authored-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2023-04-06 14:59:44 +08:00
github-actions[bot]
95d04c370d Fix: vela top cannot switch the theme (#5756)
Signed-off-by: howieyuen <howieyuen@outlook.com>
(cherry picked from commit cb1c33bed1)

Co-authored-by: howieyuen <howieyuen@outlook.com>
2023-03-28 15:38:55 +08:00
github-actions[bot]
a583f66b0d [Backport release-1.7] Fix: gateway message is wrong (#5751)
Co-authored-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
2023-03-28 09:30:29 +08:00
github-actions[bot]
7ae1aff648 [Backport release-1.7] Fix: fix vela-minimal helm chart unrecognised options (#5729)
* fix(vela-minimal): fix unrecognised options

Signed-off-by: florent.madiot.e <florent.madiot.e@thalesdigital.io>
(cherry picked from commit c9394a18a6)

* Fix(vela-minimal): make reviewable

Signed-off-by: florent.madiot.e <florent.madiot.e@thalesdigital.io>
(cherry picked from commit f4f7f96cc8)

---------

Co-authored-by: florent.madiot.e <florent.madiot.e@thalesdigital.io>
2023-03-24 11:29:34 +08:00
github-actions[bot]
0ff40d75e5 Fix: use logs to show errs intead of return in adopt all (#5712)
Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
(cherry picked from commit f0e3c33be2)

Co-authored-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2023-03-21 13:40:54 +08:00
github-actions[bot]
3d410fed5f Fix: system crd validation hook should not always use the default vela system (#5711)
Signed-off-by: Somefive <yd219913@alibaba-inc.com>
(cherry picked from commit b4b0f99f41)

Co-authored-by: Somefive <yd219913@alibaba-inc.com>
2023-03-21 10:18:28 +08:00
Tianxin Dong
f8285df49d Feat: add adopt all command (#5690) (#5696) (#5697)
Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2023-03-20 13:40:04 +08:00
Tianxin Dong
e4cd1ffd1d Feat: add adopt all command (#5690) (#5696)
Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2023-03-17 15:51:39 +08:00
Tianxin Dong
592f8b8e8f Fix: stores workflow status in revison if it is restarted (#5604) (#5673)
Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2023-03-14 22:14:41 +08:00
github-actions[bot]
94c215c361 [Backport release-1.7] Fix: add addon registry (#5660)
* Fix: add addon registry

Signed-off-by: suwanliang_yewu <suwanliang_yewu@cmss.chinamobile.com>
(cherry picked from commit 74d3ad2c88)

* Fix: modify edit errors

Signed-off-by: suwanliang_yewu <suwanliang_yewu@cmss.chinamobile.com>
(cherry picked from commit 6ae828cb04)

---------

Co-authored-by: suwanliang_yewu <suwanliang_yewu@cmss.chinamobile.com>
2023-03-13 14:15:13 +08:00
github-actions[bot]
1723a1795d Fix: make read-only object not found error more clear (#5619)
Signed-off-by: Somefive <yd219913@alibaba-inc.com>
(cherry picked from commit 7bc97f812b)

Co-authored-by: Somefive <yd219913@alibaba-inc.com>
2023-03-06 13:20:20 +08:00
github-actions[bot]
0861498ab8 Fix: replication example componentdefinition miss workload field for webhook validation (#5618)
Signed-off-by: Somefive <yd219913@alibaba-inc.com>
(cherry picked from commit c8709a2c13)

Co-authored-by: Somefive <yd219913@alibaba-inc.com>
2023-03-06 13:18:49 +08:00
github-actions[bot]
52c9a8f0a3 [Backport release-1.7] Fix: length of name should be less than 32 (#5599)
* Fix: length of name should be less than 32

Signed-off-by: caiqi <caiqi_yewu@cmss.chinamobile.com>
(cherry picked from commit c06347c923)

* Fix: length of name should be less than 32

Signed-off-by: caiqi <caiqi_yewu@cmss.chinamobile.com>
(cherry picked from commit b18bca6f92)

---------

Co-authored-by: caiqi <caiqi_yewu@cmss.chinamobile.com>
2023-03-03 16:56:38 +08:00
github-actions[bot]
c7f337fd35 [Backport release-1.7] Feat: update version of terraform-controller to v0.7.10. (#5591)
Co-authored-by: raradhakrishnan <raradhakrishnan@guidewire.com>
2023-03-01 11:05:22 +08:00
github-actions[bot]
9dca76e0de [Backport release-1.7] Fix: the array type cannot be converted to interface type (#5588)
* Fix: the array type cannot be converted to interface type

Signed-off-by: wuzhongjian <wuzhongjian_yewu@cmss.chinamobile.com>
(cherry picked from commit 16f70d7335)

* Fix: the array type cannot be converted to interface type

Signed-off-by: wuzhongjian <wuzhongjian_yewu@cmss.chinamobile.com>
(cherry picked from commit 0d0f51e3c5)

* Fix: the array type cannot be converted to interface type

Signed-off-by: wuzhongjian <wuzhongjian_yewu@cmss.chinamobile.com>
(cherry picked from commit 07a52595d3)

* Fix: the array type cannot be converted to interface type

Signed-off-by: wuzhongjian <wuzhongjian_yewu@cmss.chinamobile.com>
(cherry picked from commit 19175578dc)

---------

Co-authored-by: wuzhongjian <wuzhongjian_yewu@cmss.chinamobile.com>
2023-03-01 09:49:19 +08:00
github-actions[bot]
348f540a82 Fix: The resource topology fails to display the pods under the job (#5566) (#5573)
Signed-off-by: hanzhaoyang <hanzhaoyang@jd.com>
(cherry picked from commit c0327918fb)

Co-authored-by: hanzhaoyang <hanzhaoyang@jd.com>
2023-02-27 16:29:38 +08:00
33 changed files with 685 additions and 222 deletions

View File

@@ -113,19 +113,20 @@ spec:
}
if context.outputs.ingress.status.loadBalancer.ingress != _|_ {
let igs = context.outputs.ingress.status.loadBalancer.ingress
let host = context.outputs.ingress.spec.rules[0].host
if igs[0].ip != _|_ {
if igs[0].host != _|_ {
if host != _|_ {
message: "Visiting URL: " + context.outputs.ingress.spec.rules[0].host + ", IP: " + igs[0].ip
}
if igs[0].host == _|_ {
if host == _|_ {
message: "Host not specified, visit the cluster or load balancer in front of the cluster with IP: " + igs[0].ip
}
}
if igs[0].ip == _|_ {
if igs[0].host != _|_ {
if host != _|_ {
message: "Visiting URL: " + context.outputs.ingress.spec.rules[0].host
}
if igs[0].host != _|_ {
if host != _|_ {
message: "Host not specified, visit the cluster or load balancer in front of the cluster"
}
}

View File

@@ -323,7 +323,7 @@ spec:
envName: string
secretKey: string
}]
mountPath?: string
mountPath: string
subPath?: string
defaultMode: *420 | int
readOnly: *false | bool

View File

@@ -65,7 +65,6 @@ helm install --create-namespace -n vela-system kubevela kubevela/vela-minimal --
| `controllerArgs.reSyncPeriod` | The period for resync the applications | `5m` |
| `OAMSpecVer` | OAMSpecVer is the oam spec version controller want to setup | `minimal` |
| `disableCaps` | Disable capability | `envbinding,rollout` |
| `applyOnceOnly` | Valid applyOnceOnly values: true/false/on/off/force | `off` |
| `dependCheckWait` | dependCheckWait is the time to wait for ApplicationConfiguration's dependent-resource ready | `30s` |
@@ -97,20 +96,29 @@ helm install --create-namespace -n vela-system kubevela kubevela/vela-minimal --
| `healthCheck.port` | KubeVela health check port | `9440` |
### KubeVela controller optimization parameters
| Name | Description | Value |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- | ------- |
| `featureGates.applyOnce` | if enabled, the apply-once feature will be applied to all applications, no state-keep and no resource data storage in ResourceTracker | `false` |
### MultiCluster parameters
| Name | Description | Value |
| ----------------------------------------------------- | -------------------------------- | -------------------------------- |
| `multicluster.enabled` | Whether to enable multi-cluster | `true` |
| `multicluster.clusterGateway.replicaCount` | ClusterGateway replica count | `1` |
| `multicluster.clusterGateway.port` | ClusterGateway port | `9443` |
| `multicluster.clusterGateway.image.repository` | ClusterGateway image repository | `oamdev/cluster-gateway` |
| `multicluster.clusterGateway.image.tag` | ClusterGateway image tag | `v1.7.0` |
| `multicluster.clusterGateway.image.pullPolicy` | ClusterGateway image pull policy | `IfNotPresent` |
| `multicluster.clusterGateway.resources.limits.cpu` | ClusterGateway cpu limit | `100m` |
| `multicluster.clusterGateway.resources.limits.memory` | ClusterGateway memory limit | `200Mi` |
| `multicluster.clusterGateway.secureTLS.enabled` | Whether to enable secure TLS | `true` |
| `multicluster.clusterGateway.secureTLS.certPath` | Path to the certificate file | `/etc/k8s-cluster-gateway-certs` |
| Name | Description | Value |
| ------------------------------------------------------- | -------------------------------- | -------------------------------- |
| `multicluster.enabled` | Whether to enable multi-cluster | `true` |
| `multicluster.clusterGateway.replicaCount` | ClusterGateway replica count | `1` |
| `multicluster.clusterGateway.port` | ClusterGateway port | `9443` |
| `multicluster.clusterGateway.image.repository` | ClusterGateway image repository | `oamdev/cluster-gateway` |
| `multicluster.clusterGateway.image.tag` | ClusterGateway image tag | `v1.8.0-alpha.3` |
| `multicluster.clusterGateway.image.pullPolicy` | ClusterGateway image pull policy | `IfNotPresent` |
| `multicluster.clusterGateway.resources.requests.cpu` | ClusterGateway cpu request | `50m` |
| `multicluster.clusterGateway.resources.requests.memory` | ClusterGateway memory request | `20Mi` |
| `multicluster.clusterGateway.resources.limits.cpu` | ClusterGateway cpu limit | `500m` |
| `multicluster.clusterGateway.resources.limits.memory` | ClusterGateway memory limit | `200Mi` |
| `multicluster.clusterGateway.secureTLS.enabled` | Whether to enable secure TLS | `true` |
| `multicluster.clusterGateway.secureTLS.certPath` | Path to the certificate file | `/etc/k8s-cluster-gateway-certs` |
### Test parameters

View File

@@ -113,19 +113,20 @@ spec:
}
if context.outputs.ingress.status.loadBalancer.ingress != _|_ {
let igs = context.outputs.ingress.status.loadBalancer.ingress
let host = context.outputs.ingress.spec.rules[0].host
if igs[0].ip != _|_ {
if igs[0].host != _|_ {
if host != _|_ {
message: "Visiting URL: " + context.outputs.ingress.spec.rules[0].host + ", IP: " + igs[0].ip
}
if igs[0].host == _|_ {
if host == _|_ {
message: "Host not specified, visit the cluster or load balancer in front of the cluster with IP: " + igs[0].ip
}
}
if igs[0].ip == _|_ {
if igs[0].host != _|_ {
if host != _|_ {
message: "Visiting URL: " + context.outputs.ingress.spec.rules[0].host
}
if igs[0].host != _|_ {
if host != _|_ {
message: "Host not specified, visit the cluster or load balancer in front of the cluster"
}
}

View File

@@ -323,7 +323,7 @@ spec:
envName: string
secretKey: string
}]
mountPath?: string
mountPath: string
subPath?: string
defaultMode: *420 | int
readOnly: *false | bool

View File

@@ -166,10 +166,8 @@ spec:
- "--use-webhook=true"
- "--webhook-port={{ .Values.webhookService.port }}"
- "--webhook-cert-dir={{ .Values.admissionWebhooks.certificate.mountPath }}"
- "--autogen-workload-definition={{ .Values.admissionWebhooks.autoGenWorkloadDefinition }}"
{{ end }}
- "--health-addr=:{{ .Values.healthCheck.port }}"
- "--apply-once-only={{ .Values.applyOnceOnly }}"
{{ if ne .Values.disableCaps "" }}
- "--disable-caps={{ .Values.disableCaps }}"
{{ end }}
@@ -188,6 +186,7 @@ spec:
- "--max-workflow-step-error-retry-times={{ .Values.workflow.step.errorRetryTimes }}"
- "--feature-gates=EnableSuspendOnFailure={{- .Values.workflow.enableSuspendOnFailure | toString -}}"
- "--feature-gates=AuthenticateApplication={{- .Values.authentication.enabled | toString -}}"
- "--feature-gates=ApplyOnce={{- .Values.featureGates.applyOnce | toString -}}"
{{ if .Values.authentication.enabled }}
{{ if .Values.authentication.withUser }}
- "--authentication-with-user"

View File

@@ -26,9 +26,6 @@ OAMSpecVer: "minimal"
## @param disableCaps Disable capability
disableCaps: "envbinding,rollout"
## @param applyOnceOnly Valid applyOnceOnly values: true/false/on/off/force
applyOnceOnly: "off"
## @param dependCheckWait dependCheckWait is the time to wait for ApplicationConfiguration's dependent-resource ready
dependCheckWait: 30s
@@ -86,6 +83,11 @@ webhookService:
healthCheck:
port: 9440
## @section KubeVela controller optimization parameters
##@param featureGates.applyOnce if enabled, the apply-once feature will be applied to all applications, no state-keep and no resource data storage in ResourceTracker
featureGates:
applyOnce: false
## @section MultiCluster parameters
@@ -95,6 +97,8 @@ healthCheck:
## @param multicluster.clusterGateway.image.repository ClusterGateway image repository
## @param multicluster.clusterGateway.image.tag ClusterGateway image tag
## @param multicluster.clusterGateway.image.pullPolicy ClusterGateway image pull policy
## @param multicluster.clusterGateway.resources.requests.cpu ClusterGateway cpu request
## @param multicluster.clusterGateway.resources.requests.memory ClusterGateway memory request
## @param multicluster.clusterGateway.resources.limits.cpu ClusterGateway cpu limit
## @param multicluster.clusterGateway.resources.limits.memory ClusterGateway memory limit
## @param multicluster.clusterGateway.secureTLS.enabled Whether to enable secure TLS
@@ -106,11 +110,14 @@ multicluster:
port: 9443
image:
repository: oamdev/cluster-gateway
tag: v1.7.0
tag: v1.8.0-alpha.3
pullPolicy: IfNotPresent
resources:
requests:
cpu: 50m
memory: 20Mi
limits:
cpu: 100m
cpu: 500m
memory: 200Mi
secureTLS:
enabled: true

View File

@@ -22,6 +22,7 @@ import (
"time"
"github.com/kubevela/pkg/util/compression"
"github.com/kubevela/pkg/util/k8s"
"github.com/kubevela/pkg/util/singleton"
"k8s.io/apiserver/pkg/util/feature"
"k8s.io/klog/v2"
@@ -55,7 +56,7 @@ func (in *SystemCRDValidationHook) Run(ctx context.Context) error {
feature.DefaultMutableFeatureGate.Enabled(features.GzipApplicationRevision) {
appRev := &v1beta1.ApplicationRevision{}
appRev.Name = fmt.Sprintf("core.pre-check.%d", time.Now().UnixNano())
appRev.Namespace = types.DefaultKubeVelaNS
appRev.Namespace = k8s.GetRuntimeNamespace()
key := client.ObjectKeyFromObject(appRev)
appRev.SetLabels(map[string]string{oam.LabelPreCheck: types.VelaCoreName})
appRev.Spec.Application.Name = appRev.Name

29
go.mod
View File

@@ -54,17 +54,16 @@ require (
github.com/hashicorp/hcl/v2 v2.12.0
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174
github.com/imdario/mergo v0.3.13
github.com/koding/websocketproxy v0.0.0-20181220232114-7ed82d81a28c
github.com/kubevela/pkg v0.0.0-20230105054759-263dc191bf51
github.com/kubevela/pkg v0.0.0-20230316114047-e2b41b377bac
github.com/kubevela/prism v1.7.0-alpha.1
github.com/kubevela/workflow v0.4.1
github.com/kubevela/workflow v0.4.3
github.com/kyokomi/emoji v2.2.4+incompatible
github.com/mitchellh/hashstructure/v2 v2.0.1
github.com/mitchellh/hashstructure/v2 v2.0.2
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd
github.com/oam-dev/cluster-gateway v1.7.0-alpha.1
github.com/oam-dev/cluster-register v1.0.4-0.20220928064144-5f76a9d7ca8c
github.com/oam-dev/terraform-config-inspect v0.0.0-20210418082552-fc72d929aa28
github.com/oam-dev/terraform-controller v0.7.8
github.com/oam-dev/terraform-controller v0.7.10
github.com/olekukonko/tablewriter v0.0.5
github.com/onsi/ginkgo v1.16.5
github.com/onsi/ginkgo/v2 v2.1.6
@@ -88,9 +87,9 @@ require (
go.mongodb.org/mongo-driver v1.5.1
go.uber.org/zap v1.21.0 // indirect
golang.org/x/crypto v0.4.0
golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2
golang.org/x/term v0.3.0
golang.org/x/text v0.5.0
golang.org/x/oauth2 v0.0.0-20220722155238-128564f6959c
golang.org/x/term v0.5.0
golang.org/x/text v0.7.0
gomodules.xyz/jsonpatch/v2 v2.2.0
gopkg.in/yaml.v3 v3.0.1
gotest.tools v2.2.0+incompatible
@@ -100,14 +99,14 @@ require (
k8s.io/apiextensions-apiserver v0.25.2
k8s.io/apimachinery v0.25.3
k8s.io/apiserver v0.25.3
k8s.io/cli-runtime v0.25.2
k8s.io/cli-runtime v0.25.3
k8s.io/client-go v0.25.3
k8s.io/component-base v0.25.3
k8s.io/helm v2.17.0+incompatible
k8s.io/klog/v2 v2.70.1
k8s.io/kube-aggregator v0.25.3
k8s.io/kubectl v0.25.2
k8s.io/metrics v0.25.2
k8s.io/kubectl v0.25.3
k8s.io/metrics v0.25.3
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed
open-cluster-management.io/api v0.7.0
sigs.k8s.io/controller-runtime v0.12.3
@@ -117,6 +116,8 @@ require (
sigs.k8s.io/yaml v1.3.0
)
require github.com/koding/websocketproxy v0.0.0-20181220232114-7ed82d81a28c
require (
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
@@ -301,14 +302,14 @@ require (
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.7.0 // indirect
golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.3.0 // indirect
golang.org/x/net v0.7.0 // indirect
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde // indirect
golang.org/x/sys v0.3.0 // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
golang.org/x/tools v0.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/grpc v1.48.0 // indirect
google.golang.org/protobuf v1.28.0 // indirect
google.golang.org/protobuf v1.28.1 // 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

51
go.sum
View File

@@ -1285,12 +1285,12 @@ github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
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 v0.0.0-20230105054759-263dc191bf51 h1:xrcNNaAjqC6tr1leSYcjLFgrXKpZ8u87jpB5TolhUIc=
github.com/kubevela/pkg v0.0.0-20230105054759-263dc191bf51/go.mod h1:ZRnxY/gOcg/8FilZA+eYr+rtVXb1ijT5HFTe8zrv9zo=
github.com/kubevela/pkg v0.0.0-20230316114047-e2b41b377bac h1:TLQchMx+BRTnHyebDpOWF2RpF2eTczFBtJro3/H9vwI=
github.com/kubevela/pkg v0.0.0-20230316114047-e2b41b377bac/go.mod h1:GilLxt+9L4sU2tLeZAGHga8wiYmjjfPX/Q6JkyuuXSM=
github.com/kubevela/prism v1.7.0-alpha.1 h1:oeZFn1Oy6gxSSFzMTfsWjLOCKaaooMVm1JGNK4j4Mlo=
github.com/kubevela/prism v1.7.0-alpha.1/go.mod h1:AJSDfdA+RkRSnWx3xEcogbmOTpX+l7RSIwqVHxwUtaI=
github.com/kubevela/workflow v0.4.1 h1:lYeWE9KgSSkb368u8G7cGfyzCz41Am8MdxgViRFJxXE=
github.com/kubevela/workflow v0.4.1/go.mod h1:AX/WL3G/YBkpmNpA/SKKm9M3Y0T9y95gZA8mFWylkyM=
github.com/kubevela/workflow v0.4.3 h1:1WAMb4xrRXQW5hK5bXwV2WFHlxn2+ezkblai8oC5DmY=
github.com/kubevela/workflow v0.4.3/go.mod h1:U94Hz5rlHPAatN+Birhumly26zjAguMumdhrYk+e5mo=
github.com/kulti/thelper v0.4.0/go.mod h1:vMu2Cizjy/grP+jmsvOFDx1kYP6+PD1lqg4Yu5exl2U=
github.com/kunwardeep/paralleltest v1.0.3/go.mod h1:vLydzomDFpk7yu5UX02RmP0H8QfRPOV/oFhWN85Mjb4=
github.com/kylelemons/godebug v0.0.0-20160406211939-eadb3ce320cb/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
@@ -1435,8 +1435,8 @@ github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQ
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ=
github.com/mitchellh/hashstructure/v2 v2.0.1 h1:L60q1+q7cXE4JeEJJKMnh2brFIe3rZxCihYAB61ypAY=
github.com/mitchellh/hashstructure/v2 v2.0.1/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE=
github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=
github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE=
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
@@ -1523,8 +1523,8 @@ github.com/oam-dev/stern v1.13.2 h1:jlGgtJbKmIVhzkH44ft5plkgs8XEfvxbFrQdX60CQR4=
github.com/oam-dev/stern v1.13.2/go.mod h1:0pLjZt0amXE/ErF16Rdrgd98H2owN8Hmn3/7CX5+AeA=
github.com/oam-dev/terraform-config-inspect v0.0.0-20210418082552-fc72d929aa28 h1:tD8HiFKnt0jnwdTWjeqUnfnUYLD/+Nsmj8ZGIxqDWiU=
github.com/oam-dev/terraform-config-inspect v0.0.0-20210418082552-fc72d929aa28/go.mod h1:Mu8i0/DdplvnjwRbAYPsc8+LRR27n/mp8VWdkN10GzE=
github.com/oam-dev/terraform-controller v0.7.8 h1:4Kss5EnMljKecw8o2aPCpZdOTP1L1ODgf8BjmgN/cMI=
github.com/oam-dev/terraform-controller v0.7.8/go.mod h1:83eY+m0ehYAnQytilG9TVjuCgDQWl3+pnE6oIJ9EujE=
github.com/oam-dev/terraform-controller v0.7.10 h1:e2STz6Od53S4Ra4+QQs65lujF50vIb6eQtTMuvvofjk=
github.com/oam-dev/terraform-controller v0.7.10/go.mod h1:xvgChKG0pij0WEKRrX7w30SdVBPVOlRl/+Mv7+2C1cI=
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
@@ -2300,8 +2300,8 @@ golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/net v0.3.0 h1:VWL6FNY2bEEmsGVKabSlHu5Irp34xmMRoqb/9lF9lxk=
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
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-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -2319,8 +2319,8 @@ golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j
golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE=
golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2 h1:+jnHzr9VPj32ykQVai5DNahi9+NSp7yYuCsl5eAQtL0=
golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE=
golang.org/x/oauth2 v0.0.0-20220722155238-128564f6959c h1:q3gFqPqH7NVofKo3c3yETAP//pPI+G5mvB7qqj1Y5kY=
golang.org/x/oauth2 v0.0.0-20220722155238-128564f6959c/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
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=
@@ -2484,8 +2484,8 @@ golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
golang.org/x/sys v0.5.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-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
@@ -2494,8 +2494,8 @@ golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuX
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI=
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180805044716-cb6730876b98/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -2507,8 +2507,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/time v0.0.0-20161028155119-f51c12702a4d/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -2813,8 +2813,9 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
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=
@@ -2969,8 +2970,8 @@ k8s.io/apiserver v0.22.2/go.mod h1:vrpMmbyjWrgdyOvZTSpsusQq5iigKNWv9o9KlDAbBHI=
k8s.io/apiserver v0.22.6/go.mod h1:OlL1rGa2kKWGj2JEXnwBcul/BwC9Twe95gm4ohtiIIs=
k8s.io/apiserver v0.25.3 h1:m7+xGuG5+KYAnEsqaFtDyWMkmMMEOFYlu+NlWv5qSBI=
k8s.io/apiserver v0.25.3/go.mod h1:9bT47iM2fzRuhICJpM/RcQR9sqDDfZ7Yw60h0p3JW08=
k8s.io/cli-runtime v0.25.2 h1:XOx+SKRjBpYMLY/J292BHTkmyDffl/qOx3YSuFZkTuc=
k8s.io/cli-runtime v0.25.2/go.mod h1:OQx3+/0st6x5YpkkJQlEWLC73V0wHsOFMC1/roxV8Oc=
k8s.io/cli-runtime v0.25.3 h1:Zs7P7l7db/5J+KDePOVtDlArAa9pZXaDinGWGZl0aM8=
k8s.io/cli-runtime v0.25.3/go.mod h1:InHHsjkyW5hQsILJGpGjeruiDZT/R0OkROQgD6GzxO4=
k8s.io/client-go v0.0.0-20190620085101-78d2af792bab/go.mod h1:E95RaSlHr79aHaX0aGSwcPNfygDiPKOVXdmivCIZT0k=
k8s.io/client-go v0.0.0-20190918160344-1fbdaa4c8d90/go.mod h1:J69/JveO6XESwVgG53q3Uz5OSfgsv4uxpScmmyYOOlk=
k8s.io/client-go v0.0.0-20191122220542-ed16ecbdf3a0/go.mod h1:tyxNgOmR/Xi39HrlQ/9LQgiHJgBvmY7gp95o5GpBA4o=
@@ -3063,11 +3064,11 @@ k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c/go.mod h1:vHXdDvt9+2spS2R
k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65/go.mod h1:sX9MT8g7NVZM5lVL/j8QyCCJe8YSMW30QvGZWaCIDIk=
k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 h1:MQ8BAZPZlWk3S9K4a9NCkIFQtZShWqoha7snGixVgEA=
k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1/go.mod h1:C/N6wCaBHeBHkHUesQOQy2/MZqGgMAFPqGsGQLdbZBU=
k8s.io/kubectl v0.25.2 h1:2993lTeVimxKSWx/7z2PiJxUILygRa3tmC4QhFaeioA=
k8s.io/kubectl v0.25.2/go.mod h1:eoBGJtKUj7x38KXelz+dqVtbtbKwCqyKzJWmBHU0prg=
k8s.io/kubectl v0.25.3 h1:HnWJziEtmsm4JaJiKT33kG0kadx68MXxUE8UEbXnN4U=
k8s.io/kubectl v0.25.3/go.mod h1:glU7PiVj/R6Ud4A9FJdTcJjyzOtCJyc0eO7Mrbh3jlI=
k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
k8s.io/metrics v0.25.2 h1:105TuPaIFfr4EHzN56WwZJO7r1UesuDytNTzeMqGySo=
k8s.io/metrics v0.25.2/go.mod h1:4NDAauOuEJ+NWO2+hWkhFE4rWBx/plLWJOYU3vGl0sA=
k8s.io/metrics v0.25.3 h1:fp5RuALkbwI3UbKITdNYu6sa3LF4JPANR/ofq3oe+Fg=
k8s.io/metrics v0.25.3/go.mod h1:5j5FKJb8RHsb3Q2PLsD/p1mLiA1fTrl+a62Les+KDhc=
k8s.io/utils v0.0.0-20190221042446-c2654d5206da/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0=
k8s.io/utils v0.0.0-20190801114015-581e00157fb1/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=

View File

@@ -18,6 +18,7 @@ package service
import (
"fmt"
"reflect"
)
// guaranteePolicyExist check the slice whether contain the target policy, if not put it in.
@@ -57,16 +58,36 @@ func extractPolicyListAndProperty(property map[string]interface{}) ([]string, ma
if policies == nil {
return nil, property, nil
}
list, ok := policies.([]interface{})
if !ok {
list, err := InterfaceSlice(policies)
if err != nil {
return nil, nil, fmt.Errorf("the policies incorrect")
}
if len(list) == 0 {
return nil, property, nil
}
res := []string{}
var res []string
for _, i := range list {
res = append(res, i.(string))
}
return res, property, nil
}
// InterfaceSlice interface to []interface{}
func InterfaceSlice(slice interface{}) ([]interface{}, error) {
if arr, ok := slice.([]interface{}); ok {
return arr, nil
}
s := reflect.ValueOf(slice)
if s.Kind() != reflect.Slice {
return nil, fmt.Errorf("InterfaceSlice() given a non-slice type")
}
// Keep the distinction between nil and empty slice input
if s.IsNil() {
return nil, nil
}
ret := make([]interface{}, s.Len())
for i := 0; i < s.Len(); i++ {
ret[i] = s.Index(i).Interface()
}
return ret, nil
}

View File

@@ -174,61 +174,87 @@ func TestExtractPolicyListAndProperty(t *testing.T) {
testCases := []struct {
input string
res struct {
policies []string
properties map[string]interface{}
noError bool
policies []string
properties map[string]interface{}
noUnmarshallError bool
noExtractError bool
}
}{
{
input: `{"policies": null, "components": null}`,
res: struct {
policies []string
properties map[string]interface{}
noUnmarshallError bool
noExtractError bool
}{policies: nil, properties: map[string]interface{}{
"policies": nil,
"components": nil,
}, noUnmarshallError: true, noExtractError: true},
},
{
input: `{"policies": "policy1", "components": "comp1"}`,
res: struct {
policies []string
properties map[string]interface{}
noUnmarshallError bool
noExtractError bool
}{policies: nil, properties: nil, noUnmarshallError: true, noExtractError: false},
},
{
input: `{"policies":["policy1","policy2"], "components": ["comp1"]}`,
res: struct {
policies []string
properties map[string]interface{}
noError bool
policies []string
properties map[string]interface{}
noUnmarshallError bool
noExtractError bool
}{policies: []string{"policy1", "policy2"}, properties: map[string]interface{}{
"policies": []interface{}{"policy1", "policy2"},
"components": []interface{}{"comp1"},
}, noError: true},
}, noUnmarshallError: true, noExtractError: true},
},
{
input: `{"policies":["policy1"], "components": ["comp1"]}`,
res: struct {
policies []string
properties map[string]interface{}
noError bool
policies []string
properties map[string]interface{}
noUnmarshallError bool
noExtractError bool
}{policies: []string{"policy1"}, properties: map[string]interface{}{
"policies": []interface{}{"policy1"},
"components": []interface{}{"comp1"},
}, noError: true},
}, noUnmarshallError: true, noExtractError: true},
},
{
input: `{"policies":["policy1", "components": ["comp1"]}`,
res: struct {
policies []string
properties map[string]interface{}
noError bool
}{noError: false},
policies []string
properties map[string]interface{}
noUnmarshallError bool
noExtractError bool
}{noUnmarshallError: false, noExtractError: false},
},
{
input: `{}`,
res: struct {
policies []string
properties map[string]interface{}
noError bool
}{policies: nil, properties: nil, noError: true},
policies []string
properties map[string]interface{}
noUnmarshallError bool
noExtractError bool
}{policies: nil, properties: nil, noUnmarshallError: true, noExtractError: true},
},
}
for _, testCase := range testCases {
var in = map[string]interface{}{}
err := json.Unmarshal([]byte(testCase.input), &in)
if testCase.res.noError {
if testCase.res.noUnmarshallError {
assert.NilError(t, err)
} else {
assert.Equal(t, err != nil, true)
continue
}
policy, properties, err := extractPolicyListAndProperty(in)
if testCase.res.noError {
if testCase.res.noExtractError {
assert.NilError(t, err)
} else {
assert.Equal(t, err != nil, true)

View File

@@ -69,7 +69,7 @@ func ValidatePayloadType(fl validator.FieldLevel) bool {
// ValidateName custom check name field
func ValidateName(fl validator.FieldLevel) bool {
value := fl.Field().String()
if len(value) > 32 || len(value) < 2 {
if len(value) > 31 || len(value) < 2 {
return false
}
return nameRegexp.MatchString(value)

View File

@@ -193,7 +193,9 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
app.Status.SetConditions(condition.ReadyCondition(common.PolicyCondition.String()))
r.Recorder.Event(app, event.Normal(velatypes.ReasonPolicyGenerated, velatypes.MessagePolicyGenerated))
workflowInstance, runners, err := handler.GenerateApplicationSteps(logCtx, app, appParser, appFile, handler.currentAppRev)
handler.CheckWorkflowRestart(logCtx, app)
workflowInstance, runners, err := handler.GenerateApplicationSteps(logCtx, app, appParser, appFile)
if err != nil {
logCtx.Error(err, "[handle workflow]")
r.Recorder.Event(app, event.Warning(velatypes.ReasonFailedWorkflow, err))
@@ -449,15 +451,12 @@ func (r *Reconciler) doWorkflowFinish(logCtx monitorContext.Context, app *v1beta
wfContext.CleanupMemoryStore(app.Name, app.Namespace)
t := time.Since(app.Status.Workflow.StartTime.Time).Seconds()
metrics.WorkflowFinishedTimeHistogram.WithLabelValues(string(state)).Observe(t)
switch state {
case workflowv1alpha1.WorkflowStateSucceeded:
if state == workflowv1alpha1.WorkflowStateSucceeded {
app.Status.SetConditions(condition.ReadyCondition(common.WorkflowCondition.String()))
r.Recorder.Event(app, event.Normal(velatypes.ReasonApplied, velatypes.MessageWorkflowFinished))
handler.UpdateApplicationRevisionStatus(logCtx, handler.currentAppRev, true, app.Status.Workflow)
logCtx.Info("Application manifests has applied by workflow successfully")
default:
handler.UpdateApplicationRevisionStatus(logCtx, handler.latestAppRev, false, app.Status.Workflow)
}
handler.UpdateApplicationRevisionStatus(logCtx, handler.currentAppRev, app.Status.Workflow)
logCtx.Info("Application manifests has applied by workflow successfully")
}
func hasHealthCheckPolicy(policies []*appfile.Workload) bool {

View File

@@ -719,6 +719,76 @@ var _ = Describe("Test Application Controller", func() {
}, appRevision)).Should(BeNil())
})
It("revision should be updated if the workflow is restarted", func() {
ns := &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "vela-test-app-restart-revision",
},
}
Expect(k8sClient.Create(ctx, ns)).Should(BeNil())
app := &v1beta1.Application{
ObjectMeta: metav1.ObjectMeta{
Name: "vela-test-app-restart-revision",
Namespace: "vela-test-app-restart-revision",
},
Spec: v1beta1.ApplicationSpec{
Components: []common.ApplicationComponent{},
Workflow: &v1beta1.Workflow{
Steps: []workflowv1alpha1.WorkflowStep{
{
WorkflowStepBase: workflowv1alpha1.WorkflowStepBase{
Name: "suspend",
Type: "suspend",
},
},
},
},
},
}
Expect(k8sClient.Create(ctx, app.DeepCopy())).Should(BeNil())
appKey := client.ObjectKey{
Name: app.Name,
Namespace: app.Namespace,
}
testutil.ReconcileOnceAfterFinalizer(reconciler, reconcile.Request{NamespacedName: appKey})
By("Check Application Created with the correct revision")
curApp := &v1beta1.Application{}
Expect(k8sClient.Get(ctx, appKey, curApp)).Should(BeNil())
Expect(curApp.Status.Phase).Should(Equal(common.ApplicationWorkflowSuspending))
Expect(curApp.Status.LatestRevision).ShouldNot(BeNil())
Expect(curApp.Status.LatestRevision.Revision).Should(BeEquivalentTo(1))
appRevision := &v1beta1.ApplicationRevision{}
Expect(k8sClient.Get(ctx, client.ObjectKey{
Namespace: app.Namespace,
Name: curApp.Status.LatestRevision.Name,
}, appRevision)).Should(BeNil())
Expect(appRevision.Status.Workflow).Should(BeNil())
// update the app
curApp.Spec.Workflow.Steps[0].DependsOn = []string{"invalid"}
Expect(k8sClient.Update(ctx, curApp)).Should(BeNil())
Expect(k8sClient.Get(ctx, appKey, curApp)).Should(BeNil())
testutil.ReconcileOnce(reconciler, reconcile.Request{NamespacedName: appKey})
Expect(k8sClient.Get(ctx, client.ObjectKey{
Namespace: app.Namespace,
Name: curApp.Status.LatestRevision.Name,
}, appRevision)).Should(BeNil())
Expect(appRevision.Status.Workflow).ShouldNot(BeNil())
Expect(appRevision.Status.Workflow.Finished).Should(BeTrue())
Expect(appRevision.Status.Workflow.Terminated).Should(BeTrue())
Expect(appRevision.Status.Workflow.EndTime.IsZero()).ShouldNot(BeTrue())
Expect(appRevision.Status.Workflow.Phase).Should(Equal(workflowv1alpha1.WorkflowStateSuspending))
By("Delete Application, clean the resource")
Expect(k8sClient.Delete(ctx, app)).Should(BeNil())
})
It("revision should exist in created workload render by context.appRevision", func() {
ns := &corev1.Namespace{

View File

@@ -85,9 +85,9 @@ var (
func (h *AppHandler) GenerateApplicationSteps(ctx monitorContext.Context,
app *v1beta1.Application,
appParser *appfile.Parser,
af *appfile.Appfile,
appRev *v1beta1.ApplicationRevision) (*wfTypes.WorkflowInstance, []wfTypes.TaskRunner, error) {
af *appfile.Appfile) (*wfTypes.WorkflowInstance, []wfTypes.TaskRunner, error) {
appRev := h.currentAppRev
appLabels := map[string]string{
oam.LabelAppName: app.Name,
oam.LabelAppNamespace: app.Namespace,
@@ -118,7 +118,7 @@ func (h *AppHandler) GenerateApplicationSteps(ctx monitorContext.Context,
})
query.Install(handlerProviders, h.r.Client, nil)
instance := generateWorkflowInstance(af, app, appRev.Name)
instance := generateWorkflowInstance(af, app)
executor.InitializeWorkflowInstance(instance)
runners, err := generator.GenerateRunners(ctx, instance, wfTypes.StepGeneratorOptions{
Providers: handlerProviders,
@@ -143,7 +143,7 @@ func (h *AppHandler) GenerateApplicationSteps(ctx monitorContext.Context,
return instance, runners, nil
}
// needRestart check if application workflow need restart and return the desired
// CheckWorkflowRestart check if application workflow need restart and return the desired
// rev to be set in status
// 1. If workflow status is empty, it means no previous running record, the
// workflow will restart (cold start)
@@ -152,8 +152,8 @@ func (h *AppHandler) GenerateApplicationSteps(ctx monitorContext.Context,
// 3. If workflow status is not empty, the desired rev will be the
// ApplicationRevision name. For backward compatibility, the legacy style
// <rev>:<hash> will be recognized and reduced into <rev>
func needRestart(app *v1beta1.Application, revName string) (string, bool) {
desiredRev, currentRev := revName, ""
func (h *AppHandler) CheckWorkflowRestart(ctx monitorContext.Context, app *v1beta1.Application) {
desiredRev, currentRev := h.currentAppRev.Name, ""
if app.Status.Workflow != nil {
currentRev = app.Status.Workflow.AppRevision
}
@@ -166,10 +166,40 @@ func needRestart(app *v1beta1.Application, revName string) (string, bool) {
currentRev = currentRev[:idx]
}
}
return desiredRev, currentRev == "" || desiredRev != currentRev
if currentRev != "" && desiredRev == currentRev {
return
}
// record in revision
if h.latestAppRev != nil && h.latestAppRev.Status.Workflow == nil && app.Status.Workflow != nil {
app.Status.Workflow.Terminated = true
app.Status.Workflow.Finished = true
if app.Status.Workflow.EndTime.IsZero() {
app.Status.Workflow.EndTime = metav1.Now()
}
h.UpdateApplicationRevisionStatus(ctx, h.latestAppRev, app.Status.Workflow)
}
// clean recorded resources info.
app.Status.Services = nil
app.Status.AppliedResources = nil
// clean conditions after render
var reservedConditions []condition.Condition
for i, cond := range app.Status.Conditions {
condTpy, err := common.ParseApplicationConditionType(string(cond.Type))
if err == nil {
if condTpy <= common.RenderCondition {
reservedConditions = append(reservedConditions, app.Status.Conditions[i])
}
}
}
app.Status.Conditions = reservedConditions
app.Status.Workflow = &common.WorkflowStatus{
AppRevision: desiredRev,
}
}
func generateWorkflowInstance(af *appfile.Appfile, app *v1beta1.Application, appRev string) *wfTypes.WorkflowInstance {
func generateWorkflowInstance(af *appfile.Appfile, app *v1beta1.Application) *wfTypes.WorkflowInstance {
instance := &wfTypes.WorkflowInstance{
WorkflowMeta: wfTypes.WorkflowMeta{
Name: af.Name,
@@ -191,27 +221,6 @@ func generateWorkflowInstance(af *appfile.Appfile, app *v1beta1.Application, app
Steps: af.WorkflowSteps,
Mode: af.WorkflowMode,
}
if desiredRev, nr := needRestart(app, appRev); nr {
// clean recorded resources info.
app.Status.Services = nil
app.Status.AppliedResources = nil
// clean conditions after render
var reservedConditions []condition.Condition
for i, cond := range app.Status.Conditions {
condTpy, err := common.ParseApplicationConditionType(string(cond.Type))
if err == nil {
if condTpy <= common.RenderCondition {
reservedConditions = append(reservedConditions, app.Status.Conditions[i])
}
}
}
app.Status.Conditions = reservedConditions
app.Status.Workflow = &common.WorkflowStatus{
AppRevision: desiredRev,
}
return instance
}
status := app.Status.Workflow
instance.Status = workflowv1alpha1.WorkflowRunStatus{
Mode: *af.WorkflowMode,

View File

@@ -112,13 +112,15 @@ var _ = Describe("Test Application workflow generator", func() {
Expect(err).Should(BeNil())
_, err = af.GeneratePolicyManifests(context.Background())
Expect(err).Should(BeNil())
appRev := &oamcore.ApplicationRevision{}
handler, err := NewAppHandler(ctx, reconciler, app, appParser)
Expect(err).Should(Succeed())
logCtx := monitorContext.NewTraceContext(ctx, "")
_, taskRunner, err := handler.GenerateApplicationSteps(logCtx, app, appParser, af, appRev)
handler.currentAppRev = &oamcore.ApplicationRevision{}
handler.CheckWorkflowRestart(logCtx, app)
_, taskRunner, err := handler.GenerateApplicationSteps(logCtx, app, appParser, af)
Expect(err).To(BeNil())
Expect(len(taskRunner)).Should(BeEquivalentTo(2))
Expect(taskRunner[0].Name()).Should(BeEquivalentTo("myweb1"))
@@ -154,13 +156,14 @@ var _ = Describe("Test Application workflow generator", func() {
Expect(err).Should(BeNil())
_, err = af.GeneratePolicyManifests(context.Background())
Expect(err).Should(BeNil())
appRev := &oamcore.ApplicationRevision{}
handler, err := NewAppHandler(ctx, reconciler, app, appParser)
Expect(err).Should(Succeed())
logCtx := monitorContext.NewTraceContext(ctx, "")
_, taskRunner, err := handler.GenerateApplicationSteps(logCtx, app, appParser, af, appRev)
handler.currentAppRev = &oamcore.ApplicationRevision{}
handler.CheckWorkflowRestart(logCtx, app)
_, taskRunner, err := handler.GenerateApplicationSteps(logCtx, app, appParser, af)
Expect(err).To(BeNil())
Expect(len(taskRunner)).Should(BeEquivalentTo(2))
Expect(taskRunner[0].Name()).Should(BeEquivalentTo("myweb1"))
@@ -276,13 +279,14 @@ var _ = Describe("Test Application workflow generator", func() {
}
af, err := appParser.GenerateAppFile(ctx, app)
Expect(err).Should(BeNil())
appRev := &oamcore.ApplicationRevision{}
handler, err := NewAppHandler(ctx, reconciler, app, appParser)
Expect(err).Should(Succeed())
logCtx := monitorContext.NewTraceContext(ctx, "")
_, taskRunner, err := handler.GenerateApplicationSteps(logCtx, app, appParser, af, appRev)
handler.currentAppRev = &oamcore.ApplicationRevision{}
handler.CheckWorkflowRestart(logCtx, app)
_, taskRunner, err := handler.GenerateApplicationSteps(logCtx, app, appParser, af)
Expect(err).To(BeNil())
Expect(len(taskRunner)).Should(BeEquivalentTo(2))
Expect(taskRunner[0].Name()).Should(BeEquivalentTo("myweb1"))
@@ -317,13 +321,14 @@ var _ = Describe("Test Application workflow generator", func() {
}
af, err := appParser.GenerateAppFile(ctx, app)
Expect(err).Should(BeNil())
appRev := &oamcore.ApplicationRevision{}
handler, err := NewAppHandler(ctx, reconciler, app, appParser)
Expect(err).Should(Succeed())
logCtx := monitorContext.NewTraceContext(ctx, "")
_, _, err = handler.GenerateApplicationSteps(logCtx, app, appParser, af, appRev)
handler.currentAppRev = &oamcore.ApplicationRevision{}
handler.CheckWorkflowRestart(logCtx, app)
_, _, err = handler.GenerateApplicationSteps(logCtx, app, appParser, af)
Expect(err).NotTo(BeNil())
})
@@ -355,13 +360,14 @@ var _ = Describe("Test Application workflow generator", func() {
}
af, err := appParser.GenerateAppFile(ctx, app)
Expect(err).Should(BeNil())
appRev := &oamcore.ApplicationRevision{}
handler, err := NewAppHandler(ctx, reconciler, app, appParser)
Expect(err).Should(Succeed())
logCtx := monitorContext.NewTraceContext(ctx, "")
_, _, err = handler.GenerateApplicationSteps(logCtx, app, appParser, af, appRev)
handler.currentAppRev = &oamcore.ApplicationRevision{}
handler.CheckWorkflowRestart(logCtx, app)
_, _, err = handler.GenerateApplicationSteps(logCtx, app, appParser, af)
Expect(err).NotTo(BeNil())
})
})

View File

@@ -1019,11 +1019,11 @@ func (h historiesByComponentRevision) Less(i, j int) bool {
}
// UpdateApplicationRevisionStatus update application revision status
func (h *AppHandler) UpdateApplicationRevisionStatus(ctx context.Context, appRev *v1beta1.ApplicationRevision, succeed bool, wfStatus *common.WorkflowStatus) {
func (h *AppHandler) UpdateApplicationRevisionStatus(ctx context.Context, appRev *v1beta1.ApplicationRevision, wfStatus *common.WorkflowStatus) {
if appRev == nil || DisableAllApplicationRevision {
return
}
appRev.Status.Succeeded = succeed
appRev.Status.Succeeded = wfStatus.Phase == workflowv1alpha1.WorkflowStateSucceeded
appRev.Status.Workflow = wfStatus
// Versioned the context backend values.

View File

@@ -231,7 +231,7 @@ func createOrGetExisting(ctx context.Context, act *applyAction, c client.Client,
return nil, err
}
if act.readOnly {
return nil, fmt.Errorf("cannot create %s (%s) in read-only mode", desired.GetObjectKind().GroupVersionKind().Kind, desired.GetName())
return nil, fmt.Errorf("%s (%s) is marked as read-only but does not exist. You should check the existence of the resource or remove the read-only policy", desired.GetObjectKind().GroupVersionKind().Kind, desired.GetName())
}
if act.updateAnnotation {
if err := addLastAppliedConfigAnnotation(desired); err != nil {

View File

@@ -108,6 +108,15 @@ func init() {
}),
GroupResourceType: GroupResourceType{Group: "apps", Kind: "DaemonSet"},
},
ChildrenResourcesRule{
GroupResourceType: GroupResourceType{Group: "batch", Kind: "Job"},
SubResources: buildSubResources([]*SubResourceSelector{
{
ResourceType: ResourceType{APIVersion: "v1", Kind: "Pod"},
listOptions: defaultWorkloadLabelListOption,
},
}),
},
ChildrenResourcesRule{
GroupResourceType: GroupResourceType{Group: "", Kind: "Service"},
SubResources: buildSubResources([]*SubResourceSelector{

View File

@@ -72,8 +72,8 @@ func NewAddAddonRegistryCommand(c common.Args, ioStreams cmdutil.IOStreams) *cob
Short: "Add an addon registry.",
Long: "Add an addon registry.",
Example: `add a helm repo registry: vela addon registry add --type=helm my-repo --endpoint=<URL>
add a github registry: vela addon registry add my-repo --type git --endpoint=<URL> --path=<ptah> --token=<git token>"
add a gitlab registry: vela addon registry add my-repo --type gitlab --endpoint=<URL> --gitlabRepoName=<repoName> --path=<path> --token=<git token>`,
add a github registry: vela addon registry add my-repo --type git --endpoint=<URL> --path=<ptah> --gitToken=<git token>"
add a gitlab registry: vela addon registry add my-repo --type gitlab --endpoint=<URL> --gitlabRepoName=<repoName> --path=<path> --gitToken=<git token>`,
RunE: func(cmd *cobra.Command, args []string) error {
registry, err := getRegistryFromArgs(cmd, args)
if err != nil {

View File

@@ -32,7 +32,9 @@ import (
"helm.sh/helm/v3/pkg/release"
"helm.sh/helm/v3/pkg/releaseutil"
"helm.sh/helm/v3/pkg/storage"
appsv1 "k8s.io/api/apps/v1"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
apitypes "k8s.io/apimachinery/pkg/types"
@@ -44,6 +46,8 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/yaml"
"github.com/kubevela/pkg/util/k8s"
"github.com/kubevela/pkg/util/resourcetopology"
velaslices "github.com/kubevela/pkg/util/slices"
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
@@ -52,6 +56,7 @@ import (
"github.com/oam-dev/kubevela/apis/types"
velacmd "github.com/oam-dev/kubevela/pkg/cmd"
cmdutil "github.com/oam-dev/kubevela/pkg/cmd/util"
"github.com/oam-dev/kubevela/pkg/oam"
"github.com/oam-dev/kubevela/pkg/utils/apply"
"github.com/oam-dev/kubevela/pkg/utils/env"
"github.com/oam-dev/kubevela/pkg/utils/util"
@@ -71,6 +76,9 @@ const (
//go:embed adopt-templates/default.cue
var defaultAdoptTemplate string
//go:embed resource-topology/builtin-rule.cue
var defaultResourceTopologyRule string
var (
adoptTypes = []string{adoptTypeNative, adoptTypeHelm}
adoptModes = []string{adoptModeReadOnly, adoptModeTakeOver}
@@ -92,36 +100,49 @@ type AdoptOptions struct {
HelmReleaseName string
HelmReleaseNamespace string
HelmDriver string
HelmConfig *action.Configuration
HelmStore *storage.Storage
HelmRelease *release.Release
HelmReleases []*release.Release
HelmReleaseRevisions []*release.Release
NativeResourceRefs []*resourceRef
Apply bool
Recycle bool
Yes bool
All bool
AdoptTemplateFile string
AdoptTemplate string
AdoptTemplateCUEValue cue.Value
ResourceTopologyRuleFile string
ResourceTopologyRule string
AllGVKs []schema.GroupVersionKind
Resources []*unstructured.Unstructured `json:"resources"`
util.IOStreams
}
func (opt *AdoptOptions) parseResourceRef(f velacmd.Factory, cmd *cobra.Command, arg string) (*resourceRef, error) {
parts := strings.Split(arg, "/")
_, gr := schema.ParseResourceArg(parts[0])
func (opt *AdoptOptions) parseResourceGVK(f velacmd.Factory, arg string) (schema.GroupVersionKind, error) {
_, gr := schema.ParseResourceArg(arg)
gvks, err := f.Client().RESTMapper().KindsFor(gr.WithVersion(""))
if err != nil {
return nil, fmt.Errorf("failed to find types for resource %s: %w", arg, err)
return schema.GroupVersionKind{}, fmt.Errorf("failed to find types for resource %s: %w", arg, err)
}
if len(gvks) == 0 {
return nil, fmt.Errorf("no schema found for resource %s: %w", arg, err)
return schema.GroupVersionKind{}, fmt.Errorf("no schema found for resource %s: %w", arg, err)
}
return gvks[0], nil
}
func (opt *AdoptOptions) parseResourceRef(f velacmd.Factory, cmd *cobra.Command, arg string) (*resourceRef, error) {
parts := strings.Split(arg, "/")
gvk, err := opt.parseResourceGVK(f, parts[0])
if err != nil {
return nil, err
}
gvk := gvks[0]
mappings, err := f.Client().RESTMapper().RESTMappings(gvk.GroupKind(), gvk.Version)
if err != nil {
return nil, fmt.Errorf("failed to find mappings for resource %s: %w", arg, err)
@@ -149,6 +170,186 @@ func (opt *AdoptOptions) parseResourceRef(f velacmd.Factory, cmd *cobra.Command,
return or, nil
}
// Init .
func (opt *AdoptOptions) Init(f velacmd.Factory, cmd *cobra.Command, args []string) error {
if opt.All {
if len(args) > 0 {
for _, arg := range args {
gvk, err := opt.parseResourceGVK(f, arg)
if err != nil {
return err
}
opt.AllGVKs = append(opt.AllGVKs, gvk)
apiVersion, kind := gvk.ToAPIVersionAndKind()
fmt.Fprintf(opt.Out, "Adopt all %s/%s resources\n", apiVersion, kind)
}
}
if len(opt.AllGVKs) == 0 {
opt.AllGVKs = []schema.GroupVersionKind{
appsv1.SchemeGroupVersion.WithKind("Deployment"),
appsv1.SchemeGroupVersion.WithKind("StatefulSet"),
appsv1.SchemeGroupVersion.WithKind("DaemonSet"),
}
_, _ = opt.Out.Write([]byte("No arguments specified, adopt all Deployment/StatefulSet/DaemonSet resources by default\n"))
}
}
if opt.AdoptTemplateFile != "" {
bs, err := os.ReadFile(opt.AdoptTemplateFile)
if err != nil {
return fmt.Errorf("failed to load file %s", opt.AdoptTemplateFile)
}
opt.AdoptTemplate = string(bs)
} else {
opt.AdoptTemplate = defaultAdoptTemplate
}
if opt.ResourceTopologyRuleFile != "" {
bs, err := os.ReadFile(opt.ResourceTopologyRuleFile)
if err != nil {
return fmt.Errorf("failed to load file %s", opt.ResourceTopologyRuleFile)
}
opt.ResourceTopologyRule = string(bs)
} else {
opt.ResourceTopologyRule = defaultResourceTopologyRule
}
opt.AppNamespace = velacmd.GetNamespace(f, cmd)
opt.AdoptTemplateCUEValue = cuecontext.New().CompileString(fmt.Sprintf("%s\n\n%s: %s", opt.AdoptTemplate, adoptCUETempVal, adoptCUETempFunc))
switch opt.Type {
case adoptTypeNative:
if opt.Recycle {
return fmt.Errorf("native resource adoption does not support --recycle flag")
}
case adoptTypeHelm:
if len(opt.HelmDriver) == 0 {
opt.HelmDriver = os.Getenv(helmDriverEnvKey)
}
if len(opt.HelmDriver) == 0 {
opt.HelmDriver = defaultHelmDriver
}
actionConfig := new(action.Configuration)
opt.HelmReleaseNamespace = opt.AppNamespace
if err := actionConfig.Init(
util.NewRestConfigGetterByConfig(f.Config(), opt.HelmReleaseNamespace),
opt.HelmReleaseNamespace,
opt.HelmDriver,
klog.Infof); err != nil {
return err
}
opt.HelmConfig = actionConfig
default:
return fmt.Errorf("invalid adopt type: %s, available types: [%s]", opt.Type, strings.Join(adoptTypes, ", "))
}
if slices.Index(adoptModes, opt.Mode) < 0 {
return fmt.Errorf("invalid adopt mode: %s, available modes: [%s]", opt.Mode, strings.Join(adoptModes, ", "))
}
if opt.Recycle && !opt.Apply {
return fmt.Errorf("old data can only be recycled when the adoption application is applied")
}
return nil
}
// MultipleRun .
func (opt *AdoptOptions) MultipleRun(f velacmd.Factory, cmd *cobra.Command) error {
resources := make([][]*unstructured.Unstructured, 0)
releases := make([]*release.Release, 0)
var err error
ctx := context.Background()
matchLabels := metav1.LabelSelector{
MatchExpressions: []metav1.LabelSelectorRequirement{
{
Key: oam.LabelAppName,
Operator: metav1.LabelSelectorOpDoesNotExist,
},
},
}
selector, err := metav1.LabelSelectorAsSelector(&matchLabels)
if err != nil {
return err
}
switch opt.Type {
case adoptTypeNative:
for _, gvk := range opt.AllGVKs {
list := &unstructured.UnstructuredList{}
list.SetGroupVersionKind(gvk)
if err := f.Client().List(ctx, list, &client.ListOptions{Namespace: opt.AppNamespace, LabelSelector: selector}); err != nil {
apiVersion, kind := gvk.ToAPIVersionAndKind()
_, _ = fmt.Fprintf(opt.Out, "Warning: failed to list resources from %s/%s: %s", apiVersion, kind, err.Error())
continue
}
dedup := make([]k8s.ResourceIdentifier, 0)
for _, item := range list.Items {
engine := resourcetopology.New(opt.ResourceTopologyRule)
itemIdentifier := k8s.ResourceIdentifier{
Name: item.GetName(),
Namespace: item.GetNamespace(),
Kind: item.GetKind(),
APIVersion: item.GetAPIVersion(),
}
if velaslices.Contains(dedup, itemIdentifier) {
continue
}
firstElement := item
r := []*unstructured.Unstructured{&firstElement}
peers, err := engine.GetPeerResources(ctx, itemIdentifier)
if err != nil {
_, _ = fmt.Fprintf(opt.Out, "Warning: failed to get peer resources for %s/%s: %s", itemIdentifier.APIVersion, itemIdentifier.Kind, err.Error())
resources = append(resources, r)
continue
}
dedup = append(dedup, peers...)
for _, peer := range peers {
gvk, err := k8s.GetGVKFromResource(peer)
if err != nil {
_, _ = fmt.Fprintf(opt.Out, "Warning: failed to get gvk from resource %s/%s: %s", peer.APIVersion, peer.Kind, err.Error())
continue
}
peerResource := &unstructured.Unstructured{}
peerResource.SetGroupVersionKind(gvk)
if err := f.Client().Get(ctx, apitypes.NamespacedName{Namespace: peer.Namespace, Name: peer.Name}, peerResource); err != nil {
_, _ = fmt.Fprintf(opt.Out, "Warning: failed to get resource %s/%s: %s", peer.Namespace, peer.Name, err.Error())
continue
}
r = append(r, peerResource)
}
resources = append(resources, r)
}
}
case adoptTypeHelm:
releases, err = opt.HelmConfig.Releases.List(func(release *release.Release) bool {
return true
})
if err != nil {
return err
}
}
for _, r := range resources {
opt.Resources = r
opt.AppName = r[0].GetName()
opt.AppNamespace = r[0].GetNamespace()
if err := opt.Run(f, cmd); err != nil {
_, _ = fmt.Fprintf(opt.Out, "Error: failed to adopt %s/%s: %s", opt.AppNamespace, opt.AppName, err.Error())
continue
}
}
for _, r := range releases {
opt.AppName = r.Name
opt.AppNamespace = r.Namespace
opt.HelmReleaseName = r.Name
opt.HelmReleaseNamespace = r.Namespace
// TODO(fog): filter the helm that already adopted by vela
if err := opt.loadHelm(); err != nil {
_, _ = fmt.Fprintf(opt.Out, "Error: failed to load helm for %s/%s: %s", opt.AppNamespace, opt.AppName, err.Error())
continue
}
if err := opt.Run(f, cmd); err != nil {
_, _ = fmt.Fprintf(opt.Out, "Error: failed to adopt %s/%s: %s", opt.AppNamespace, opt.AppName, err.Error())
continue
}
}
return nil
}
// Complete autofill fields in opts
func (opt *AdoptOptions) Complete(f velacmd.Factory, cmd *cobra.Command, args []string) error {
opt.AppNamespace = velacmd.GetNamespace(f, cmd)
@@ -169,6 +370,9 @@ func (opt *AdoptOptions) Complete(f velacmd.Factory, cmd *cobra.Command, args []
if opt.AppNamespace == "" {
opt.AppNamespace = opt.NativeResourceRefs[0].Namespace
}
if err := opt.loadNative(f, cmd); err != nil {
return err
}
case adoptTypeHelm:
if len(args) > 0 {
opt.HelmReleaseName = args[0]
@@ -176,26 +380,13 @@ func (opt *AdoptOptions) Complete(f velacmd.Factory, cmd *cobra.Command, args []
if len(args) > 1 {
return fmt.Errorf("helm type adoption only support one helm release by far")
}
if len(opt.HelmDriver) == 0 {
opt.HelmDriver = os.Getenv(helmDriverEnvKey)
}
if len(opt.HelmDriver) == 0 {
opt.HelmDriver = defaultHelmDriver
}
if opt.AppName == "" {
opt.AppName = opt.HelmReleaseName
}
opt.HelmReleaseNamespace = opt.AppNamespace
default:
}
if opt.AdoptTemplateFile != "" {
bs, err := os.ReadFile(opt.AdoptTemplateFile)
if err != nil {
return fmt.Errorf("failed to load file %s", opt.AdoptTemplateFile)
if err := opt.loadHelm(); err != nil {
return err
}
opt.AdoptTemplate = string(bs)
} else {
opt.AdoptTemplate = defaultAdoptTemplate
default:
}
if opt.AppName != "" {
var ctx = context.Background()
@@ -225,21 +416,10 @@ func (opt *AdoptOptions) Validate() error {
if opt.AppName == "" {
return fmt.Errorf("app-name flag must be set for native resource adoption when multiple resources have different names")
}
if opt.Recycle {
return fmt.Errorf("native resource adoption does not support --recycle flag")
}
case adoptTypeHelm:
if len(opt.HelmReleaseName) == 0 {
return fmt.Errorf("helm release name must not be empty")
}
default:
return fmt.Errorf("invalid adopt type: %s, available types: [%s]", opt.Type, strings.Join(adoptTypes, ", "))
}
if slices.Index(adoptModes, opt.Mode) < 0 {
return fmt.Errorf("invalid adopt mode: %s, available modes: [%s]", opt.Mode, strings.Join(adoptModes, ", "))
}
if opt.Recycle && !opt.Apply {
return fmt.Errorf("old data can only be recycled when the adoption application is applied")
}
return nil
}
@@ -256,27 +436,18 @@ func (opt *AdoptOptions) loadNative(f velacmd.Factory, cmd *cobra.Command) error
return nil
}
func (opt *AdoptOptions) loadHelm(f velacmd.Factory) error {
actionConfig := new(action.Configuration)
err := actionConfig.Init(
util.NewRestConfigGetterByConfig(f.Config(), opt.HelmReleaseNamespace),
opt.HelmReleaseNamespace,
opt.HelmDriver,
klog.Infof)
if err != nil {
return err
}
opt.HelmStore = actionConfig.Releases
releases, err := opt.HelmStore.History(opt.HelmReleaseName)
func (opt *AdoptOptions) loadHelm() error {
opt.HelmStore = opt.HelmConfig.Releases
revisions, err := opt.HelmStore.History(opt.HelmReleaseName)
if err != nil {
return fmt.Errorf("helm release %s/%s not loaded: %w", opt.HelmReleaseNamespace, opt.HelmReleaseName, err)
}
if len(releases) == 0 {
if len(revisions) == 0 {
return fmt.Errorf("helm release %s/%s not found", opt.HelmReleaseNamespace, opt.HelmReleaseName)
}
releaseutil.SortByRevision(releases)
opt.HelmRelease = releases[len(releases)-1]
opt.HelmReleases = releases
releaseutil.SortByRevision(revisions)
opt.HelmRelease = revisions[len(revisions)-1]
opt.HelmReleaseRevisions = revisions
manifests := releaseutil.SplitManifests(opt.HelmRelease.Manifest)
var objs []*unstructured.Unstructured
for _, val := range manifests {
@@ -312,17 +483,6 @@ func (opt *AdoptOptions) render() (*v1beta1.Application, error) {
// Run collect resources, assemble into application and print/apply
func (opt *AdoptOptions) Run(f velacmd.Factory, cmd *cobra.Command) error {
switch opt.Type {
case adoptTypeNative:
if err := opt.loadNative(f, cmd); err != nil {
return fmt.Errorf("failed to load native resources: %w", err)
}
case adoptTypeHelm:
if err := opt.loadHelm(f); err != nil {
return fmt.Errorf("failed to load resources from helm release %s/%s: %w", opt.HelmReleaseNamespace, opt.HelmReleaseName, err)
}
default:
}
app, err := opt.render()
if err != nil {
return fmt.Errorf("failed to make adoption application for resources: %w", err)
@@ -337,6 +497,9 @@ func (opt *AdoptOptions) Run(f velacmd.Factory, cmd *cobra.Command) error {
if bs, err = yaml.Marshal(app); err != nil {
return fmt.Errorf("failed to encode application into YAML format: %w", err)
}
if opt.All {
_, _ = opt.Out.Write([]byte("\n---\n"))
}
_, _ = opt.Out.Write(bs)
}
if opt.Recycle && opt.Apply {
@@ -357,7 +520,7 @@ func (opt *AdoptOptions) Run(f velacmd.Factory, cmd *cobra.Command) error {
}
switch opt.Type {
case adoptTypeHelm:
for _, r := range opt.HelmReleases {
for _, r := range opt.HelmReleaseRevisions {
if _, err = opt.HelmStore.Delete(r.Name, r.Version); err != nil {
return fmt.Errorf("failed to clean up helm release: %w", err)
}
@@ -404,11 +567,21 @@ var (
the command and make your own assemble rules for the adoption application. You can
refer to https://github.com/kubevela/kubevela/blob/master/references/cli/adopt-templates/default.cue
to see the default implementation of adoption rules.
If you want to adopt all resources with resource topology rule to Applications,
you can use: 'vela adopt --all'. The resource topology rule can be customized by
'--resource-topology-rule' flag.
`))
adoptExample = templates.Examples(i18n.T(`
# Native Resources Adoption
## Adopt resources into new application
## Adopt all resources to Applications with resource topology rule
## Use: vela adopt <resources-type> --all
vela adopt --all
vela adopt deployment --all --resource-topology-rule myrule.cue
## Use: vela adopt <resources-type>[/<resource-namespace>]/<resource-name> <resources-type>[/<resource-namespace>]/<resource-name> ...
vela adopt deployment/my-app configmap/my-app
@@ -431,6 +604,11 @@ var (
# Helm Chart Adoption
## Adopt all helm releases to Applications with resource topology rule
## Use: vela adopt <resources-type> --all
vela adopt --all --type helm
vela adopt my-chart --all --resource-topology-rule myrule.cue --type helm
## Adopt resources in a deployed helm chart
vela adopt my-chart -n my-namespace --type helm
@@ -465,8 +643,12 @@ func NewAdoptCommand(f velacmd.Factory, streams util.IOStreams) *cobra.Command {
Annotations: map[string]string{
types.TagCommandType: types.TypeCD,
},
Args: cobra.MinimumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
cmdutil.CheckErr(o.Init(f, cmd, args))
if o.All {
cmdutil.CheckErr(o.MultipleRun(f, cmd))
return
}
cmdutil.CheckErr(o.Complete(f, cmd, args))
cmdutil.CheckErr(o.Validate())
cmdutil.CheckErr(o.Run(f, cmd))
@@ -476,10 +658,12 @@ func NewAdoptCommand(f velacmd.Factory, streams util.IOStreams) *cobra.Command {
cmd.Flags().StringVarP(&o.Mode, "mode", "m", o.Mode, fmt.Sprintf("The mode of adoption. Available values: [%s]", strings.Join(adoptModes, ", ")))
cmd.Flags().StringVarP(&o.AppName, "app-name", "", o.AppName, "The name of application for adoption. If empty for helm type adoption, it will inherit the helm chart's name.")
cmd.Flags().StringVarP(&o.AdoptTemplateFile, "adopt-template", "", o.AdoptTemplate, "The CUE template for adoption. If not provided, the default template will be used when --auto is switched on.")
cmd.Flags().StringVarP(&o.ResourceTopologyRuleFile, "resource-topology-rule", "", o.ResourceTopologyRule, "The CUE template for specify the rule of the resource topology. If not provided, the default rule will be used.")
cmd.Flags().StringVarP(&o.HelmDriver, "driver", "d", o.HelmDriver, "The storage backend of helm adoption. Only take effect when --type=helm.")
cmd.Flags().BoolVarP(&o.Apply, "apply", "", o.Apply, "If true, the application for adoption will be applied. Otherwise, it will only be printed.")
cmd.Flags().BoolVarP(&o.Recycle, "recycle", "", o.Recycle, "If true, when the adoption application is successfully applied, the old storage (like Helm secret) will be recycled.")
cmd.Flags().BoolVarP(&o.Yes, "yes", "y", o.Yes, "Skip confirmation prompt")
cmd.Flags().BoolVarP(&o.All, "all", "", o.All, "Adopt all resources in the namespace")
return velacmd.NewCommandBuilder(f, cmd).
WithNamespaceFlag().
WithResponsiveWriter().

View File

@@ -17,6 +17,7 @@ limitations under the License.
package cli
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
@@ -27,6 +28,11 @@ import (
)
func TestDefaultNamespace(t *testing.T) {
f := velacmd.NewDeferredFactory(config.GetConfig)
ioStream := util.IOStreams{}
ctx := context.Background()
cmd := NewAdoptCommand(f, ioStream)
cmd.SetContext(ctx)
testcase := []struct {
namespace string
args []string
@@ -46,10 +52,8 @@ func TestDefaultNamespace(t *testing.T) {
Type: adoptTypeNative,
Mode: adoptModeReadOnly,
}
f := velacmd.NewDeferredFactory(config.GetConfig)
ioStream := util.IOStreams{}
cmd := NewAdoptCommand(f, ioStream)
err := opt.Complete(f, cmd, c.args)
_ = cmd.Flags().Set(FlagNamespace, c.namespace)
err := opt.Init(f, cmd, c.args)
if err != nil {
t.Fatalf("failed to parse resourceRef: %v", err)
}

View File

@@ -19,6 +19,7 @@ package cli
import (
"context"
"fmt"
"regexp"
"strings"
"github.com/fatih/color"
@@ -34,6 +35,8 @@ import (
"github.com/oam-dev/kubevela/references/appfile"
)
var re = regexp.MustCompile(`"((?:[^"\\]|\\.)*)"`)
// NewLogsCommand creates `logs` command to tail logs of application
func NewLogsCommand(c common.Args, order string, ioStreams util.IOStreams) *cobra.Command {
largs := &Args{Args: c}
@@ -122,6 +125,10 @@ func (l *Args) printPodLogs(ctx context.Context, ioStreams util.IOStreams, selec
}
}
if show {
match := re.FindStringSubmatch(str)
if len(match) > 1 {
str = strings.ReplaceAll(match[1], "\\n", "\n")
}
ioStreams.Infonln(str)
}
case <-ctx.Done():

View File

@@ -0,0 +1,92 @@
rules: [
{
group: "apps"
resource: "deployment"
subResources: [
{
group: "apps"
resource: "replicaSet"
selectors: {
ownerReference: true
}
},
]
peerResources: commonPeerResources
}, {
group: "apps"
resource: "replicaSet"
subResources: [
{
group: ""
resource: "pod"
selectors: {
ownerReference: true
}
},
]
}, {
group: "apps"
resource: "statefulSet"
subResources: [
{
group: ""
resource: "pod"
selectors: {
ownerReference: true
}
},
]
peerResources: commonPeerResources
}, {
group: "apps"
resource: "daemonSet"
subResources: [
{
group: ""
resource: "pod"
selectors: {
ownerReference: true
}
},
]
peerResources: commonPeerResources
},
]
commonPeerResources: [{
group: ""
resource: "configMap"
selectors: {
name: [
if context.data.spec.template.spec.volumes != _|_ {
for v in context.data.spec.template.spec.volumes if v.configMap != _|_ if v.configMap.name != _|_ {
v.configMap.name
},
},
]
}
}, {
group: ""
resource: "secret"
selectors: {
name: [
if context.data.spec.template.spec.volumes != _|_ {
for v in context.data.spec.template.spec.volumes if v.secret != _|_ if v.secret.name != _|_ {
v.secret.name
},
},
]
}
}, {
group: ""
resource: "service"
selectors: {
builtin: "service"
}
}, {
group: "networking.k8s.io"
resource: "ingress"
selectors: {
builtin: "ingress"
}
}]

View File

@@ -291,7 +291,7 @@ func makeThemeConfigFileIfNotExist() bool {
if _, err := os.Open(filepath.Clean(themeConfigFilePath)); err != nil {
if os.IsNotExist(err) {
// make file if not exist
_ = os.MkdirAll(filepath.Clean(velaThemeHome), 0600)
_ = os.MkdirAll(filepath.Clean(velaThemeHome), 0700)
_ = os.WriteFile(filepath.Clean(themeConfigFilePath), []byte("name : "+DefaultTheme), 0600)
}
return false

View File

@@ -17,6 +17,8 @@ limitations under the License.
package config
import (
"os"
"strings"
"testing"
"github.com/gdamore/tcell/v2"
@@ -35,3 +37,11 @@ func TestColor(t *testing.T) {
c2 := Color("red")
assert.Equal(t, c2.Color(), tcell.GetColor("red").TrueColor())
}
func TestPersistentThemeConfig(t *testing.T) {
defer PersistentThemeConfig(DefaultTheme)
PersistentThemeConfig("foo")
bytes, err := os.ReadFile(themeConfigFilePath)
assert.Nil(t, err)
assert.True(t, strings.Contains(string(bytes), "foo"))
}

View File

@@ -243,6 +243,7 @@ type WorkflowArgs struct {
Writer io.Writer
Args common.Args
StepName string
StepID string
ErrMap map[string]string
App *v1beta1.Application
WorkflowRun *workflowv1alpha1.WorkflowRun
@@ -399,7 +400,7 @@ func (w *WorkflowArgs) printStepLogs(ctx context.Context, cli client.Client, ioS
return w.printResourceLogs(ctx, cli, ioStreams, []wfTypes.Resource{{
Namespace: types.DefaultKubeVelaNS,
LabelSelector: w.ControllerLabels,
}}, []string{fmt.Sprintf(`step_name="%s"`, w.StepName), fmt.Sprintf("%s/%s", w.WorkflowInstance.Namespace, w.WorkflowInstance.Name), "cue logs"})
}}, []string{fmt.Sprintf(`stepSessionID="%s"`, w.StepID), fmt.Sprintf("%s/%s", w.WorkflowInstance.Namespace, w.WorkflowInstance.Name), "cue logs"})
case logConfig.Source != nil:
if len(logConfig.Source.Resources) > 0 {
return w.printResourceLogs(ctx, cli, ioStreams, logConfig.Source.Resources, nil)
@@ -454,7 +455,8 @@ func (w *WorkflowArgs) selectWorkflowStep(msg string) error {
if err != nil {
return fmt.Errorf("failed to select step %s: %w", unwrapStepName(w.StepName), err)
}
w.StepName = unwrapStepID(stepName, w.WorkflowInstance)
w.StepName = unwrapStepName(stepName)
w.StepID = unwrapStepID(stepName, w.WorkflowInstance)
return nil
}

View File

@@ -22,6 +22,8 @@ metadata:
name: replica-webservice
namespace: vela-system
spec:
workload:
type: autodetects.core.oam.dev
schematic:
cue:
template: |

View File

@@ -49,7 +49,7 @@ var token string
const (
baseDomain = "http://127.0.0.1:8001"
baseURL = "http://127.0.0.1:8001/api/v1"
testNSprefix = "api-e2e-test-"
testNSprefix = "api-test-"
)
func TestE2eApiserverTest(t *testing.T) {

View File

@@ -7,6 +7,8 @@ metadata:
name: replica-webservice
namespace: vela-system
spec:
workload:
type: autodetects.core.oam.dev
schematic:
cue:
template: |

View File

@@ -14,19 +14,20 @@ gateway: {
}
if context.outputs.ingress.status.loadBalancer.ingress != _|_ {
let igs = context.outputs.ingress.status.loadBalancer.ingress
let host = context.outputs.ingress.spec.rules[0].host
if igs[0].ip != _|_ {
if igs[0].host != _|_ {
if host != _|_ {
message: "Visiting URL: " + context.outputs.ingress.spec.rules[0].host + ", IP: " + igs[0].ip
}
if igs[0].host == _|_ {
if host == _|_ {
message: "Host not specified, visit the cluster or load balancer in front of the cluster with IP: " + igs[0].ip
}
}
if igs[0].ip == _|_ {
if igs[0].host != _|_ {
if host != _|_ {
message: "Visiting URL: " + context.outputs.ingress.spec.rules[0].host
}
if igs[0].host != _|_ {
if host != _|_ {
message: "Host not specified, visit the cluster or load balancer in front of the cluster"
}
}

View File

@@ -326,7 +326,7 @@ template: {
envName: string
secretKey: string
}]
mountPath?: string
mountPath: string
subPath?: string
defaultMode: *420 | int
readOnly: *false | bool