Compare commits

...

12 Commits

Author SHA1 Message Date
github-actions[bot]
b11eb845b2 Fix: don't return err if subresource type is not found when listing application resources (#5311)
Signed-off-by: hnd4r7 <307365651@qq.com>
(cherry picked from commit 58a150d1d4)

Co-authored-by: hnd4r7 <307365651@qq.com>
2023-01-11 14:56:01 +08:00
github-actions[bot]
b12968c2ae fix: errorMsg when uninstall vela (#5309)
Signed-off-by: bitliu <bitliu@tencent.com>
(cherry picked from commit 771e0b5429)

Co-authored-by: bitliu <bitliu@tencent.com>
2023-01-11 14:48:54 +08:00
github-actions[bot]
d8d0c91c59 [Backport release-1.6] Fix: create a config with the same name reported an incorrect error (#5306)
* Fix: create a config with the same name reported an incorrect error

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

* Fix: create a config with the same name reported an incorrect error

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

Co-authored-by: wuzhongjian <wuzhongjian_yewu@cmss.chinamobile.com>
2023-01-11 14:24:47 +08:00
github-actions[bot]
5f6209e8de Fix: Delete appplication fails if status.workflow.endTime not specified. (#5296)
Error Details:
E0106 08:12:02.807341       1 controller.go:317] controller/application "msg"="Reconciler error" "error"="Application.core.oam.dev \"test\" is invalid: status.workflow.endTime: Invalid value: \"null\": status.workflow.endTime in body must be of type string: \"null\"" "name"="test" "namespace"="test" "reconciler group"="core.oam.dev" "reconciler kind"="Application"

If the workflow is not completed, the endtime should be null, and the deletion of the application will fail

Signed-off-by: old.prince <di7zhang@gmail.com>
(cherry picked from commit 16b6a02018)

Co-authored-by: old.prince <di7zhang@gmail.com>
2023-01-10 15:15:56 +08:00
github-actions[bot]
a198fa5f9a Test: let addon helper tests use local helm server (#5289)
Signed-off-by: Charlie Chiang <charlie_c_0129@outlook.com>
(cherry picked from commit 44eaa1d004)

Co-authored-by: Charlie Chiang <charlie_c_0129@outlook.com>
2023-01-09 13:30:37 +08:00
github-actions[bot]
f01639e175 Fix: keep the workflow data structure in MongoDB (#5283)
Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
(cherry picked from commit 035d668837)

Co-authored-by: barnettZQG <barnett.zqg@gmail.com>
2023-01-06 15:13:42 +08:00
Tianxin Dong
b24b52b651 Chore: update workflow vendor to fix certain bugs in 1.6 (#5254)
Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>

Signed-off-by: FogDong <dongtianxin.tx@alibaba-inc.com>
2023-01-03 16:12:19 +08:00
github-actions[bot]
ae91006a3d Fix:Dry-run from revision application,Problems caused by resource version lower than the current version (#5250)
Signed-off-by: old.prince <di7zhang@gmail.com>
(cherry picked from commit d5fcb04147)

Co-authored-by: oldprince <di7zhang@gmail.com>
2023-01-03 11:37:20 +08:00
Somefive
42d6791476 Fix: gc failure cause workflow restart not working properly (#5242)
Signed-off-by: Somefive <yd219913@alibaba-inc.com>

Signed-off-by: Somefive <yd219913@alibaba-inc.com>
2022-12-30 18:10:38 +08:00
github-actions[bot]
c85502e54a Fix: remove useless field when loading pod in top (#5230)
Signed-off-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
(cherry picked from commit 8582ae7d93)

Co-authored-by: Qiaozp <qiaozhongpei.qzp@alibaba-inc.com>
2022-12-26 13:17:56 +08:00
github-actions[bot]
f9a6b22294 Fix: addon ls comman does not show the componentless application (#5204)
Signed-off-by: zhaohuihui <zhaohuihui_yewu@cmss.chinamobile.com>
(cherry picked from commit 50f6347050)

Co-authored-by: zhaohuihui <zhaohuihui_yewu@cmss.chinamobile.com>
2022-12-19 13:23:43 +08:00
github-actions[bot]
5085a99a12 [Backport release-1.6] Feat: rollout support statefulsets (#5203)
* rollout support workload

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

* modify the error output

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

Co-authored-by: suwanliang_yewu <suwanliang_yewu@cmss.chinamobile.com>
2022-12-19 12:10:08 +08:00
27 changed files with 266 additions and 49 deletions

View File

@@ -333,7 +333,8 @@ type WorkflowStatus struct {
Steps []workflowv1alpha1.WorkflowStepStatus `json:"steps,omitempty"`
StartTime metav1.Time `json:"startTime,omitempty"`
EndTime metav1.Time `json:"endTime,omitempty"`
// +nullable
EndTime metav1.Time `json:"endTime,omitempty"`
}
// DefinitionType describes the type of DefinitionRevision.

View File

@@ -844,6 +844,7 @@ spec:
type: object
endTime:
format: date-time
nullable: true
type: string
finished:
type: boolean
@@ -2759,6 +2760,7 @@ spec:
type: object
endTime:
format: date-time
nullable: true
type: string
finished:
type: boolean
@@ -4813,6 +4815,7 @@ spec:
type: object
endTime:
format: date-time
nullable: true
type: string
finished:
type: boolean

View File

@@ -768,6 +768,7 @@ spec:
type: object
endTime:
format: date-time
nullable: true
type: string
finished:
type: boolean
@@ -1530,6 +1531,7 @@ spec:
type: object
endTime:
format: date-time
nullable: true
type: string
finished:
type: boolean

View File

@@ -844,6 +844,7 @@ spec:
type: object
endTime:
format: date-time
nullable: true
type: string
finished:
type: boolean
@@ -2759,6 +2760,7 @@ spec:
type: object
endTime:
format: date-time
nullable: true
type: string
finished:
type: boolean
@@ -4813,6 +4815,7 @@ spec:
type: object
endTime:
format: date-time
nullable: true
type: string
finished:
type: boolean

View File

@@ -768,6 +768,7 @@ spec:
type: object
endTime:
format: date-time
nullable: true
type: string
finished:
type: boolean
@@ -1530,6 +1531,7 @@ spec:
type: object
endTime:
format: date-time
nullable: true
type: string
finished:
type: boolean

2
go.mod
View File

@@ -58,7 +58,7 @@ require (
github.com/koding/websocketproxy v0.0.0-20181220232114-7ed82d81a28c
github.com/kubevela/pkg v0.0.0-20221024115939-a103acee6db2
github.com/kubevela/prism v1.5.1-0.20220915071949-6bf3ad33f84f
github.com/kubevela/workflow v0.3.3
github.com/kubevela/workflow v0.3.4-0.20230103040208-bca032d481ed
github.com/kyokomi/emoji v2.2.4+incompatible
github.com/mitchellh/hashstructure/v2 v2.0.1
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd

4
go.sum
View File

@@ -1337,8 +1337,8 @@ github.com/kubevela/pkg v0.0.0-20221024115939-a103acee6db2 h1:C3cAfrxst1+dIWgLLh
github.com/kubevela/pkg v0.0.0-20221024115939-a103acee6db2/go.mod h1:TgIGEB/r0NOy63Jzem7WsL3AIr34l+ClH9dmPqcZ4d4=
github.com/kubevela/prism v1.5.1-0.20220915071949-6bf3ad33f84f h1:1lUtU1alPThdcsn4MI6XjPb7eJLuZPpmlEdgjtnUMKw=
github.com/kubevela/prism v1.5.1-0.20220915071949-6bf3ad33f84f/go.mod h1:m724/7ANnB/iukyHW20+DicpeJMEC/JA0ZhgsHY10MA=
github.com/kubevela/workflow v0.3.3 h1:NSbQGcABWJIzUV5wfWFJsrO/ffZ4mCVfofUtUHCTojQ=
github.com/kubevela/workflow v0.3.3/go.mod h1:5jfZ8T1m/En44wDGRf2YqCSlODfEnAV+9PnzoLoDlFs=
github.com/kubevela/workflow v0.3.4-0.20230103040208-bca032d481ed h1:VGeEvL/XOkwADhLS4Upz5zEM6Enjw4yx8JU3Z+UUqXw=
github.com/kubevela/workflow v0.3.4-0.20230103040208-bca032d481ed/go.mod h1:5jfZ8T1m/En44wDGRf2YqCSlODfEnAV+9PnzoLoDlFs=
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=

View File

@@ -844,6 +844,7 @@ spec:
type: object
endTime:
format: date-time
nullable: true
type: string
finished:
type: boolean
@@ -2759,6 +2760,7 @@ spec:
type: object
endTime:
format: date-time
nullable: true
type: string
finished:
type: boolean
@@ -4813,6 +4815,7 @@ spec:
type: object
endTime:
format: date-time
nullable: true
type: string
finished:
type: boolean

View File

@@ -769,6 +769,7 @@ spec:
type: object
endTime:
format: date-time
nullable: true
type: string
finished:
type: boolean
@@ -1531,6 +1532,7 @@ spec:
type: object
endTime:
format: date-time
nullable: true
type: string
finished:
type: boolean

View File

@@ -17,9 +17,12 @@ limitations under the License.
package addon
import (
"bytes"
"context"
"errors"
"net/http"
"net/http/httptest"
"os"
"strings"
v1 "k8s.io/api/core/v1"
@@ -29,6 +32,38 @@ import (
. "github.com/onsi/gomega"
)
func setupMockServer() *httptest.Server {
var listenURL string
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
fileList := []string{
"index.yaml",
"fluxcd-test-version-1.0.0.tgz",
"fluxcd-test-version-2.0.0.tgz",
"vela-workflow-v0.3.5.tgz",
"foo-v1.0.0.tgz",
"bar-v1.0.0.tgz",
"bar-v2.0.0.tgz",
"mock-be-dep-addon-v1.0.0.tgz",
}
for _, f := range fileList {
if strings.Contains(req.URL.Path, f) {
file, err := os.ReadFile("../../e2e/addon/mock/testrepo/helm-repo/" + f)
if err != nil {
_, _ = w.Write([]byte(err.Error()))
}
if f == "index.yaml" {
// in index.yaml, url is hardcoded to 127.0.0.1:9098,
// so we need to replace it with the real random listen url
file = bytes.ReplaceAll(file, []byte("http://127.0.0.1:9098"), []byte(listenURL))
}
_, _ = w.Write(file)
}
}
}))
listenURL = s.URL
return s
}
var _ = Describe("test FindAddonPackagesDetailFromRegistry", func() {
Describe("when no registry is added, no matter what you do, it will just return error", func() {
Context("when empty addonNames and registryNames is supplied", func() {
@@ -50,12 +85,15 @@ var _ = Describe("test FindAddonPackagesDetailFromRegistry", func() {
})
Describe("one versioned registry is added", func() {
var s *httptest.Server
BeforeEach(func() {
// Prepare KubeVela registry
s = setupMockServer()
// Prepare registry
reg := &Registry{
Name: "KubeVela",
Name: "addon_helper_test",
Helm: &HelmSource{
URL: "https://addons.kubevela.net",
URL: s.URL,
},
}
ds := NewRegistryDataStore(k8sClient)
@@ -63,38 +101,36 @@ var _ = Describe("test FindAddonPackagesDetailFromRegistry", func() {
})
AfterEach(func() {
// Clean up KubeVela registry
// Clean up registry
ds := NewRegistryDataStore(k8sClient)
Expect(ds.DeleteRegistry(context.Background(), "KubeVela")).To(Succeed())
Expect(ds.DeleteRegistry(context.Background(), "addon_helper_test")).To(Succeed())
s.Close()
})
Context("when empty addonNames and registryNames is supplied", func() {
It("should return error, empty addonNames are not allowed", func() {
_, err := FindAddonPackagesDetailFromRegistry(context.Background(), k8sClient, []string{}, []string{"KubeVela"})
_, err := FindAddonPackagesDetailFromRegistry(context.Background(), k8sClient, []string{}, []string{"addon_helper_test"})
Expect(err).To(HaveOccurred())
})
It("should return error, empty addonNames are not allowed", func() {
_, err := FindAddonPackagesDetailFromRegistry(context.Background(), k8sClient, nil, []string{"KubeVela"})
_, err := FindAddonPackagesDetailFromRegistry(context.Background(), k8sClient, nil, []string{"addon_helper_test"})
Expect(err).To(HaveOccurred())
})
})
Context("one existing addon name provided", func() {
It("should return one valid result, matching all registries", func() {
res, err := FindAddonPackagesDetailFromRegistry(context.Background(), k8sClient, []string{"velaux"}, nil)
res, err := FindAddonPackagesDetailFromRegistry(context.Background(), k8sClient, []string{"foo"}, nil)
Expect(err).To(Succeed())
Expect(res).To(HaveLen(1))
Expect(res[0].Name).To(Equal("velaux"))
Expect(res[0].InstallPackage).ToNot(BeNil())
Expect(res[0].APISchema).ToNot(BeNil())
Expect(res[0].Name).To(Equal("foo"))
})
It("should return one valid result, matching one registry", func() {
res, err := FindAddonPackagesDetailFromRegistry(context.Background(), k8sClient, []string{"velaux"}, []string{"KubeVela"})
res, err := FindAddonPackagesDetailFromRegistry(context.Background(), k8sClient, []string{"foo"}, []string{"addon_helper_test"})
Expect(err).To(Succeed())
Expect(res).To(HaveLen(1))
Expect(res[0].Name).To(Equal("velaux"))
Expect(res[0].InstallPackage).ToNot(BeNil())
Expect(res[0].APISchema).ToNot(BeNil())
Expect(res[0].Name).To(Equal("foo"))
})
})
@@ -108,26 +144,20 @@ var _ = Describe("test FindAddonPackagesDetailFromRegistry", func() {
Context("two existing addon names provided", func() {
It("should return two valid result", func() {
res, err := FindAddonPackagesDetailFromRegistry(context.Background(), k8sClient, []string{"velaux", "traefik"}, nil)
res, err := FindAddonPackagesDetailFromRegistry(context.Background(), k8sClient, []string{"foo", "bar"}, nil)
Expect(err).To(Succeed())
Expect(res).To(HaveLen(2))
Expect(res[0].Name).To(Equal("velaux"))
Expect(res[0].InstallPackage).ToNot(BeNil())
Expect(res[0].APISchema).ToNot(BeNil())
Expect(res[1].Name).To(Equal("traefik"))
Expect(res[1].InstallPackage).ToNot(BeNil())
Expect(res[1].APISchema).ToNot(BeNil())
Expect(res[0].Name).To(Equal("foo"))
Expect(res[1].Name).To(Equal("bar"))
})
})
Context("one existing addon name and one non-existent addon name provided", func() {
It("should return only one valid result", func() {
res, err := FindAddonPackagesDetailFromRegistry(context.Background(), k8sClient, []string{"velaux", "non-existent-addon"}, nil)
res, err := FindAddonPackagesDetailFromRegistry(context.Background(), k8sClient, []string{"foo", "non-existent-addon"}, nil)
Expect(err).To(Succeed())
Expect(res).To(HaveLen(1))
Expect(res[0].Name).To(Equal("velaux"))
Expect(res[0].InstallPackage).ToNot(BeNil())
Expect(res[0].APISchema).ToNot(BeNil())
Expect(res[0].Name).To(Equal("foo"))
})
})
})

View File

@@ -50,7 +50,7 @@ type Workflow struct {
// WorkflowStep defines how to execute a workflow step.
type WorkflowStep struct {
WorkflowStepBase `json:",inline"`
WorkflowStepBase `json:",inline" bson:",inline"`
SubSteps []WorkflowStepBase `json:"subSteps,omitempty"`
}
@@ -123,7 +123,7 @@ type WorkflowRecord struct {
// WorkflowStepStatus is the workflow step status database model
type WorkflowStepStatus struct {
StepStatus `json:",inline"`
StepStatus `json:",inline" bson:",inline"`
SubStepsStatus []StepStatus `json:"subSteps,omitempty"`
}

View File

@@ -1513,6 +1513,13 @@ func (c *applicationServiceImpl) DryRunAppOrRevision(ctx context.Context, appMod
}
case "REVISION":
app, _, err = c.getAppModelFromRevision(ctx, appModel.Name, dryRunReq.Version)
originalApp := &v1beta1.Application{}
if err := c.KubeClient.Get(ctx, types.NamespacedName{
Name: app.Name,
Namespace: app.Namespace,
}, originalApp); err == nil {
app.ResourceVersion = originalApp.ResourceVersion
}
if err != nil {
return nil, err
}

View File

@@ -137,6 +137,14 @@ func (u *configServiceImpl) CreateConfig(ctx context.Context, project string, re
return nil, err
}
}
exist, err := u.Factory.IsExist(ctx, ns, req.Name)
if err != nil {
klog.Errorf("check config name is exist failure %s", err.Error())
return nil, bcode.ErrConfigExist
}
if exist {
return nil, bcode.ErrConfigExist
}
var properties = make(map[string]interface{})
if err := json.Unmarshal([]byte(req.Properties), &properties); err != nil {
return nil, err
@@ -156,9 +164,6 @@ func (u *configServiceImpl) CreateConfig(ctx context.Context, project string, re
return nil, err
}
if err := u.Factory.CreateOrUpdateConfig(ctx, configItem, ns); err != nil {
if errors.Is(err, config.ErrConfigExist) {
return nil, bcode.ErrConfigExist
}
return nil, err
}
return convertConfig(project, *configItem), nil
@@ -196,9 +201,12 @@ func (u *configServiceImpl) UpdateConfig(ctx context.Context, project string, na
return nil, err
}
if err := u.Factory.CreateOrUpdateConfig(ctx, configItem, ns); err != nil {
if errors.Is(err, config.ErrConfigExist) {
if errors.Is(err, config.ErrChangeTemplate) {
return nil, bcode.ErrChangeTemplate
}
if errors.Is(err, config.ErrChangeSecretType) {
return nil, bcode.ErrChangeSecretType
}
return nil, err
}
return convertConfig(project, *configItem), nil

View File

@@ -741,7 +741,6 @@ func pipelineStep2WorkflowStep(step model.WorkflowStep) v1alpha1.WorkflowStep {
func pipelineSpec2WorkflowSpec(spec model.WorkflowSpec) *v1alpha1.WorkflowSpec {
res := &v1alpha1.WorkflowSpec{
Mode: spec.Mode,
Steps: make([]v1alpha1.WorkflowStep, 0),
}
for _, step := range spec.Steps {

View File

@@ -37,4 +37,7 @@ var (
// ErrNotFoundDistribution means the distribution is not exist
ErrNotFoundDistribution = NewBcode(404, 16007, "the distribution is not exist")
// ErrChangeSecretType the secret type of the config can not be change
ErrChangeSecretType = NewBcode(400, 16008, "the secret type of the config can not be change")
)

View File

@@ -88,6 +88,12 @@ var ErrConfigNotFound = errors.New("the config is not exist")
// ErrTemplateNotFound means the template is not exist
var ErrTemplateNotFound = errors.New("the template is not exist")
// ErrChangeTemplate means the template of the config can not be change
var ErrChangeTemplate = errors.New("the template of the config can not be change")
// ErrChangeSecretType means the secret type of the config can not be change
var ErrChangeSecretType = errors.New("the secret type of the config can not be change")
// NamespacedName the namespace and name model
type NamespacedName struct {
Name string `json:"name"`
@@ -192,6 +198,7 @@ type Factory interface {
ListConfigs(ctx context.Context, namespace, template, scope string, withStatus bool) ([]*Config, error)
DeleteConfig(ctx context.Context, namespace, name string) error
CreateOrUpdateConfig(ctx context.Context, i *Config, ns string) error
IsExist(ctx context.Context, namespace, name string) (bool, error)
CreateOrUpdateDistribution(ctx context.Context, ns, name string, ads *CreateDistributionSpec) error
ListDistributions(ctx context.Context, ns string) ([]*Distribution, error)
@@ -549,7 +556,10 @@ func (k *kubeConfigFactory) CreateOrUpdateConfig(ctx context.Context, i *Config,
var secret v1.Secret
if err := k.cli.Get(ctx, pkgtypes.NamespacedName{Namespace: i.Namespace, Name: i.Name}, &secret); err == nil {
if secret.Labels[types.LabelConfigType] != i.Template.Name {
return ErrConfigExist
return ErrChangeTemplate
}
if secret.Type != i.Secret.Type {
return ErrChangeSecretType
}
}
if err := k.apiApply.Apply(ctx, i.Secret, apply.Quiet()); err != nil {
@@ -571,6 +581,17 @@ func (k *kubeConfigFactory) CreateOrUpdateConfig(ctx context.Context, i *Config,
return nil
}
func (k *kubeConfigFactory) IsExist(ctx context.Context, namespace, name string) (bool, error) {
var secret v1.Secret
if err := k.cli.Get(ctx, pkgtypes.NamespacedName{Namespace: namespace, Name: name}, &secret); err != nil {
if apierrors.IsNotFound(err) {
return false, nil
}
return false, err
}
return true, nil
}
func (k *kubeConfigFactory) ListConfigs(ctx context.Context, namespace, template, scope string, withStatus bool) ([]*Config, error) {
var list = &v1.SecretList{}
requirement := fmt.Sprintf("%s=%s", types.LabelConfigCatalog, types.VelaCoreConfig)

View File

@@ -145,6 +145,12 @@ var _ = Describe("test config factory", func() {
Expect(len(config.Targets)).Should(Equal(1))
})
It("check if the config exist", func() {
exist, err := fac.IsExist(context.TODO(), "default", "db-config")
Expect(err).Should(BeNil())
Expect(exist).Should(BeTrue())
})
It("list the distributions", func() {
distributions, err := fac.ListDistributions(context.TODO(), "default")
Expect(err).Should(BeNil())

View File

@@ -302,6 +302,11 @@ func (r *Reconciler) gcResourceTrackers(logCtx monitorContext.Context, handler *
}))
defer subCtx.Commit("finish gc resourceTrackers")
statusUpdater := r.patchStatus
if isUpdate {
statusUpdater = r.updateStatus
}
var options []resourcekeeper.GCOption
if !gcOutdated {
options = append(options, resourcekeeper.DisableMarkStageGCOption{}, resourcekeeper.DisableGCComponentRevisionOption{}, resourcekeeper.DisableLegacyGCOption{})
@@ -309,8 +314,10 @@ func (r *Reconciler) gcResourceTrackers(logCtx monitorContext.Context, handler *
finished, waiting, err := handler.resourceKeeper.GarbageCollect(logCtx, options...)
if err != nil {
logCtx.Error(err, "Failed to gc resourcetrackers")
r.Recorder.Event(handler.app, event.Warning(velatypes.ReasonFailedGC, err))
return r.endWithNegativeCondition(logCtx, handler.app, condition.ReconcileError(err), phase)
cond := condition.Deleting()
cond.Message = fmt.Sprintf("error encountered during garbage collection: %s", err.Error())
handler.app.Status.SetConditions(cond)
return r.result(statusUpdater(logCtx, handler.app, phase)).ret()
}
if !finished {
logCtx.Info("GarbageCollecting resourcetrackers unfinished")
@@ -319,13 +326,10 @@ func (r *Reconciler) gcResourceTrackers(logCtx monitorContext.Context, handler *
cond.Message = fmt.Sprintf("Waiting for %s to delete. (At least %d resources are deleting.)", waiting[0].DisplayName(), len(waiting))
}
handler.app.Status.SetConditions(cond)
return r.result(r.patchStatus(logCtx, handler.app, phase)).requeue(baseGCBackoffWaitTime).ret()
return r.result(statusUpdater(logCtx, handler.app, phase)).requeue(baseGCBackoffWaitTime).ret()
}
logCtx.Info("GarbageCollected resourcetrackers")
if isUpdate {
return r.result(r.updateStatus(logCtx, handler.app, phase)).ret()
}
return r.result(r.patchStatus(logCtx, handler.app, phase)).ret()
return r.result(statusUpdater(logCtx, handler.app, phase)).ret()
}
type reconcileResult struct {

View File

@@ -114,6 +114,7 @@ func HandleReplicas(ctx context.Context, rolloutComp string, c client.Client) as
klog.InfoS("assemble force set workload replicas to 0", "Kind", u.GetKind(), "name", u.GetName())
return nil
}
klog.Errorf("fail to get workload %s: %v", u.GetName(), err)
return err
}
// the workload already exist, we cannot reset the replicas with manifest
@@ -122,6 +123,7 @@ func HandleReplicas(ctx context.Context, rolloutComp string, c client.Client) as
wlpv := fieldpath.Pave(workload.UnstructuredContent())
replicas, err := wlpv.GetInteger(replicasFieldPath)
if err != nil {
klog.Errorf("fail to get `spec.replicas` field from workload %s: %v", u.GetName(), err)
return err
}
if err = pv.SetNumber(replicasFieldPath, float64(replicas)); err != nil {

View File

@@ -25,6 +25,7 @@ import (
appsv1 "k8s.io/api/apps/v1"
v12 "k8s.io/api/core/v1"
kerrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@@ -908,7 +909,7 @@ func iterateListSubResources(ctx context.Context, cluster string, k8sClient clie
clusterCTX := multicluster.ContextWithClusterName(ctx, cluster)
items, err := listItemByRule(clusterCTX, k8sClient, resource, *parentObject, specifiedFunc, rule.DefaultGenListOptionFunc, rule.DisableFilterByOwnerReference)
if err != nil {
if meta.IsNoMatchError(err) || runtime.IsNotRegisteredError(err) {
if meta.IsNoMatchError(err) || runtime.IsNotRegisteredError(err) || kerrors.IsNotFound(err) {
klog.Warningf("ignore list resources: %s as %v", resource.Kind, err)
continue
}

View File

@@ -99,6 +99,15 @@ func buildApplicationListTable(ctx context.Context, c client.Reader, namespace s
service[s.Name] = s
}
if len(a.Spec.Components) == 0 {
if AllNamespace {
table.AddRow(a.Namespace, a.Name, "", "", "", a.Status.Phase, "", "", a.CreationTimestamp)
} else {
table.AddRow(a.Name, "", "", "", a.Status.Phase, "", "", a.CreationTimestamp)
}
continue
}
for idx, cmp := range a.Spec.Components {
var appName = a.Name
if idx > 0 {

View File

@@ -95,7 +95,6 @@ func LoadPodDetail(cfg *rest.Config, pod *v1.Pod) Pod {
podInfo := Pod{
Name: pod.Name,
Namespace: pod.Namespace,
Cluster: pod.ClusterName,
Ready: readyContainerNum(pod),
Status: string(pod.Status.Phase),
Age: utils.TimeFormat(time.Since(pod.CreationTimestamp.Time)),

View File

@@ -80,7 +80,7 @@ func NewUnInstallCommand(c common.Args, order string, ioStreams util.IOStreams)
return errors.Wrapf(err, "cannot check installed addon")
}
if len(addons) != 0 {
return fmt.Errorf("these addons have been eanbled :%v, please guarantee there is no application using these addons and use `vela uninstall -f` uninstall include addon ", addons)
return fmt.Errorf("these addons have been enabled :%v, please guarantee there is no application using these addons and use `vela uninstall -f` uninstall include addon ", addons)
}
}

View File

@@ -49,6 +49,8 @@ rules:
- apiGroups:
- "apps"
resources:
- statefulsets
- statefulsets/status
- deployments
- deployments/status
- controllerrevisions

View File

@@ -153,7 +153,7 @@ var _ = Describe("Test the rest api about the config", func() {
Expect(config.Secret).Should(BeNil())
Expect(config.Properties["registry"]).Should(Equal("kubevela.test.com"))
By("the template is not exist")
By("the config name is exist")
req = v1.CreateConfigRequest{
Name: "test-registry",
Alias: "Test Registry",
@@ -162,6 +162,17 @@ var _ = Describe("Test the rest api about the config", func() {
Properties: `{"registry": "kubevela.test.com"}`,
}
res = post("/configs", req)
Expect(res.StatusCode).Should(Equal(400))
By("the template is not exist")
req = v1.CreateConfigRequest{
Name: "test-registry2",
Alias: "Test Registry",
Description: "This is a demo config",
Template: v1.NamespacedName{Name: templateName + "notfound"},
Properties: `{"registry": "kubevela.test.com"}`,
}
res = post("/configs", req)
Expect(res.StatusCode).Should(Equal(404))
By("without the template")

View File

@@ -714,5 +714,87 @@ var _ = Describe("Test multicluster scenario", func() {
Expect(cm.Data["cluster"]).Should(Equal("cluster-worker"))
Expect(k8sClient.Delete(hubCtx, def)).Should(Succeed())
})
It("Test application with failed gc and restart workflow", func() {
By("duplicate cluster")
secret := &corev1.Secret{}
const secretName = "disconnection-test"
Expect(k8sClient.Get(hubCtx, types.NamespacedName{Namespace: kubevelatypes.DefaultKubeVelaNS, Name: WorkerClusterName}, secret)).Should(Succeed())
secret.SetName(secretName)
secret.SetResourceVersion("")
Expect(k8sClient.Create(hubCtx, secret)).Should(Succeed())
defer func() {
_ = k8sClient.Delete(hubCtx, secret)
}()
By("create cluster normally")
bs, err := os.ReadFile("./testdata/app/app-disconnection-test.yaml")
Expect(err).Should(Succeed())
app := &v1beta1.Application{}
Expect(yaml.Unmarshal(bs, app)).Should(Succeed())
app.SetNamespace(namespace)
Expect(k8sClient.Create(hubCtx, app)).Should(Succeed())
key := client.ObjectKeyFromObject(app)
Eventually(func(g Gomega) {
g.Expect(k8sClient.Get(hubCtx, key, app)).Should(Succeed())
g.Expect(app.Status.Phase).Should(Equal(common.ApplicationRunning))
}).WithTimeout(10 * time.Second).WithPolling(2 * time.Second).Should(Succeed())
By("disconnect cluster")
Expect(k8sClient.Get(hubCtx, types.NamespacedName{Namespace: kubevelatypes.DefaultKubeVelaNS, Name: secretName}, secret)).Should(Succeed())
secret.Data["endpoint"] = []byte("https://1.2.3.4:9999")
Expect(k8sClient.Update(hubCtx, secret)).Should(Succeed())
By("update application")
Expect(k8sClient.Get(hubCtx, key, app)).Should(Succeed())
app.Spec.Policies = nil
Expect(k8sClient.Update(hubCtx, app)).Should(Succeed())
Eventually(func(g Gomega) {
g.Expect(k8sClient.Get(hubCtx, key, app)).Should(Succeed())
g.Expect(app.Status.ObservedGeneration).Should(Equal(app.Generation))
g.Expect(app.Status.Phase).Should(Equal(common.ApplicationRunning))
rts := &v1beta1.ResourceTrackerList{}
g.Expect(k8sClient.List(hubCtx, rts, client.MatchingLabels{oam.LabelAppName: key.Name, oam.LabelAppNamespace: key.Namespace})).Should(Succeed())
cnt := 0
for _, item := range rts.Items {
if item.Spec.Type == v1beta1.ResourceTrackerTypeVersioned {
cnt++
}
}
g.Expect(cnt).Should(Equal(2))
}).WithTimeout(10 * time.Second).WithPolling(2 * time.Second).Should(Succeed())
By("try update application again")
Expect(k8sClient.Get(hubCtx, key, app)).Should(Succeed())
if app.Annotations == nil {
app.Annotations = map[string]string{}
}
app.Annotations[oam.AnnotationPublishVersion] = "test"
Expect(k8sClient.Update(hubCtx, app)).Should(Succeed())
Eventually(func(g Gomega) {
g.Expect(k8sClient.Get(hubCtx, key, app)).Should(Succeed())
g.Expect(app.Status.LatestRevision).ShouldNot(BeNil())
g.Expect(app.Status.LatestRevision.Revision).Should(Equal(int64(3)))
g.Expect(app.Status.ObservedGeneration).Should(Equal(app.Generation))
g.Expect(app.Status.Phase).Should(Equal(common.ApplicationRunning))
}).WithTimeout(1 * time.Minute).WithPolling(2 * time.Second).Should(Succeed())
By("clear disconnection cluster secret")
Expect(k8sClient.Get(hubCtx, types.NamespacedName{Namespace: kubevelatypes.DefaultKubeVelaNS, Name: secretName}, secret)).Should(Succeed())
Expect(k8sClient.Delete(hubCtx, secret)).Should(Succeed())
By("wait gc application completed")
Eventually(func(g Gomega) {
rts := &v1beta1.ResourceTrackerList{}
g.Expect(k8sClient.List(hubCtx, rts, client.MatchingLabels{oam.LabelAppName: key.Name, oam.LabelAppNamespace: key.Namespace})).Should(Succeed())
cnt := 0
for _, item := range rts.Items {
if item.Spec.Type == v1beta1.ResourceTrackerTypeVersioned {
cnt++
}
}
g.Expect(cnt).Should(Equal(1))
}).WithTimeout(30 * time.Second).WithPolling(2 * time.Second).Should(Succeed())
})
})
})

View File

@@ -0,0 +1,17 @@
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: app-disconnection-test
spec:
components:
- type: k8s-objects
name: app-dis-cm
properties:
objects:
- apiVersion: v1
kind: ConfigMap
policies:
- type: topology
name: disconnection-test
properties:
clusters: ["disconnection-test"]