Fix: refactor workflow and fix some e2e tests (#2272)

* Fix: add e2e plugin test back

* Fix: e2e rollout test and try change port to 37081

* Fix: add rollout plan test back

* Refactor: change the workflow state machine and add workflow succeed state

* Refactor: refine definition controller and fix e2e of app revision

* Refactor: unlock all the normal cases

* Fix: add helm schematic logic back into workflow
This commit is contained in:
Jianbo Sun
2021-09-13 14:17:12 +08:00
committed by GitHub
parent af01349f28
commit cad21c5138
65 changed files with 533 additions and 430 deletions
+1 -1
View File
@@ -82,7 +82,7 @@ jobs:
- name: Wait for e2e preparation ready
run: |
timeout 60 bash -c 'while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:38081/api/components)" != "200" ]]; do sleep 5; done' || false
timeout 60 bash -c 'while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:37081/api/components)" != "200" ]]; do sleep 5; done' || false
- name: Run api e2e tests
run: make e2e-api-test
+1 -1
View File
@@ -82,7 +82,7 @@ jobs:
- name: Wait for e2e preparation ready
run: |
timeout 60 bash -c 'while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:38081/api/components)" != "200" ]]; do sleep 5; done' || false
timeout 60 bash -c 'while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:37081/api/components)" != "200" ]]; do sleep 5; done' || false
- name: Run api e2e tests
run: make e2e-api-test
+3 -3
View File
@@ -95,8 +95,8 @@ compress:
)
# Run against the configured Kubernetes cluster in ~/.kube/config
run: fmt vet
go run ./cmd/core/main.go
run:
go run ./cmd/core/main.go --application-revision-limit 5
# Run go fmt against code
fmt: goimports installcue
@@ -316,5 +316,5 @@ endif
check-license-header:
./hack/licence/header-check.sh
check-install-def:
def-install:
./hack/utils/installdefinition.sh
+29 -7
View File
@@ -163,18 +163,38 @@ type ApplicationPhase string
const (
// ApplicationRollingOut means the app is in the middle of rolling out
ApplicationRollingOut ApplicationPhase = "rollingOut"
// ApplicationStarting means the app is preparing for reconcile
ApplicationStarting ApplicationPhase = "starting"
// ApplicationRendering means the app is rendering
ApplicationRendering ApplicationPhase = "rendering"
// ApplicationPolicyGenerating means the app is generating policies
ApplicationPolicyGenerating ApplicationPhase = "generatingPolicy"
// ApplicationRunningWorkflow means the app is running workflow
ApplicationRunningWorkflow ApplicationPhase = "runningWorkflow"
// ApplicationWorkflowSuspending means the app's workflow is suspending
ApplicationWorkflowSuspending ApplicationPhase = "workflowSuspending"
// ApplicationWorkflowTerminated means the app's workflow is terminated
ApplicationWorkflowTerminated ApplicationPhase = "workflowTerminated"
// ApplicationWorkflowFinished means the app's workflow is finished
ApplicationWorkflowFinished ApplicationPhase = "workflowFinished"
// ApplicationRunning means the app finished rendering and applied result to the cluster
ApplicationRunning ApplicationPhase = "running"
// ApplicationHealthChecking means the app finished rendering and applied result to the cluster, but still unhealthy
ApplicationHealthChecking ApplicationPhase = "healthChecking"
// ApplicationUnhealthy means the app finished rendering and applied result to the cluster, but still unhealthy
ApplicationUnhealthy ApplicationPhase = "unhealthy"
)
// WorkflowState is a string that mark the workflow state
type WorkflowState string
const (
// WorkflowStateTerminated means workflow is terminated manually, and it won't be started unless the spec changed.
WorkflowStateTerminated WorkflowState = "terminated"
// WorkflowStateSuspended means workflow is suspended manually, and it can be resumed.
WorkflowStateSuspended WorkflowState = "suspended"
// WorkflowStateFinished means workflow is running successfully, all steps finished.
WorkflowStateFinished WorkflowState = "finished"
// WorkflowStateExecuting means workflow is still running or waiting some steps.
WorkflowStateExecuting WorkflowState = "executing"
)
// ApplicationComponentStatus record the health status of App component
@@ -272,11 +292,13 @@ type AppStatus struct {
// WorkflowStatus record the status of workflow
type WorkflowStatus struct {
AppRevision string `json:"appRevision,omitempty"`
Mode WorkflowMode `json:"mode"`
Suspend bool `json:"suspend"`
Terminated bool `json:"terminated"`
ContextBackend *corev1.ObjectReference `json:"contextBackend"`
AppRevision string `json:"appRevision,omitempty"`
Mode WorkflowMode `json:"mode"`
Suspend bool `json:"suspend"`
Terminated bool `json:"terminated"`
ContextBackend *corev1.ObjectReference `json:"contextBackend,omitempty"`
Steps []WorkflowStepStatus `json:"steps,omitempty"`
}
+8 -7
View File
@@ -38,13 +38,14 @@ const (
// event message for Application
const (
MessageParsed = "Parsed successfully"
MessageRendered = "Rendered successfully"
MessageRevisioned = "Revisioned successfully"
MessageApplied = "Applied successfully"
MessageHealthCheck = "Health checked healthy"
MessageDeployed = "Deployed successfully"
MessageRollout = "Rollout successfully"
MessageParsed = "Parsed successfully"
MessageRendered = "Rendered successfully"
MessageRevisioned = "Revisioned successfully"
MessageApplied = "Applied successfully"
MessageWorkflowFinished = "Workflow finished"
MessageHealthCheck = "Health checked healthy"
MessageDeployed = "Deployed successfully"
MessageRollout = "Rollout successfully"
MessageFailedParse = "fail to parse application, err: %v"
MessageFailedRender = "fail to render application, err: %v"
@@ -1041,7 +1041,6 @@ spec:
terminated:
type: boolean
required:
- contextBackend
- mode
- suspend
- terminated
@@ -3115,7 +3114,6 @@ spec:
terminated:
type: boolean
required:
- contextBackend
- mode
- suspend
- terminated
@@ -709,7 +709,6 @@ spec:
terminated:
type: boolean
required:
- contextBackend
- mode
- suspend
- terminated
@@ -1493,7 +1492,6 @@ spec:
terminated:
type: boolean
required:
- contextBackend
- mode
- suspend
- terminated
@@ -1152,7 +1152,6 @@ spec:
terminated:
type: boolean
required:
- contextBackend
- mode
- suspend
- terminated
@@ -41,9 +41,9 @@ spec:
echo "Waiting application is ready..."
echo "waiting for application being Applied"
kubectl -n vela-system wait --for=condition=Applied applications.core.oam.dev helm-test-vela-app --timeout=3m
echo "application being Applied"
echo "waiting for application being Ready"
kubectl -n vela-system wait --for=condition=Ready applications.core.oam.dev helm-test-vela-app --timeout=3m
echo "application is Ready"
# wait for deploy being created
echo "waiting for deployment being available"
+1 -1
View File
@@ -82,7 +82,7 @@ make core-install
To ensure you have created vela-system namespace and install definitions of necessary module.
you can run the command:
```shell script
make check-install-def
make def-install
```
And then run locally:
+5
View File
@@ -122,6 +122,7 @@ var _ = BeforeSuite(func(done Done) {
var _ = AfterSuite(func() {
By("delete application and definitions")
Expect(k8sClient.Delete(ctx, &app)).Should(BeNil())
Expect(k8sClient.Delete(ctx, &testCdDef)).Should(BeNil())
Expect(k8sClient.Delete(ctx, &testCdDefWithHelm)).Should(BeNil())
@@ -131,4 +132,8 @@ var _ = AfterSuite(func() {
Expect(k8sClient.Delete(ctx, &testTdDefWithKube)).Should(BeNil())
Expect(k8sClient.Delete(ctx, &testShowCdDef)).Should(BeNil())
Expect(k8sClient.Delete(ctx, &testShowTdDef)).Should(BeNil())
_ = os.RemoveAll("definitions/")
_ = os.Remove("dry-run-app.yaml")
_ = os.Remove("live-diff-app.yaml")
})
+42 -14
View File
@@ -35,7 +35,7 @@ var _ = Describe("Test Kubectl Plugin", func() {
componentDefName := "test-webservice"
traitDefName := "test-ingress"
PContext("Test kubectl vela dry-run", func() {
Context("Test kubectl vela dry-run", func() {
It("Test dry-run application use definitions which applied to the cluster", func() {
By("check definitions which application used whether applied to the cluster")
var cd v1beta1.ComponentDefinition
@@ -65,7 +65,7 @@ var _ = Describe("Test Kubectl Plugin", func() {
})
})
PContext("Test kubectl vela live-diff", func() {
Context("Test kubectl vela live-diff", func() {
applicationName := "test-vela-app"
It("Test live-diff application use definition which applied to the cluster", func() {
@@ -90,6 +90,12 @@ var _ = Describe("Test Kubectl Plugin", func() {
return err
}, 5*time.Second).Should(BeNil())
Eventually(func() bool {
var tempApp v1beta1.Application
_ = k8sClient.Get(ctx, client.ObjectKey{Namespace: "default", Name: app.Name}, &tempApp)
return tempApp.Status.LatestRevision != nil
}, 20*time.Second).Should(BeTrue())
By("live-diff application")
err := os.WriteFile("live-diff-app.yaml", []byte(newApplication), 0644)
Expect(err).NotTo(HaveOccurred())
@@ -99,13 +105,19 @@ var _ = Describe("Test Kubectl Plugin", func() {
})
It("Test dry-run application use definitions in local", func() {
Eventually(func() bool {
var tempApp v1beta1.Application
_ = k8sClient.Get(ctx, client.ObjectKey{Namespace: "default", Name: app.Name}, &tempApp)
return tempApp.Status.LatestRevision != nil
}, 20*time.Second).Should(BeTrue())
output, err := e2e.Exec("kubectl-vela live-diff -f live-diff-app.yaml -d definitions")
Expect(err).NotTo(HaveOccurred())
Expect(output).Should(ContainSubstring(livediffResult))
})
})
PContext("Test kubectl vela show", func() {
Context("Test kubectl vela show", func() {
It("Test show componentDefinition reference", func() {
cdName := "test-show-task"
output, err := e2e.Exec(fmt.Sprintf("kubectl-vela show %s", cdName))
@@ -161,7 +173,7 @@ var _ = Describe("Test Kubectl Plugin", func() {
})
})
PContext("Test kubectl vela comp discover", func() {
Context("Test kubectl vela comp discover", func() {
It("Test list components in local registry", func() {
output, err := e2e.Exec("kubectl-vela comp --discover --url=" + testRegistryPath)
Expect(err).NotTo(HaveOccurred())
@@ -169,7 +181,7 @@ var _ = Describe("Test Kubectl Plugin", func() {
Expect(output).Should(ContainSubstring("fake-workload"))
})
})
PContext("Test kubectl vela trait discover", func() {
Context("Test kubectl vela trait discover", func() {
It("Test list traits in local registry", func() {
output, err := e2e.Exec("kubectl-vela trait --discover --url=" + testRegistryPath)
Expect(err).NotTo(HaveOccurred())
@@ -177,7 +189,7 @@ var _ = Describe("Test Kubectl Plugin", func() {
Expect(output).Should(ContainSubstring("dynamic-sa"))
})
})
PContext("Test kubectl vela comp and trait install", func() {
Context("Test kubectl vela comp and trait install", func() {
It("Test install a sample component", func() {
output, err := e2e.Exec("kubectl-vela comp get cloneset --url=" + testRegistryPath)
Expect(err).NotTo(HaveOccurred())
@@ -189,7 +201,7 @@ var _ = Describe("Test Kubectl Plugin", func() {
Expect(output).Should(ContainSubstring("Successfully install trait: init-container"))
})
})
PContext("Test kubectl vela list installed comp and trait", func() {
Context("Test kubectl vela list installed comp and trait", func() {
It("Test list installed component", func() {
output, err := e2e.Exec("kubectl-vela comp --url=" + testRegistryPath)
Expect(err).NotTo(HaveOccurred())
@@ -201,7 +213,7 @@ var _ = Describe("Test Kubectl Plugin", func() {
Expect(output).Should(ContainSubstring("init-container"))
})
})
PContext("Test uninstall vela trait", func() {
Context("Test uninstall vela trait", func() {
It("Clean the sample component", func() {
cmd := exec.Command("kubectl", "delete", "componentDefinition", "cloneset", "-n", "vela-system")
output, err := cmd.Output()
@@ -696,10 +708,12 @@ var dryRunResult = `---
apiVersion: apps/v1
kind: Deployment
metadata:
annotations: {}
labels:
app.oam.dev/appRevision: ""
app.oam.dev/component: express-server
app.oam.dev/name: test-vela-app
app.oam.dev/resourceType: WORKLOAD
workload.oam.dev/type: test-webservice
name: express-server
namespace: default
@@ -722,10 +736,12 @@ spec:
apiVersion: v1
kind: Service
metadata:
annotations: {}
labels:
app.oam.dev/appRevision: ""
app.oam.dev/component: express-server
app.oam.dev/name: test-vela-app
app.oam.dev/resourceType: TRAIT
trait.oam.dev/resource: service
trait.oam.dev/type: test-ingress
name: express-server
@@ -741,10 +757,12 @@ spec:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations: {}
labels:
app.oam.dev/appRevision: ""
app.oam.dev/component: express-server
app.oam.dev/name: test-vela-app
app.oam.dev/resourceType: TRAIT
trait.oam.dev/resource: ingress
trait.oam.dev/type: test-ingress
name: express-server
@@ -760,8 +778,6 @@ spec:
path: /
---
`
var livediffResult = `---
@@ -770,8 +786,6 @@ var livediffResult = `---
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
- annotations:
- oam.dev/kubevela-version: UNKNOWN
creationTimestamp: null
- finalizers:
- - app.oam.dev/resource-tracker-finalizer
@@ -810,11 +824,15 @@ var livediffResult = `---
- apiVersion: apps/v1
- kind: Deployment
- metadata:
- annotations: {}
- labels:
- app.oam.dev/appRevision: ""
- app.oam.dev/component: express-server
- app.oam.dev/name: test-vela-app
- app.oam.dev/resourceType: WORKLOAD
- workload.oam.dev/type: test-webservice
- name: express-server
- namespace: default
- spec:
- selector:
- matchLabels:
@@ -836,13 +854,16 @@ var livediffResult = `---
- apiVersion: v1
- kind: Service
- metadata:
- annotations: {}
- labels:
- app.oam.dev/appRevision: ""
- app.oam.dev/component: express-server
- app.oam.dev/name: test-vela-app
- app.oam.dev/resourceType: TRAIT
- trait.oam.dev/resource: service
- trait.oam.dev/type: test-ingress
- name: express-server
- namespace: default
- spec:
- ports:
- - port: 80
@@ -856,13 +877,16 @@ var livediffResult = `---
- apiVersion: networking.k8s.io/v1beta1
- kind: Ingress
- metadata:
- annotations: {}
- labels:
- app.oam.dev/appRevision: ""
- app.oam.dev/component: express-server
- app.oam.dev/name: test-vela-app
- app.oam.dev/resourceType: TRAIT
- trait.oam.dev/resource: ingress
- trait.oam.dev/type: test-ingress
- name: express-server
- namespace: default
- spec:
- rules:
- - host: testsvc.example.com
@@ -879,10 +903,12 @@ var livediffResult = `---
+ apiVersion: apps/v1
+ kind: Deployment
+ metadata:
+ annotations: {}
+ labels:
+ app.oam.dev/appRevision: ""
+ app.oam.dev/component: new-express-server
+ app.oam.dev/name: test-vela-app
+ app.oam.dev/resourceType: WORKLOAD
+ workload.oam.dev/type: test-webservice
+ name: new-express-server
+ namespace: default
@@ -912,10 +938,12 @@ var livediffResult = `---
+ apiVersion: v1
+ kind: Service
+ metadata:
+ annotations: {}
+ labels:
+ app.oam.dev/appRevision: ""
+ app.oam.dev/component: new-express-server
+ app.oam.dev/name: test-vela-app
+ app.oam.dev/resourceType: TRAIT
+ trait.oam.dev/resource: service
+ trait.oam.dev/type: test-ingress
+ name: new-express-server
@@ -933,10 +961,12 @@ var livediffResult = `---
+ apiVersion: networking.k8s.io/v1beta1
+ kind: Ingress
+ metadata:
+ annotations: {}
+ labels:
+ app.oam.dev/appRevision: ""
+ app.oam.dev/component: new-express-server
+ app.oam.dev/name: test-vela-app
+ app.oam.dev/resourceType: TRAIT
+ trait.oam.dev/resource: ingress
+ trait.oam.dev/type: test-ingress
+ name: new-express-server
@@ -950,8 +980,6 @@ var livediffResult = `---
+ serviceName: new-express-server
+ servicePort: 8080
+ path: /
`
var testShowComponentDef = `
+6
View File
@@ -21,6 +21,12 @@ function check_install() {
rm $file
mv $file".bak" $file
done
cd -
}
check_install
DEF_PATH="charts/vela-core/templates/definitions"
check_install
@@ -1041,7 +1041,6 @@ spec:
terminated:
type: boolean
required:
- contextBackend
- mode
- suspend
- terminated
@@ -3115,7 +3114,6 @@ spec:
terminated:
type: boolean
required:
- contextBackend
- mode
- suspend
- terminated
@@ -954,7 +954,6 @@ spec:
terminated:
type: boolean
required:
- contextBackend
- mode
- suspend
- terminated
@@ -2003,7 +2002,6 @@ spec:
terminated:
type: boolean
required:
- contextBackend
- mode
- suspend
- terminated
@@ -1152,7 +1152,6 @@ spec:
terminated:
type: boolean
required:
- contextBackend
- mode
- suspend
- terminated
+2 -1
View File
@@ -353,9 +353,9 @@ func (af *Appfile) assembleWorkload(wl *unstructured.Unstructured, compName stri
// use component name as workload name
// override the name set in render phase if exist
wl.SetName(compName)
af.setNamespace(wl)
af.setWorkloadLabels(wl, labels)
af.filterAndSetAnnotations(wl)
af.setNamespace(wl)
}
/* NOTE a workload has these possible labels
@@ -785,6 +785,7 @@ func generateComponentFromHelmModule(wl *Workload, appName, revision, ns string)
ExternalRevision: wl.ExternalRevision,
StandardWorkload: &unstructured.Unstructured{},
}
if wl.FullTemplate.Reference.Type != types.AutoDetectWorkloadDefinition {
compManifest, err = generateComponentFromCUEModule(wl, appName, revision, ns)
if err != nil {
+6 -1
View File
@@ -36,6 +36,11 @@ var (
DefaultIntervalDuration = &metav1.Duration{Duration: 5 * time.Minute}
)
// ConstructHelmReleaseName will format helm release name in a fixed way
func ConstructHelmReleaseName(appName, compName string) string {
return appName + "-" + compName
}
// RenderHelmReleaseAndHelmRepo constructs HelmRelease and HelmRepository in unstructured format
func RenderHelmReleaseAndHelmRepo(helmSpec *common.Helm, compName, appName, ns string, values map[string]interface{}) (*unstructured.Unstructured, *unstructured.Unstructured, error) {
releaseSpec, repoSpec, err := decodeHelmSpec(helmSpec)
@@ -57,7 +62,7 @@ func RenderHelmReleaseAndHelmRepo(helmSpec *common.Helm, compName, appName, ns s
}
// construct unstructured HelmRelease object
rlsName := fmt.Sprintf("%s-%s", appName, compName)
rlsName := ConstructHelmReleaseName(appName, compName)
helmRelease := commonutil.GenerateUnstructuredObj(rlsName, ns, helmapi.HelmReleaseGVK)
// construct HelmRelease chart values
+2 -2
View File
@@ -260,7 +260,7 @@ func (p *Parser) makeWorkload(ctx context.Context, name, typ string, capType typ
}
func (p *Parser) makeWorkloadFromRevision(name, typ string, capType types.CapType, props runtime.RawExtension, appRev *v1beta1.ApplicationRevision) (*Workload, error) {
templ, err := LoadTemplateFromRevision(typ, capType, appRev)
templ, err := LoadTemplateFromRevision(typ, capType, appRev, p.dm)
if err != nil {
return nil, errors.WithMessagef(err, "fetch component/policy type of %s from revision", name)
}
@@ -373,7 +373,7 @@ func (p *Parser) parseTrait(ctx context.Context, name string, properties map[str
}
func (p *Parser) parseTraitFromRevision(name string, properties map[string]interface{}, appRev *v1beta1.ApplicationRevision) (*Trait, error) {
templ, err := LoadTemplateFromRevision(name, types.TypeTrait, appRev)
templ, err := LoadTemplateFromRevision(name, types.TypeTrait, appRev, p.dm)
if err != nil {
return nil, err
}
+14 -1
View File
@@ -149,7 +149,7 @@ func LoadTemplate(ctx context.Context, dm discoverymapper.DiscoveryMapper, cli c
}
// LoadTemplateFromRevision will load Definition template from app revision
func LoadTemplateFromRevision(capName string, capType types.CapType, apprev *v1beta1.ApplicationRevision) (*Template, error) {
func LoadTemplateFromRevision(capName string, capType types.CapType, apprev *v1beta1.ApplicationRevision, dm discoverymapper.DiscoveryMapper) (*Template, error) {
if apprev == nil {
return nil, errors.Errorf("fail to find template for %s as app revision is empty", capName)
}
@@ -165,6 +165,19 @@ func LoadTemplateFromRevision(capName string, capType types.CapType, apprev *v1b
if err != nil {
return nil, err
}
gvk, err := oamutil.GetGVKFromDefinition(dm, wd.Spec.Reference)
if err != nil {
return nil, errors.WithMessagef(err, "Get GVK from workload definition [%s]", capName)
}
tmpl.Reference = common.WorkloadTypeDescriptor{
Definition: common.WorkloadGVK{
APIVersion: metav1.GroupVersion{
Group: gvk.Group,
Version: gvk.Version,
}.String(),
Kind: gvk.Kind,
},
}
return tmpl, nil
}
tmpl, err := newTemplateOfCompDefinition(cd.DeepCopy())
@@ -21,12 +21,13 @@ import (
"fmt"
"time"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/crossplane/crossplane-runtime/pkg/event"
"github.com/crossplane/crossplane-runtime/pkg/meta"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
kerrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/klog/v2"
ctrl "sigs.k8s.io/controller-runtime"
@@ -109,20 +110,17 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
}
endReconcile, err := r.handleFinalizers(ctx, app)
if err != nil {
return r.endWithNegativeCondition(ctx, app, condition.ReconcileError(err))
return r.endWithNegativeCondition(ctx, app, condition.ReconcileError(err), common.ApplicationStarting)
}
if endReconcile {
return ctrl.Result{}, nil
}
// parse application to appfile
app.Status.Phase = common.ApplicationRendering
appFile, err := appParser.GenerateAppFile(ctx, app)
if err != nil {
klog.ErrorS(err, "Failed to parse application", "application", klog.KObj(app))
r.Recorder.Event(app, event.Warning(velatypes.ReasonFailedParse, err))
return r.endWithNegativeCondition(ctx, app, condition.ErrorCondition("Parsed", err))
return r.endWithNegativeCondition(ctx, app, condition.ErrorCondition("Parsed", err), common.ApplicationRendering)
}
app.Status.SetConditions(condition.ReadyCondition("Parsed"))
r.Recorder.Event(app, event.Normal(velatypes.ReasonParsed, velatypes.MessageParsed))
@@ -130,103 +128,92 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
if err := handler.PrepareCurrentAppRevision(ctx, appFile); err != nil {
klog.ErrorS(err, "Failed to prepare app revision", "application", klog.KObj(app))
r.Recorder.Event(app, event.Warning(velatypes.ReasonFailedRevision, err))
return r.endWithNegativeCondition(ctx, app, condition.ErrorCondition("Revision", err))
return r.endWithNegativeCondition(ctx, app, condition.ErrorCondition("Revision", err), common.ApplicationRendering)
}
if err := handler.FinalizeAndApplyAppRevision(ctx); err != nil {
klog.ErrorS(err, "Failed to apply app revision", "application", klog.KObj(app))
r.Recorder.Event(app, event.Warning(velatypes.ReasonFailedRevision, err))
return r.endWithNegativeCondition(ctx, app, condition.ErrorCondition("Revision", err))
return r.endWithNegativeCondition(ctx, app, condition.ErrorCondition("Revision", err), common.ApplicationRendering)
}
klog.Info("Successfully prepare current app revision", "revisionName", handler.currentAppRev.Name,
"revisionHash", handler.currentRevHash, "isNewRevision", handler.isNewRevision)
app.Status.SetConditions(condition.ReadyCondition("Revision"))
r.Recorder.Event(app, event.Normal(velatypes.ReasonRevisoned, velatypes.MessageRevisioned))
if err := handler.UpdateAppLatestRevisionStatus(ctx); err != nil {
klog.ErrorS(err, "Failed to update application status", "application", klog.KObj(app))
return r.endWithNegativeCondition(ctx, app, condition.ReconcileError(err), common.ApplicationRendering)
}
klog.Info("Successfully apply application revision", "application", klog.KObj(app))
policies, err := appFile.PrepareWorkflowAndPolicy()
if err != nil {
klog.Error(err, "[Handle PrepareWorkflowAndPolicy]")
r.Recorder.Event(app, event.Warning(velatypes.ReasonFailedRender, err))
return r.endWithNegativeCondition(ctx, app, condition.ErrorCondition("PrepareWorkflowAndPolicy", err))
return r.endWithNegativeCondition(ctx, app, condition.ErrorCondition("PrepareWorkflowAndPolicy", err), common.ApplicationPolicyGenerating)
}
if len(policies) > 0 {
if err := handler.Dispatch(ctx, "", common.PolicyResourceCreator, policies...); err != nil {
klog.Error(err, "[Handle ApplyPolicyResources]")
r.Recorder.Event(app, event.Warning(velatypes.ReasonFailedApply, err))
return r.endWithNegativeCondition(ctx, app, condition.ErrorCondition("ApplyPolices", err))
return r.endWithNegativeCondition(ctx, app, condition.ErrorCondition("ApplyPolices", err), common.ApplicationPolicyGenerating)
}
klog.InfoS("Successfully generated application policies", "application", klog.KObj(app))
}
app.Status.SetConditions(condition.ReadyCondition("Render"))
r.Recorder.Event(app, event.Normal(velatypes.ReasonRendered, velatypes.MessageRendered))
klog.InfoS("Successfully render application resources", "application", klog.KObj(app))
if !appWillRollout(app) {
steps, err := handler.GenerateApplicationSteps(ctx, app, appParser, appFile, handler.currentAppRev, r.Client, r.dm, r.pd)
if err != nil {
klog.Error(err, "[handle workflow]")
r.Recorder.Event(app, event.Warning(velatypes.ReasonFailedWorkflow, err))
return r.endWithNegativeCondition(ctx, app, condition.ErrorCondition("Workflow", err))
return r.endWithNegativeCondition(ctx, app, condition.ErrorCondition("Workflow", err), common.ApplicationRunningWorkflow)
}
done, pause, err := workflow.NewWorkflow(app, r.Client, appFile.WorkflowMode).ExecuteSteps(ctx, handler.currentAppRev, steps)
workflowState, err := workflow.NewWorkflow(app, r.Client, appFile.WorkflowMode).ExecuteSteps(ctx, handler.currentAppRev, steps)
if err != nil {
klog.Error(err, "[handle workflow]")
r.Recorder.Event(app, event.Warning(velatypes.ReasonFailedWorkflow, err))
return r.endWithNegativeCondition(ctx, app, condition.ErrorCondition("Workflow", err))
return r.endWithNegativeCondition(ctx, app, condition.ErrorCondition("Workflow", err), common.ApplicationRunningWorkflow)
}
handler.addServiceStatus(false, app.Status.Services...)
handler.addAppliedResource(app.Status.AppliedResources...)
app.Status.Services = handler.services
app.Status.AppliedResources = handler.appliedResources
if pause {
if err := r.patchStatus(ctx, app); err != nil {
return r.endWithNegativeCondition(ctx, app, condition.ReconcileError(err))
}
return ctrl.Result{}, nil
}
if !done {
if err := r.patchStatus(ctx, app); err != nil {
return r.endWithNegativeCondition(ctx, app, condition.ReconcileError(err))
}
return reconcile.Result{RequeueAfter: WorkflowReconcileWaitTime}, nil
}
wfStatus := app.Status.Workflow
if wfStatus != nil {
if wfStatus.Terminated && app.Status.Phase == common.ApplicationWorkflowTerminated {
if err := r.patchStatus(ctx, app); err != nil {
return r.endWithNegativeCondition(ctx, app, condition.ReconcileError(err))
}
return ctrl.Result{}, nil
}
if !wfStatus.Terminated {
_, err := handler.DispatchAndGC(ctx)
switch workflowState {
case common.WorkflowStateSuspended:
return ctrl.Result{}, r.patchStatus(ctx, app, common.ApplicationWorkflowSuspending)
case common.WorkflowStateTerminated:
return ctrl.Result{}, r.patchStatus(ctx, app, common.ApplicationWorkflowTerminated)
case common.WorkflowStateExecuting:
return reconcile.Result{RequeueAfter: WorkflowReconcileWaitTime}, r.patchStatus(ctx, app, common.ApplicationRunningWorkflow)
case common.WorkflowStateFinished:
wfStatus := app.Status.Workflow
if wfStatus != nil {
ref, err := handler.DispatchAndGC(ctx)
if err != nil {
klog.ErrorS(err, "Failed to gc after workflow",
"application", klog.KObj(app))
r.Recorder.Event(app, event.Warning(velatypes.ReasonFailedGC, err))
return r.endWithNegativeCondition(ctx, app, condition.ErrorCondition("GCAfterWorkflow", err))
}
wfStatus.Terminated = true
if err := r.patchStatus(ctx, app); err != nil {
return r.endWithNegativeCondition(ctx, app, condition.ReconcileError(err))
return r.endWithNegativeCondition(ctx, app, condition.ErrorCondition("GCAfterWorkflow", err), common.ApplicationRunningWorkflow)
}
app.Status.ResourceTracker = ref
}
}
app.Status.SetConditions(condition.ReadyCondition("WorkflowFinished"))
r.Recorder.Event(app, event.Normal(velatypes.ReasonApplied, velatypes.MessageWorkflowFinished))
klog.Info("Application manifests has applied by workflow successfully", "application", klog.KObj(app))
} else {
var comps []*velatypes.ComponentManifest
comps, err = appFile.GenerateComponentManifests()
if err != nil {
klog.ErrorS(err, "Failed to render components", "application", klog.KObj(app))
r.Recorder.Event(app, event.Warning(velatypes.ReasonFailedRender, err))
return r.endWithNegativeCondition(ctx, app, condition.ErrorCondition("Render", err))
return r.endWithNegativeCondition(ctx, app, condition.ErrorCondition("Render", err), common.ApplicationRendering)
}
handler.handleCheckManageWorkloadTrait(handler.currentAppRev.Spec.TraitDefinitions, comps)
@@ -234,32 +221,23 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
if err := handler.HandleComponentsRevision(ctx, comps); err != nil {
klog.ErrorS(err, "Failed to handle compoents revision", "application", klog.KObj(app))
r.Recorder.Event(app, event.Warning(velatypes.ReasonFailedRevision, err))
return r.endWithNegativeCondition(ctx, app, condition.ErrorCondition("Render", err))
return r.endWithNegativeCondition(ctx, app, condition.ErrorCondition("Render", err), common.ApplicationRendering)
}
klog.Info("Application manifests has prepared and ready for appRollout to handle", "application", klog.KObj(app))
}
if err := handler.UpdateAppLatestRevisionStatus(ctx); err != nil {
klog.ErrorS(err, "Failed to update application status", "application", klog.KObj(app))
return r.endWithNegativeCondition(ctx, app, condition.ReconcileError(err))
}
app.Status.SetConditions(condition.ReadyCondition("Applied"))
r.Recorder.Event(app, event.Normal(velatypes.ReasonApplied, velatypes.MessageApplied))
klog.Info("Successfully apply application manifests", "application", klog.KObj(app))
// if inplace is false and rolloutPlan is nil, it means the user will use an outer AppRollout object to rollout the application
if handler.app.Spec.RolloutPlan != nil {
res, err := handler.handleRollout(ctx)
if err != nil {
klog.ErrorS(err, "Failed to handle rollout", "application", klog.KObj(app))
r.Recorder.Event(app, event.Warning(velatypes.ReasonFailedRollout, err))
return r.endWithNegativeCondition(ctx, app, condition.ErrorCondition("Rollout", err))
return r.endWithNegativeCondition(ctx, app, condition.ErrorCondition("Rollout", err), common.ApplicationRollingOut)
}
// skip health check and garbage collection if rollout have not finished
// start next reconcile immediately
if res.Requeue || res.RequeueAfter > 0 {
app.Status.Phase = common.ApplicationRollingOut
if err := r.patchStatus(ctx, app); err != nil {
return r.endWithNegativeCondition(ctx, app, condition.ReconcileError(err))
if err := r.patchStatus(ctx, app, common.ApplicationRollingOut); err != nil {
return r.endWithNegativeCondition(ctx, app, condition.ReconcileError(err), common.ApplicationRollingOut)
}
return res, nil
}
@@ -267,45 +245,29 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
// there is no need reconcile immediately, that means the rollout operation have finished
r.Recorder.Event(app, event.Normal(velatypes.ReasonRollout, velatypes.MessageRollout))
app.Status.SetConditions(condition.ReadyCondition("Rollout"))
klog.Info("Finished rollout ")
klog.InfoS("Finished rollout ", "application", klog.KObj(app))
}
var phase = common.ApplicationRunning
if !hasHealthCheckPolicy(appFile.Policies) {
app.Status.Phase = common.ApplicationHealthChecking
if !isHealthy(handler.services) {
app.Status.SetConditions(condition.Condition{
Type: v1beta1.TypeHealthy,
Status: corev1.ConditionFalse,
LastTransitionTime: metav1.Now(),
Reason: v1beta1.ReasonUnhealthy,
})
if err := r.patchStatus(ctx, app); err != nil {
return r.endWithNegativeCondition(ctx, app, condition.ReconcileError(err))
}
return r.endWithNegativeCondition(ctx, app, condition.ErrorCondition("HealthCheck", errors.New("not healthy")))
phase = common.ApplicationUnhealthy
}
app.Status.SetConditions(condition.Condition{
Type: v1beta1.TypeHealthy,
Status: corev1.ConditionTrue,
LastTransitionTime: metav1.Now(),
Reason: v1beta1.ReasonHealthy,
})
r.Recorder.Event(app, event.Normal(velatypes.ReasonHealthCheck, velatypes.MessageHealthCheck))
}
app.Status.Phase = common.ApplicationRunning
if err := garbageCollection(ctx, handler); err != nil {
klog.ErrorS(err, "Failed to run garbage collection")
r.Recorder.Event(app, event.Warning(velatypes.ReasonFailedGC, err))
return r.endWithNegativeCondition(ctx, app, condition.ReconcileError(err))
return r.endWithNegativeCondition(ctx, app, condition.ReconcileError(err), phase)
}
klog.Info("Successfully garbage collect", "application", klog.KObj(app))
app.Status.SetConditions(condition.Condition{
Type: condition.TypeReady,
Status: corev1.ConditionTrue,
LastTransitionTime: metav1.Now(),
Reason: condition.ReasonReconcileSuccess,
})
r.Recorder.Event(app, event.Normal(velatypes.ReasonDeployed, velatypes.MessageDeployed))
if err := r.patchStatus(ctx, app); err != nil {
return r.endWithNegativeCondition(ctx, app, condition.ReconcileError(err))
}
return ctrl.Result{}, nil
return ctrl.Result{}, r.patchStatus(ctx, app, phase)
}
// NOTE Because resource tracker is cluster-scoped resources, we cannot garbage collect them
@@ -358,15 +320,16 @@ func (r *Reconciler) handleFinalizers(ctx context.Context, app *v1beta1.Applicat
return false, nil
}
func (r *Reconciler) endWithNegativeCondition(ctx context.Context, app *v1beta1.Application, condition condition.Condition) (ctrl.Result, error) {
func (r *Reconciler) endWithNegativeCondition(ctx context.Context, app *v1beta1.Application, condition condition.Condition, phase common.ApplicationPhase) (ctrl.Result, error) {
app.SetConditions(condition)
if err := r.patchStatus(ctx, app); err != nil {
if err := r.patchStatus(ctx, app, phase); err != nil {
return ctrl.Result{}, errors.WithMessage(err, "cannot update application status")
}
return ctrl.Result{}, fmt.Errorf("object level reconcile error, type: %q, msg: %q", string(condition.Type), condition.Message)
}
func (r *Reconciler) patchStatus(ctx context.Context, app *v1beta1.Application) error {
func (r *Reconciler) patchStatus(ctx context.Context, app *v1beta1.Application, phase common.ApplicationPhase) error {
app.Status.Phase = phase
updateObservedGeneration(app)
return r.Client.Status().Patch(ctx, app, client.Merge)
}
@@ -134,7 +134,8 @@ var _ = Describe("Test application controller finalizer logic", func() {
checkApp = new(v1beta1.Application)
Expect(k8sClient.Get(ctx, appKey, checkApp)).Should(BeNil())
Expect(k8sClient.Get(ctx, getTrackerKey(checkApp.Namespace, checkApp.Name, "v1"), rt)).Should(Succeed())
Expect(checkApp.Status.ResourceTracker).Should(BeNil())
Expect(checkApp.Status.ResourceTracker).ShouldNot(BeNil())
Expect(checkApp.Status.ResourceTracker.Name).Should(BeEquivalentTo("app-1-v1-cross-namespace"))
})
It("Test error occurs in the middle of dispatching", func() {
@@ -148,10 +149,10 @@ var _ = Describe("Test application controller finalizer logic", func() {
testutil.ReconcileOnceAfterFinalizer(reconciler, ctrl.Request{NamespacedName: appKey})
Expect(k8sClient.Get(ctx, appKey, checkApp)).Should(BeNil())
// because error occurs in the middle of dispatching
// resource tracker for v1 is created but v1 is not recorded in app status
By("Verify latest app revision is not recorded in status")
Expect(checkApp.Status.LatestRevision).Should(BeNil())
// though error occurs in the middle of dispatching
// resource tracker for v1 is also created and recorded in app status
By("Verify latest app revision is also recorded in status")
Expect(checkApp.Status.LatestRevision).ShouldNot(BeNil())
By("Verify ResourceTracker is created")
rt := &v1beta1.ResourceTracker{}
@@ -222,7 +223,7 @@ var _ = Describe("Test application controller finalizer logic", func() {
testutil.ReconcileOnceAfterFinalizer(reconciler, ctrl.Request{NamespacedName: appKey})
checkApp = new(v1beta1.Application)
Expect(k8sClient.Get(ctx, appKey, checkApp)).Should(BeNil())
Expect(checkApp.Status.ResourceTracker).Should(BeNil())
Expect(checkApp.Status.ResourceTracker).ShouldNot(BeNil())
Expect(k8sClient.Get(ctx, getTrackerKey(checkApp.Namespace, checkApp.Name, "v2"), rt)).Should(Succeed())
Expect(k8sClient.Delete(ctx, checkApp)).Should(BeNil())
testutil.ReconcileOnceAfterFinalizer(reconciler, ctrl.Request{NamespacedName: appKey})
@@ -63,6 +63,9 @@ func (h *AppHandler) Dispatch(ctx context.Context, cluster string, owner common.
_, err := h.dispatcher.Dispatch(ctx, manifests)
if err == nil {
for _, mf := range manifests {
if mf == nil {
continue
}
ref := common.ClusterObjectReference{
Cluster: cluster,
Creator: owner,
@@ -390,7 +393,7 @@ func (h *AppHandler) handleRollout(ctx context.Context) (reconcile.Result, error
}
// construct a fake rollout object and call rollout.DoReconcile
r := applicationrollout.NewReconciler(h.r.Client, h.r.dm, h.r.Recorder, h.r.Scheme)
r := applicationrollout.NewReconciler(h.r.Client, h.r.dm, h.r.pd, h.r.Recorder, h.r.Scheme, h.r.concurrentReconciles)
res, err := r.DoReconcile(ctx, &appRollout)
if err != nil {
return reconcile.Result{}, err
@@ -189,34 +189,24 @@ func (am *AppManifests) assemble() {
return
}
for _, comp := range am.componentManifests {
if checkAutoDetectComponent(comp.StandardWorkload) {
klog.Warningf("component without specify workloadDef can not attach traits currently")
continue
}
compRevisionName := comp.RevisionName
compName := comp.Name
additionalLabel := map[string]string{
oam.LabelAppComponentRevision: compRevisionName,
oam.LabelAppRevisionHash: am.AppRevision.Labels[oam.LabelAppRevisionHash],
}
klog.InfoS("Assemble manifests for component", "name", compName)
wl, err := am.assembleWorkload(compName, comp.StandardWorkload, additionalLabel, comp.PackagedWorkloadResources)
klog.InfoS("Assemble manifests for component", "name", comp.Name)
wl, traits, err := PrepareBeforeApply(comp, am.AppRevision, am.WorkloadOptions)
if err != nil {
am.finalizeAssemble(err)
return
}
am.assembledWorkloads[compName] = wl
if wl == nil {
klog.Warningf("component without specify workloadDef can not attach traits currently")
continue
}
am.assembledWorkloads[comp.Name] = wl
workloadRef := corev1.ObjectReference{
APIVersion: wl.GetAPIVersion(),
Kind: wl.GetKind(),
Name: wl.GetName(),
}
am.assembledTraits[compName] = make([]*unstructured.Unstructured, len(comp.Traits))
for i, trait := range comp.Traits {
am.setTraitLabels(trait, additionalLabel)
am.assembledTraits[compName][i] = trait
}
am.assembledTraits[comp.Name] = traits
am.referencedScopes[workloadRef] = make([]corev1.ObjectReference, len(comp.Scopes))
for i, scope := range comp.Scopes {
am.referencedScopes[workloadRef][i] = *scope
@@ -225,6 +215,31 @@ func (am *AppManifests) assemble() {
am.finalizeAssemble(nil)
}
// PrepareBeforeApply will prepare for some necessary info before apply
func PrepareBeforeApply(comp *types.ComponentManifest, appRev *v1beta1.ApplicationRevision, workloadOpt []WorkloadOption) (*unstructured.Unstructured, []*unstructured.Unstructured, error) {
if checkAutoDetectComponent(comp.StandardWorkload) {
return nil, nil, nil
}
compRevisionName := comp.RevisionName
compName := comp.Name
additionalLabel := map[string]string{
oam.LabelAppComponentRevision: compRevisionName,
oam.LabelAppRevisionHash: appRev.Labels[oam.LabelAppRevisionHash],
}
wl, err := assembleWorkload(compName, comp.StandardWorkload, additionalLabel, comp.PackagedWorkloadResources, appRev, workloadOpt)
if err != nil {
return nil, nil, err
}
assembledTraits := make([]*unstructured.Unstructured, len(comp.Traits))
for i, trait := range comp.Traits {
setTraitLabels(trait, additionalLabel)
assembledTraits[i] = trait
}
return wl, assembledTraits, nil
}
func (am *AppManifests) complete() error {
if len(am.componentManifests) == 0 {
var err error
@@ -275,20 +290,20 @@ func (am *AppManifests) validate() error {
return nil
}
func (am *AppManifests) assembleWorkload(compName string, wl *unstructured.Unstructured,
labels map[string]string, resources []*unstructured.Unstructured) (*unstructured.Unstructured, error) {
func assembleWorkload(compName string, wl *unstructured.Unstructured,
labels map[string]string, resources []*unstructured.Unstructured, appRev *v1beta1.ApplicationRevision, wop []WorkloadOption) (*unstructured.Unstructured, error) {
// use component name as workload name
// override the name set in render phase if exist
wl.SetName(compName)
am.setWorkloadLabels(wl, labels)
setWorkloadLabels(wl, labels)
workloadType := wl.GetLabels()[oam.WorkloadTypeLabel]
compDefinition := am.AppRevision.Spec.ComponentDefinitions[workloadType]
compDefinition := appRev.Spec.ComponentDefinitions[workloadType]
copyPackagedResources := make([]*unstructured.Unstructured, len(resources))
for i, v := range resources {
copyPackagedResources[i] = v.DeepCopy()
}
for _, wo := range am.WorkloadOptions {
for _, wo := range wop {
if err := wo.ApplyToWorkload(wl, compDefinition.DeepCopy(), copyPackagedResources); err != nil {
klog.ErrorS(err, "Failed applying a workload option", "workload", klog.KObj(wl), "name", wl.GetName())
return nil, errors.Wrapf(err, "cannot apply workload option for component %q", compName)
@@ -301,14 +316,14 @@ func (am *AppManifests) assembleWorkload(compName string, wl *unstructured.Unstr
// component revision label added here
// label key: app.oam.dev/revision
func (am *AppManifests) setWorkloadLabels(wl *unstructured.Unstructured, additionalLabels map[string]string) {
func setWorkloadLabels(wl *unstructured.Unstructured, additionalLabels map[string]string) {
// add more workload-specific labels here
util.AddLabels(wl, additionalLabels)
}
// component revision label added here
// label key: app.oam.dev/revision
func (am *AppManifests) setTraitLabels(trait *unstructured.Unstructured, additionalLabels map[string]string) {
func setTraitLabels(trait *unstructured.Unstructured, additionalLabels map[string]string) {
// add more trait-specific labels here
util.AddLabels(trait, additionalLabels)
}
@@ -228,6 +228,9 @@ func (a *AppManifestsDispatcher) applyAndRecordManifests(ctx context.Context, ma
BlockOwnerDeletion: pointer.BoolPtr(true),
}
for _, rsc := range manifests {
if rsc == nil {
continue
}
immutable, err := a.ImmutableResourcesUpdate(ctx, rsc, ownerRef, applyOpts)
if immutable {
@@ -284,6 +287,9 @@ func (a *AppManifestsDispatcher) updateResourceTrackerStatus(ctx context.Context
a.currentRT.Status.TrackedResources = make([]v1.ObjectReference, 0)
}
for _, rsc := range appliedManifests {
if rsc == nil {
continue
}
appliedRef := v1.ObjectReference{
APIVersion: rsc.GetAPIVersion(),
Kind: rsc.GetKind(),
@@ -60,15 +60,15 @@ func (h *GCHandler) GarbageCollect(ctx context.Context, oldRT, newRT *v1beta1.Re
}
klog.InfoS("Garbage collect for application", "old", h.oldRT.Name, "new", h.newRT.Name)
for _, oldRsc := range h.oldRT.Status.TrackedResources {
isRemoved := true
reused := false
for _, newRsc := range h.newRT.Status.TrackedResources {
if oldRsc.APIVersion == newRsc.APIVersion && oldRsc.Kind == newRsc.Kind &&
oldRsc.Namespace == newRsc.Namespace && oldRsc.Name == newRsc.Name {
isRemoved = false
reused = true
break
}
}
if isRemoved {
if !reused {
toBeDeleted := &unstructured.Unstructured{}
toBeDeleted.SetAPIVersion(oldRsc.APIVersion)
toBeDeleted.SetKind(oldRsc.Kind)
@@ -19,6 +19,8 @@ import (
"context"
"encoding/json"
"github.com/oam-dev/kubevela/pkg/controller/core.oam.dev/v1alpha2/application/assemble"
"github.com/pkg/errors"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -126,18 +128,27 @@ func (h *AppHandler) applyComponentFunc(appParser *appfile.Parser, appRev *v1bet
if err := af.SetOAMContract(manifest); err != nil {
return nil, nil, false, errors.WithMessage(err, "SetOAMContract")
}
if err := h.HandleComponentsRevision(context.Background(), []*types.ComponentManifest{manifest}); err != nil {
if err := h.HandleComponentsRevision(context.TODO(), []*types.ComponentManifest{manifest}); err != nil {
return nil, nil, false, errors.WithMessage(err, "HandleComponentsRevision")
}
if len(manifest.PackagedWorkloadResources) != 0 {
if err := h.Dispatch(context.TODO(), "", common.WorkflowResourceCreator, manifest.PackagedWorkloadResources...); err != nil {
return nil, nil, false, errors.WithMessage(err, "cannot dispatch packaged workload resources")
}
}
readyWorkload, readyTraits, err := assemble.PrepareBeforeApply(manifest, appRev, []assemble.WorkloadOption{assemble.DiscoveryHelmBasedWorkload(context.TODO(), h.r.Client)})
if err != nil {
return nil, nil, false, errors.WithMessage(err, "assemble resources before apply fail")
}
skipStandardWorkload := skipApplyWorkload(wl)
if !skipStandardWorkload {
if err := h.Dispatch(context.Background(), "", common.WorkflowResourceCreator, manifest.StandardWorkload); err != nil {
if err := h.Dispatch(context.TODO(), "", common.WorkflowResourceCreator, readyWorkload); err != nil {
return nil, nil, false, errors.WithMessage(err, "DispatchStandardWorkload")
}
}
if err := h.Dispatch(context.Background(), "", common.WorkflowResourceCreator, manifest.Traits...); err != nil {
if err := h.Dispatch(context.TODO(), "", common.WorkflowResourceCreator, readyTraits...); err != nil {
return nil, nil, false, errors.WithMessage(err, "DispatchTraits")
}
@@ -689,7 +689,7 @@ func (h *AppHandler) UpdateAppLatestRevisionStatus(ctx context.Context) error {
Revision: int64(revNum),
RevisionHash: h.currentRevHash,
}
if err := h.r.patchStatus(ctx, h.app); err != nil {
if err := h.r.patchStatus(ctx, h.app, common.ApplicationRendering); err != nil {
klog.InfoS("Failed to update the latest appConfig revision to status", "application", klog.KObj(h.app),
"latest revision", revName, "err", err)
return err
@@ -759,6 +759,13 @@ func gatherUsingAppRevision(ctx context.Context, h *AppHandler) (map[string]bool
appRev := dispatch.ExtractAppRevisionName(rt.Name, ns)
usingRevision[appRev] = true
}
appRolloutRevision, err := utils.CheckAppRolloutUsingAppRevision(ctx, h.r.Client, h.app.Namespace, h.app.Name)
if err != nil {
return usingRevision, err
}
for _, revName := range appRolloutRevision {
usingRevision[revName] = true
}
appDeployUsingRevision, err := utils.CheckAppDeploymentUsingAppRevision(ctx, h.r.Client, h.app.Namespace, h.app.Name)
if err != nil {
return usingRevision, err
@@ -70,8 +70,6 @@ var controllerDone context.CancelFunc
var mgr ctrl.Manager
var appRevisionLimit = 5
// TODO: create a mock client and add UT to cover all the failure cases
func TestAPIs(t *testing.T) {
RegisterFailHandler(Fail)
@@ -228,7 +228,7 @@ var _ = Describe("Test Workflow", func() {
}, appObj)).Should(BeNil())
Expect(appObj.Status.Workflow.Steps[0].Phase).Should(Equal(common.WorkflowStepPhaseSucceeded))
Expect(appObj.Status.Workflow.Terminated).Should(BeTrue())
Expect(appObj.Status.Phase).Should(BeEquivalentTo(common.ApplicationRunning))
})
It("test workflow suspend", func() {
@@ -253,10 +253,16 @@ var _ = Describe("Test Workflow", func() {
Expect(appObj.Status.Workflow.Suspend).Should(BeTrue())
Expect(appObj.Status.Phase).Should(BeEquivalentTo(common.ApplicationWorkflowSuspending))
Expect(appObj.Status.Workflow.Steps[0].Phase).Should(BeEquivalentTo(common.WorkflowStepPhaseSucceeded))
// resume
appObj.Status.Workflow.Suspend = false
Expect(k8sClient.Status().Patch(ctx, appObj, client.Merge)).Should(BeNil())
Expect(k8sClient.Get(ctx, client.ObjectKey{
Name: suspendApp.Name,
Namespace: suspendApp.Namespace,
}, appObj)).Should(BeNil())
Expect(appObj.Status.Workflow.Suspend).Should(BeFalse())
tryReconcile(reconciler, suspendApp.Name, suspendApp.Namespace)
tryReconcile(reconciler, suspendApp.Name, suspendApp.Namespace)
@@ -268,7 +274,7 @@ var _ = Describe("Test Workflow", func() {
}, appObj)).Should(BeNil())
Expect(appObj.Status.Workflow.Suspend).Should(BeFalse())
Expect(appObj.Status.Workflow.Terminated).Should(BeTrue())
Expect(appObj.Status.Phase).Should(BeEquivalentTo(common.ApplicationRunning))
})
It("test workflow terminate a suspend workflow", func() {
@@ -150,7 +150,6 @@ func (r *Reconciler) DoReconcile(ctx context.Context, appRollout *v1beta1.AppRol
if len(appRollout.Spec.ComponentList) == 1 {
h.needRollComponent = appRollout.Spec.ComponentList[0]
}
// call assemble func generate source and target manifest
if err = h.prepareWorkloads(ctx); err != nil {
return reconcile.Result{}, err
@@ -282,12 +281,14 @@ func (r *Reconciler) updateStatus(ctx context.Context, appRollout *v1beta1.AppRo
}
// NewReconciler render a applicationRollout reconciler
func NewReconciler(c client.Client, dm discoverymapper.DiscoveryMapper, record event.Recorder, scheme *runtime.Scheme) *Reconciler {
func NewReconciler(c client.Client, dm discoverymapper.DiscoveryMapper, pd *packages.PackageDiscover, record event.Recorder, scheme *runtime.Scheme, concurrent int) *Reconciler {
return &Reconciler{
Client: c,
dm: dm,
record: record,
Scheme: scheme,
Client: c,
dm: dm,
pd: pd,
record: record,
Scheme: scheme,
concurrentReconciles: concurrent,
}
}
@@ -65,17 +65,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
var componentDefinition v1beta1.ComponentDefinition
if err := r.Get(ctx, req.NamespacedName, &componentDefinition); err != nil {
if apierrors.IsNotFound(err) {
err = nil
}
klog.InfoS("The ComponentDefinition doesn't exist", "componentDefinition", klog.KRef(req.Namespace, req.Name))
return ctrl.Result{}, err
}
// this is a placeholder for finalizer here in the future
if componentDefinition.DeletionTimestamp != nil {
klog.InfoS("The ComponentDefinition is being deleted", "componentDefinition", klog.KRef(req.Namespace, req.Name))
return ctrl.Result{}, nil
return ctrl.Result{}, client.IgnoreNotFound(err)
}
// refresh package discover when componentDefinition is registered
@@ -94,7 +84,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
if err != nil {
klog.ErrorS(err, "Could not generate DefinitionRevision", "componentDefinition", klog.KObj(&componentDefinition))
r.record.Event(&componentDefinition, event.Warning("Could not generate DefinitionRevision", err))
return ctrl.Result{}, util.EndReconcileWithNegativeCondition(ctx, r, &componentDefinition,
return ctrl.Result{}, util.PatchCondition(ctx, r, &componentDefinition,
condition.ReconcileError(fmt.Errorf(util.ErrGenerateDefinitionRevision, componentDefinition.Name, err)))
}
@@ -102,7 +92,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
if err := r.createComponentDefRevision(ctx, &componentDefinition, defRev.DeepCopy()); err != nil {
klog.ErrorS(err, "Could not create DefinitionRevision")
r.record.Event(&componentDefinition, event.Warning("cannot create DefinitionRevision", err))
return ctrl.Result{}, util.EndReconcileWithNegativeCondition(ctx, r, &componentDefinition,
return ctrl.Result{}, util.PatchCondition(ctx, r, &componentDefinition,
condition.ReconcileError(fmt.Errorf(util.ErrCreateDefinitionRevision, defRev.Name, err)))
}
klog.InfoS("Successfully created definitionRevision", "definitionRevision", klog.KObj(defRev))
@@ -116,7 +106,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
if err := r.UpdateStatus(ctx, &componentDefinition); err != nil {
klog.ErrorS(err, "Could not update componentDefinition Status")
r.record.Event(&componentDefinition, event.Warning("cannot update ComponentDefinition Status", err))
return ctrl.Result{}, util.EndReconcileWithNegativeCondition(ctx, r, &componentDefinition,
return ctrl.Result{}, util.PatchCondition(ctx, r, &componentDefinition,
condition.ReconcileError(fmt.Errorf(util.ErrUpdateComponentDefinition, componentDefinition.Name, err)))
}
klog.InfoS("Successfully updated the status.latestRevision of the ComponentDefinition", "componentDefinition", klog.KRef(req.Namespace, req.Name),
@@ -134,7 +124,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
if err != nil {
klog.InfoS("Could not capability in ConfigMap", "err", err)
r.record.Event(&(componentDefinition), event.Warning("Could not store capability in ConfigMap", err))
return ctrl.Result{}, util.EndReconcileWithNegativeCondition(ctx, r, &(componentDefinition),
return ctrl.Result{}, util.PatchCondition(ctx, r, &(componentDefinition),
condition.ReconcileError(fmt.Errorf(util.ErrStoreCapabilityInConfigMap, def.Name, err)))
}
@@ -143,7 +133,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
if err := r.UpdateStatus(ctx, &componentDefinition); err != nil {
klog.InfoS("Could not update componentDefinition Status", "err", err)
r.record.Event(&componentDefinition, event.Warning("cannot update ComponentDefinition Status", err))
return ctrl.Result{}, util.EndReconcileWithNegativeCondition(ctx, r, &componentDefinition,
return ctrl.Result{}, util.PatchCondition(ctx, r, &componentDefinition,
condition.ReconcileError(fmt.Errorf(util.ErrUpdateComponentDefinition, componentDefinition.Name, err)))
}
klog.InfoS("Successfully updated the status.configMapRef of the ComponentDefinition", "componentDefinition",
@@ -65,10 +65,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
klog.InfoS("Reconciling PolicyDefinition...", "Name", definitionName, "Namespace", req.Namespace)
var policydefinition v1beta1.PolicyDefinition
if err := r.Get(ctx, req.NamespacedName, &policydefinition); err != nil {
if apierrors.IsNotFound(err) {
err = nil
}
return ctrl.Result{}, err
return ctrl.Result{}, client.IgnoreNotFound(err)
}
// this is a placeholder for finalizer here in the future
@@ -92,7 +89,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
if err != nil {
klog.ErrorS(err, "cannot generate DefinitionRevision", "PolicyDefinitionName", policydefinition.Name)
r.record.Event(&policydefinition, event.Warning("cannot generate DefinitionRevision", err))
return ctrl.Result{}, util.EndReconcileWithNegativeCondition(ctx, r, &policydefinition,
return ctrl.Result{}, util.PatchCondition(ctx, r, &policydefinition,
condition.ReconcileError(fmt.Errorf(util.ErrGenerateDefinitionRevision, policydefinition.Name, err)))
}
@@ -100,7 +97,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
if err = r.createPolicyDefRevision(ctx, &policydefinition, defRev); err != nil {
klog.ErrorS(err, "cannot create DefinitionRevision")
r.record.Event(&(policydefinition), event.Warning("cannot create DefinitionRevision", err))
return ctrl.Result{}, util.EndReconcileWithNegativeCondition(ctx, r, &(policydefinition),
return ctrl.Result{}, util.PatchCondition(ctx, r, &(policydefinition),
condition.ReconcileError(fmt.Errorf(util.ErrCreateDefinitionRevision, defRev.Name, err)))
}
klog.InfoS("Successfully created PolicyDefRevision", "name", defRev.Name)
@@ -114,7 +111,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
if err := r.UpdateStatus(ctx, &policydefinition); err != nil {
klog.ErrorS(err, "cannot update PolicyDefinition Status")
r.record.Event(&(policydefinition), event.Warning("cannot update PolicyDefinition Status", err))
return ctrl.Result{}, util.EndReconcileWithNegativeCondition(ctx, r, &(policydefinition),
return ctrl.Result{}, util.PatchCondition(ctx, r, &(policydefinition),
condition.ReconcileError(fmt.Errorf(util.ErrUpdatePolicyDefinition, policydefinition.Name, err)))
}
@@ -64,11 +64,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
var traitdefinition v1beta1.TraitDefinition
if err := r.Get(ctx, req.NamespacedName, &traitdefinition); err != nil {
if apierrors.IsNotFound(err) {
err = nil
}
klog.InfoS("The TraitDefinition doesn't exist", "traitDefinition", klog.KRef(req.Namespace, req.Name))
return ctrl.Result{}, err
return ctrl.Result{}, client.IgnoreNotFound(err)
}
// this is a placeholder for finalizer here in the future
@@ -93,7 +89,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
if err != nil {
klog.InfoS("Could not generate definitionRevision", "traitDefinition", klog.KObj(&traitdefinition), "err", err)
r.record.Event(&traitdefinition, event.Warning("Could not generate DefinitionRevision", err))
return ctrl.Result{}, util.EndReconcileWithNegativeCondition(ctx, r, &traitdefinition,
return ctrl.Result{}, util.PatchCondition(ctx, r, &traitdefinition,
condition.ReconcileError(fmt.Errorf(util.ErrGenerateDefinitionRevision, traitdefinition.Name, err)))
}
@@ -101,7 +97,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
if err := r.createTraitDefRevision(ctx, &traitdefinition, defRev); err != nil {
klog.ErrorS(err, "Could not create DefinitionRevision")
r.record.Event(&traitdefinition, event.Warning("Could not create definitionRevision", err))
return ctrl.Result{}, util.EndReconcileWithNegativeCondition(ctx, r, &traitdefinition,
return ctrl.Result{}, util.PatchCondition(ctx, r, &traitdefinition,
condition.ReconcileError(fmt.Errorf(util.ErrCreateDefinitionRevision, defRev.Name, err)))
}
klog.InfoS("Successfully created definitionRevision", "definitionRevision", klog.KObj(defRev))
@@ -114,7 +110,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
if err := r.UpdateStatus(ctx, &traitdefinition); err != nil {
klog.ErrorS(err, "Could not update TraitDefinition Status", "traitDefinition", klog.KRef(req.Namespace, req.Name))
r.record.Event(&traitdefinition, event.Warning("Could not update TraitDefinition Status", err))
return ctrl.Result{}, util.EndReconcileWithNegativeCondition(ctx, r, &traitdefinition,
return ctrl.Result{}, util.PatchCondition(ctx, r, &traitdefinition,
condition.ReconcileError(fmt.Errorf(util.ErrUpdateTraitDefinition, traitdefinition.Name, err)))
}
klog.InfoS("Successfully updated the status.latestRevision of the TraitDefinition", "traitDefinition", klog.KRef(req.Namespace, req.Name),
@@ -133,7 +129,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
if err != nil {
klog.InfoS("Could not store capability in ConfigMap", "err", err)
r.record.Event(&(traitdefinition), event.Warning("Could not store capability in ConfigMap", err))
return ctrl.Result{}, util.EndReconcileWithNegativeCondition(ctx, r, &traitdefinition,
return ctrl.Result{}, util.PatchCondition(ctx, r, &traitdefinition,
condition.ReconcileError(fmt.Errorf(util.ErrStoreCapabilityInConfigMap, traitdefinition.Name, err)))
}
@@ -142,7 +138,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
if err := r.UpdateStatus(ctx, &traitdefinition); err != nil {
klog.ErrorS(err, "Could not update TraitDefinition Status", "traitDefinition", klog.KRef(req.Namespace, req.Name))
r.record.Event(&traitdefinition, event.Warning("Could not update TraitDefinition Status", err))
return ctrl.Result{}, util.EndReconcileWithNegativeCondition(ctx, r, &traitdefinition,
return ctrl.Result{}, util.PatchCondition(ctx, r, &traitdefinition,
condition.ReconcileError(fmt.Errorf(util.ErrUpdateTraitDefinition, traitdefinition.Name, err)))
}
klog.InfoS("Successfully updated the status.configMapRef of the TraitDefinition", "traitDefinition",
@@ -65,10 +65,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
var wfstepdefinition v1beta1.WorkflowStepDefinition
if err := r.Get(ctx, req.NamespacedName, &wfstepdefinition); err != nil {
if apierrors.IsNotFound(err) {
err = nil
}
return ctrl.Result{}, err
return ctrl.Result{}, client.IgnoreNotFound(err)
}
// this is a placeholder for finalizer here in the future
@@ -91,7 +88,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
if err != nil {
klog.ErrorS(err, "cannot generate DefinitionRevision", "WorkflowStepDefinitionName", wfstepdefinition.Name)
r.record.Event(&wfstepdefinition, event.Warning("cannot generate DefinitionRevision", err))
return ctrl.Result{}, util.EndReconcileWithNegativeCondition(ctx, r, &wfstepdefinition,
return ctrl.Result{}, util.PatchCondition(ctx, r, &wfstepdefinition,
condition.ReconcileError(fmt.Errorf(util.ErrGenerateDefinitionRevision, wfstepdefinition.Name, err)))
}
@@ -99,7 +96,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
if err = r.createWFStepDefRevision(ctx, &wfstepdefinition, defRev); err != nil {
klog.ErrorS(err, "cannot create DefinitionRevision")
r.record.Event(&(wfstepdefinition), event.Warning("cannot create DefinitionRevision", err))
return ctrl.Result{}, util.EndReconcileWithNegativeCondition(ctx, r, &(wfstepdefinition),
return ctrl.Result{}, util.PatchCondition(ctx, r, &(wfstepdefinition),
condition.ReconcileError(fmt.Errorf(util.ErrCreateDefinitionRevision, defRev.Name, err)))
}
klog.InfoS("Successfully created WFStepDefRevision", "name", defRev.Name)
@@ -112,7 +109,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
if err := r.UpdateStatus(ctx, &wfstepdefinition); err != nil {
klog.ErrorS(err, "cannot update WorkflowStepDefinition Status")
r.record.Event(&(wfstepdefinition), event.Warning("cannot update WorkflowStepDefinition Status", err))
return ctrl.Result{}, util.EndReconcileWithNegativeCondition(ctx, r, &(wfstepdefinition),
return ctrl.Result{}, util.PatchCondition(ctx, r, &(wfstepdefinition),
condition.ReconcileError(fmt.Errorf(util.ErrUpdateWorkflowStepDefinition, wfstepdefinition.Name, err)))
}
+48
View File
@@ -25,6 +25,8 @@ import (
"strings"
"time"
"github.com/oam-dev/kubevela/apis/standard.oam.dev/v1alpha1"
"github.com/crossplane/crossplane-runtime/pkg/fieldpath"
mapset "github.com/deckarep/golang-set"
"github.com/mitchellh/hashstructure/v2"
@@ -320,6 +322,52 @@ func RefreshPackageDiscover(ctx context.Context, k8sClient client.Client, dm dis
return nil
}
// CheckAppRolloutUsingAppRevision get all AppRollout using appRevisions related the app
func CheckAppRolloutUsingAppRevision(ctx context.Context, c client.Reader, appNs string, appName string) ([]string, error) {
rolloutOpts := []client.ListOption{
client.InNamespace(appNs),
}
var res []string
ars := new(v1beta1.AppRolloutList)
if err := c.List(ctx, ars, rolloutOpts...); err != nil {
return nil, err
}
if len(ars.Items) == 0 {
return res, nil
}
relatedRevs := new(v1beta1.ApplicationRevisionList)
revOpts := []client.ListOption{
client.InNamespace(appNs),
client.MatchingLabels{oam.LabelAppName: appName},
}
if err := c.List(ctx, relatedRevs, revOpts...); err != nil {
return nil, err
}
if len(relatedRevs.Items) == 0 {
return res, nil
}
revName := map[string]bool{}
for _, rev := range relatedRevs.Items {
if len(rev.Name) != 0 {
revName[rev.Name] = true
}
}
for _, d := range ars.Items {
if d.Status.RollingState == v1alpha1.RolloutSucceedState ||
d.Status.RollingState == v1alpha1.RolloutAbandoningState ||
d.Status.RollingState == v1alpha1.RolloutFailedState {
continue
}
if revName[d.Spec.TargetAppRevisionName] {
res = append(res, d.Spec.TargetAppRevisionName)
}
if revName[d.Spec.SourceAppRevisionName] {
res = append(res, d.Spec.SourceAppRevisionName)
}
}
return res, nil
}
// CheckAppDeploymentUsingAppRevision get all appDeployments using appRevisions related the app
func CheckAppDeploymentUsingAppRevision(ctx context.Context, c client.Reader, appNs string, appName string) ([]string, error) {
deployOpts := []client.ListOption{
+11
View File
@@ -483,6 +483,17 @@ func EndReconcileWithNegativeCondition(ctx context.Context, r client.StatusClien
return errors.Errorf(ErrReconcileErrInCondition, condition[0].Type, condition[0].Message)
}
// PatchCondition will patch status with condition and return, it generally used by cases which don't want reconcile after patch
func PatchCondition(ctx context.Context, r client.StatusClient, workload ConditionedObject,
condition ...condition.Condition) error {
if len(condition) == 0 {
return nil
}
workloadPatch := client.MergeFrom(workload.DeepCopyObject().(client.Object))
workload.SetConditions(condition...)
return r.Status().Patch(ctx, workload, workloadPatch, client.FieldOwner(workload.GetUID()))
}
// IsConditionChanged will check if conditions in workload is changed compare to newCondition
func IsConditionChanged(newCondition []condition.Condition, workload ConditionedObject) bool {
var conditionIsChanged bool
+2 -3
View File
@@ -20,9 +20,6 @@ import (
"encoding/json"
"github.com/pkg/errors"
"github.com/oam-dev/kubevela/pkg/oam"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
@@ -31,6 +28,8 @@ import (
"k8s.io/apimachinery/pkg/util/strategicpatch"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/oam-dev/kubevela/pkg/oam"
)
var k8sScheme = runtime.NewScheme()
@@ -82,7 +82,7 @@ func (h *MutatingHandler) Mutate(obj *v1beta1.ComponentDefinition) error {
klog.InfoS("mutate", "name", obj.Name)
// If the Type field is not empty, it means that ComponentDefinition refers to an existing WorkloadDefinition
if obj.Spec.Workload.Type != "" && obj.Spec.Workload.Definition == (common.WorkloadGVK{}) {
if obj.Spec.Workload.Type != types.AutoDetectWorkloadDefinition && (obj.Spec.Workload.Type != "" && obj.Spec.Workload.Definition == (common.WorkloadGVK{})) {
workloadDef := new(v1beta1.WorkloadDefinition)
return h.Client.Get(context.TODO(), client.ObjectKey{Name: obj.Spec.Workload.Type, Namespace: obj.Namespace}, workloadDef)
}
+2 -1
View File
@@ -18,6 +18,7 @@ package workflow
import (
"context"
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
"github.com/oam-dev/kubevela/pkg/workflow/types"
)
@@ -26,5 +27,5 @@ import (
type Workflow interface {
// ExecuteSteps executes the steps of an Application with given steps of rendered resources.
// It returns done=true only if all steps are executed and succeeded.
ExecuteSteps(ctx context.Context, appRev *v1beta1.ApplicationRevision, taskRunners []types.TaskRunner) (done bool, pause bool, err error)
ExecuteSteps(ctx context.Context, appRev *v1beta1.ApplicationRevision, taskRunners []types.TaskRunner) (state common.WorkflowState, err error)
}
+22 -35
View File
@@ -52,13 +52,13 @@ func NewWorkflow(app *oamcore.Application, cli client.Client, mode common.Workfl
}
// ExecuteSteps process workflow step in order.
func (w *workflow) ExecuteSteps(ctx context.Context, appRev *oamcore.ApplicationRevision, taskRunners []wfTypes.TaskRunner) (done bool, pause bool, gerr error) {
func (w *workflow) ExecuteSteps(ctx context.Context, appRev *oamcore.ApplicationRevision, taskRunners []wfTypes.TaskRunner) (common.WorkflowState, error) {
revAndSpecHash, err := computeAppRevisionHash(appRev.Name, w.app)
if err != nil {
return false, false, err
return common.WorkflowStateExecuting, err
}
if len(taskRunners) == 0 {
return true, false, nil
return common.WorkflowStateFinished, nil
}
if w.app.Status.Workflow == nil || w.app.Status.Workflow.AppRevision != revAndSpecHash {
@@ -76,37 +76,24 @@ func (w *workflow) ExecuteSteps(ctx context.Context, appRev *oamcore.Application
}
wfStatus := w.app.Status.Workflow
allTasksDone := w.allDone(taskRunners)
if wfStatus.Terminated {
done = true
if !allTasksDone {
w.app.Status.Phase = common.ApplicationWorkflowTerminated
}
return
return common.WorkflowStateTerminated, nil
}
w.app.Status.Phase = common.ApplicationRunningWorkflow
if allTasksDone {
done = true
return
}
if wfStatus.Suspend {
pause = true
w.app.Status.Phase = common.ApplicationWorkflowSuspending
return
return common.WorkflowStateSuspended, nil
}
if allTasksDone {
return common.WorkflowStateFinished, nil
}
var (
wfCtx wfContext.Context
)
wfCtx, gerr = w.makeContext(appRev.Name)
if gerr != nil {
return
wfCtx, err = w.makeContext(appRev.Name)
if err != nil {
return common.WorkflowStateExecuting, err
}
e := &engine{
@@ -114,20 +101,20 @@ func (w *workflow) ExecuteSteps(ctx context.Context, appRev *oamcore.Application
dagMode: w.dagMode,
}
gerr = e.run(wfCtx, taskRunners)
if wfStatus.Suspend {
pause = true
w.app.Status.Phase = common.ApplicationWorkflowSuspending
err = e.run(wfCtx, taskRunners)
if err != nil {
return common.WorkflowStateExecuting, err
}
if wfStatus.Terminated {
done = true
w.app.Status.Phase = common.ApplicationWorkflowTerminated
} else {
done = w.allDone(taskRunners)
return common.WorkflowStateTerminated, nil
}
return done, pause, gerr
if wfStatus.Suspend {
return common.WorkflowStateSuspended, nil
}
if w.allDone(taskRunners) {
return common.WorkflowStateFinished, nil
}
return common.WorkflowStateExecuting, nil
}
func (w *workflow) allDone(taskRunners []wfTypes.TaskRunner) bool {
+26 -39
View File
@@ -66,10 +66,9 @@ var _ = Describe("Test Workflow", func() {
},
})
wf := NewWorkflow(app, k8sClient, common.WorkflowModeStep)
done, pause, err := wf.ExecuteSteps(context.Background(), revision, runners)
state, err := wf.ExecuteSteps(context.Background(), revision, runners)
Expect(err).ToNot(HaveOccurred())
Expect(pause).Should(BeFalse())
Expect(done).Should(BeFalse())
Expect(state).Should(BeEquivalentTo(common.WorkflowStateExecuting))
workflowStatus := app.Status.Workflow
Expect(workflowStatus.ContextBackend.Name).Should(BeEquivalentTo("workflow-" + revision.Name))
workflowStatus.ContextBackend = nil
@@ -104,10 +103,9 @@ var _ = Describe("Test Workflow", func() {
app.Status.Workflow = workflowStatus
wf = NewWorkflow(app, k8sClient, common.WorkflowModeStep)
done, pause, err = wf.ExecuteSteps(context.Background(), revision, runners)
state, err = wf.ExecuteSteps(context.Background(), revision, runners)
Expect(err).ToNot(HaveOccurred())
Expect(pause).Should(BeFalse())
Expect(done).Should(BeTrue())
Expect(state).Should(BeEquivalentTo(common.WorkflowStateFinished))
app.Status.Workflow.ContextBackend = nil
Expect(cmp.Diff(*app.Status.Workflow, common.WorkflowStatus{
AppRevision: app.Status.Workflow.AppRevision,
@@ -145,10 +143,9 @@ var _ = Describe("Test Workflow", func() {
},
})
wf := NewWorkflow(app, k8sClient, common.WorkflowModeStep)
done, pause, err := wf.ExecuteSteps(context.Background(), revision, runners)
state, err := wf.ExecuteSteps(context.Background(), revision, runners)
Expect(err).ToNot(HaveOccurred())
Expect(done).Should(BeFalse())
Expect(pause).Should(BeTrue())
Expect(state).Should(BeEquivalentTo(common.WorkflowStateSuspended))
wfStatus := *app.Status.Workflow
wfStatus.ContextBackend = nil
Expect(cmp.Diff(wfStatus, common.WorkflowStatus{
@@ -167,19 +164,17 @@ var _ = Describe("Test Workflow", func() {
})).Should(BeEquivalentTo(""))
// check suspend...
done, pause, err = wf.ExecuteSteps(context.Background(), revision, runners)
state, err = wf.ExecuteSteps(context.Background(), revision, runners)
Expect(err).ToNot(HaveOccurred())
Expect(pause).Should(BeTrue())
Expect(done).Should(BeFalse())
Expect(state).Should(BeEquivalentTo(common.WorkflowStateSuspended))
// check resume
app.Status.Workflow.Suspend = false
// check app meta changed
app.Name = "changed"
done, pause, err = wf.ExecuteSteps(context.Background(), revision, runners)
state, err = wf.ExecuteSteps(context.Background(), revision, runners)
Expect(err).ToNot(HaveOccurred())
Expect(pause).Should(BeFalse())
Expect(done).Should(BeTrue())
Expect(state).Should(BeEquivalentTo(common.WorkflowStateFinished))
app.Status.Workflow.ContextBackend = nil
Expect(cmp.Diff(*app.Status.Workflow, common.WorkflowStatus{
AppRevision: app.Status.Workflow.AppRevision,
@@ -199,10 +194,9 @@ var _ = Describe("Test Workflow", func() {
}},
})).Should(BeEquivalentTo(""))
done, pause, err = wf.ExecuteSteps(context.Background(), revision, runners)
state, err = wf.ExecuteSteps(context.Background(), revision, runners)
Expect(err).ToNot(HaveOccurred())
Expect(pause).Should(BeFalse())
Expect(done).Should(BeTrue())
Expect(state).Should(BeEquivalentTo(common.WorkflowStateFinished))
})
It("test for terminate", func() {
@@ -217,10 +211,9 @@ var _ = Describe("Test Workflow", func() {
},
})
wf := NewWorkflow(app, k8sClient, common.WorkflowModeStep)
done, pause, err := wf.ExecuteSteps(context.Background(), revision, runners)
state, err := wf.ExecuteSteps(context.Background(), revision, runners)
Expect(err).ToNot(HaveOccurred())
Expect(pause).Should(BeFalse())
Expect(done).Should(BeTrue())
Expect(state).Should(BeEquivalentTo(common.WorkflowStateTerminated))
app.Status.Workflow.ContextBackend = nil
Expect(cmp.Diff(*app.Status.Workflow, common.WorkflowStatus{
AppRevision: app.Status.Workflow.AppRevision,
@@ -237,10 +230,9 @@ var _ = Describe("Test Workflow", func() {
}},
})).Should(BeEquivalentTo(""))
done, pause, err = wf.ExecuteSteps(context.Background(), revision, runners)
state, err = wf.ExecuteSteps(context.Background(), revision, runners)
Expect(err).ToNot(HaveOccurred())
Expect(pause).Should(BeFalse())
Expect(done).Should(BeTrue())
Expect(state).Should(BeEquivalentTo(common.WorkflowStateTerminated))
})
It("test for error", func() {
@@ -255,10 +247,9 @@ var _ = Describe("Test Workflow", func() {
},
})
wf := NewWorkflow(app, k8sClient, common.WorkflowModeStep)
done, pause, err := wf.ExecuteSteps(context.Background(), revision, runners)
state, err := wf.ExecuteSteps(context.Background(), revision, runners)
Expect(err).To(HaveOccurred())
Expect(done).Should(BeFalse())
Expect(pause).Should(BeFalse())
Expect(state).Should(BeEquivalentTo(common.WorkflowStateExecuting))
app.Status.Workflow.ContextBackend = nil
Expect(cmp.Diff(*app.Status.Workflow, common.WorkflowStatus{
AppRevision: app.Status.Workflow.AppRevision,
@@ -274,10 +265,9 @@ var _ = Describe("Test Workflow", func() {
It("skip workflow", func() {
app, runners := makeTestCase([]oamcore.WorkflowStep{})
wf := NewWorkflow(app, k8sClient, common.WorkflowModeStep)
done, pause, err := wf.ExecuteSteps(context.Background(), revision, runners)
state, err := wf.ExecuteSteps(context.Background(), revision, runners)
Expect(err).ToNot(HaveOccurred())
Expect(done).Should(BeTrue())
Expect(pause).Should(BeFalse())
Expect(state).Should(BeEquivalentTo(common.WorkflowStateFinished))
})
It("test for DAG", func() {
@@ -297,10 +287,9 @@ var _ = Describe("Test Workflow", func() {
})
pending = true
wf := NewWorkflow(app, k8sClient, common.WorkflowModeDAG)
done, pause, err := wf.ExecuteSteps(context.Background(), revision, runners)
state, err := wf.ExecuteSteps(context.Background(), revision, runners)
Expect(err).ToNot(HaveOccurred())
Expect(pause).Should(BeFalse())
Expect(done).Should(BeFalse())
Expect(state).Should(BeEquivalentTo(common.WorkflowStateExecuting))
app.Status.Workflow.ContextBackend = nil
Expect(cmp.Diff(*app.Status.Workflow, common.WorkflowStatus{
AppRevision: app.Status.Workflow.AppRevision,
@@ -316,16 +305,14 @@ var _ = Describe("Test Workflow", func() {
}},
})).Should(BeEquivalentTo(""))
done, pause, err = wf.ExecuteSteps(context.Background(), revision, runners)
state, err = wf.ExecuteSteps(context.Background(), revision, runners)
Expect(err).ToNot(HaveOccurred())
Expect(pause).Should(BeFalse())
Expect(done).Should(BeFalse())
Expect(state).Should(BeEquivalentTo(common.WorkflowStateExecuting))
pending = false
done, pause, err = wf.ExecuteSteps(context.Background(), revision, runners)
state, err = wf.ExecuteSteps(context.Background(), revision, runners)
Expect(err).ToNot(HaveOccurred())
Expect(pause).Should(BeFalse())
Expect(done).Should(BeTrue())
Expect(state).Should(BeEquivalentTo(common.WorkflowStateFinished))
app.Status.Workflow.ContextBackend = nil
Expect(cmp.Diff(*app.Status.Workflow, common.WorkflowStatus{
AppRevision: app.Status.Workflow.AppRevision,
+1 -1
View File
@@ -1188,7 +1188,7 @@ type swaggerInfo struct {
// SwaggerInfo holds exported Swagger Info so clients can modify it
var SwaggerInfo = swaggerInfo{
Version: "0.0.1",
Host: "127.0.0.1:38081",
Host: "127.0.0.1:37081",
BasePath: "/api",
Schemes: []string{},
Title: "KubeVela Restful API",
+1 -1
View File
@@ -14,7 +14,7 @@
},
"version": "0.0.1"
},
"host": "127.0.0.1:38081",
"host": "127.0.0.1:37081",
"basePath": "/api",
"paths": {
"/definitions/{definitionName}": {
+1 -1
View File
@@ -466,7 +466,7 @@ definitions:
description: Reference to a trait created by an ApplicationConfiguration.
type: string
type: object
host: 127.0.0.1:38081
host: 127.0.0.1:37081
info:
contact:
email: NA
+1 -1
View File
@@ -42,7 +42,7 @@ import (
// @contact.email NA
// @license.name Apache 2.0
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
// @host 127.0.0.1:38081
// @host 127.0.0.1:37081
// @BasePath /api
func (s *APIServer) setupRoute(staticPath string) http.Handler {
// if deploying static Dashboard, set the mode to `release`, or to `debug`
+1 -1
View File
@@ -26,7 +26,7 @@ import (
)
// DefaultDashboardPort refers to the default port number of dashboard
var DefaultDashboardPort = ":38081"
var DefaultDashboardPort = ":37081"
// DefaultAPIServerPort refers to the default port number of APIServer
const DefaultAPIServerPort = ":38081"
+15 -5
View File
@@ -23,7 +23,6 @@ import (
"github.com/aryann/difflib"
"github.com/pkg/errors"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/yaml"
@@ -256,6 +255,7 @@ func generateManifest(app *v1beta1.Application, comps []*types.ComponentManifest
Name: app.Name,
Kind: AppKind,
}
removeRevisionRelatedLabelAndAnnotation(app)
b, err := yaml.Marshal(app)
if err != nil {
return nil, errors.Wrapf(err, "cannot marshal application %q", app.Name)
@@ -270,7 +270,7 @@ func generateManifest(app *v1beta1.Application, comps []*types.ComponentManifest
Name: comp.Name,
Kind: RawCompKind,
}
emptifyAppRevisionLabel(comp.StandardWorkload)
removeRevisionRelatedLabelAndAnnotation(comp.StandardWorkload)
b, err := yaml.Marshal(comp.StandardWorkload)
if err != nil {
return nil, errors.Wrapf(err, "cannot marshal component %q", comp.Name)
@@ -290,7 +290,7 @@ func generateManifest(app *v1beta1.Application, comps []*types.ComponentManifest
// get matched raw component and add it into appConfigComponent's subs
subs := []*manifest{rawCompManifests[comp.Name]}
for _, t := range comp.Traits {
emptifyAppRevisionLabel(t)
removeRevisionRelatedLabelAndAnnotation(t)
tType := t.GetLabels()[oam.TraitTypeLabel]
tResource := t.GetLabels()[oam.TraitResource]
@@ -345,9 +345,9 @@ func extractNameFromRevisionName(r string) string {
return strings.Join(s[0:len(s)-1], "-")
}
// emptifyAppRevisionLabel will set label oam.LabelAppRevision to empty
// removeRevisionRelatedLabelAndAnnotation will set label oam.LabelAppRevision to empty
// because dry-run cannot set value to this label
func emptifyAppRevisionLabel(o *unstructured.Unstructured) {
func removeRevisionRelatedLabelAndAnnotation(o client.Object) {
newLabels := map[string]string{}
labels := o.GetLabels()
for k, v := range labels {
@@ -358,6 +358,16 @@ func emptifyAppRevisionLabel(o *unstructured.Unstructured) {
newLabels[k] = v
}
o.SetLabels(newLabels)
newAnnotations := map[string]string{}
annotations := o.GetAnnotations()
for k, v := range annotations {
if k == oam.AnnotationKubeVelaVersion || k == oam.AnnotationAppRevision {
continue
}
newAnnotations[k] = v
}
o.SetAnnotations(newAnnotations)
}
// hasChanges checks whether existing change in diff records
+7
View File
@@ -320,6 +320,13 @@ func trackHealthCheckingStatus(ctx context.Context, c client.Client, compName, a
}
}
if wlhc == nil {
cTime := app.GetCreationTimestamp()
if time.Since(cTime.Time) <= deployTimeout {
return compStatusHealthChecking, HealthStatusUnknown, "", nil
}
if len(healthScope.Spec.AppRefs) == 0 && len(healthScope.Spec.WorkloadReferences) == 0 {
return compStatusHealthCheckDone, HealthStatusHealthy, "no workload or app found in health scope", nil
}
return compStatusUnknown, HealthStatusUnknown, "", fmt.Errorf("cannot get health condition from the health scope: %s", healthScope.Name)
}
healthStatus = wlhc.HealthStatus
+5 -6
View File
@@ -33,10 +33,9 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
apicommon "github.com/oam-dev/kubevela/apis/core.oam.dev/common"
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
"github.com/oam-dev/kubevela/apis/standard.oam.dev/v1alpha1"
"github.com/oam-dev/kubevela/pkg/controller/utils"
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
"github.com/oam-dev/kubevela/pkg/oam/util"
"github.com/oam-dev/kubevela/pkg/utils/common"
)
@@ -230,7 +229,7 @@ var _ = Describe("rollout related e2e-test,Cloneset based app embed rollout test
}, time.Second*30, time.Microsecond*300).Should(BeNil())
}
PIt("Test upgrade application", func() {
It("Test upgrade application", func() {
plan := &v1alpha1.RolloutPlan{
RolloutStrategy: v1alpha1.IncreaseFirstRolloutStrategyType,
RolloutBatches: []v1alpha1.RolloutBatch{
@@ -364,7 +363,7 @@ var _ = Describe("rollout related e2e-test,Cloneset based app embed rollout test
verifyRolloutSucceeded(utils.ConstructRevisionName(appName, 3), "3")
})
PIt("Test upgrade application in middle of rolling out", func() {
It("Test upgrade application in middle of rolling out", func() {
plan := &v1alpha1.RolloutPlan{
RolloutStrategy: v1alpha1.IncreaseFirstRolloutStrategyType,
RolloutBatches: []v1alpha1.RolloutBatch{
@@ -406,7 +405,7 @@ var _ = Describe("rollout related e2e-test,Cloneset based app embed rollout test
verifyRolloutSucceeded(utils.ConstructRevisionName(appName, 3), "3")
})
PIt("Test pause in middle of embed app rolling out", func() {
It("Test pause in middle of embed app rolling out", func() {
plan := &v1alpha1.RolloutPlan{
RolloutStrategy: v1alpha1.IncreaseFirstRolloutStrategyType,
RolloutBatches: []v1alpha1.RolloutBatch{
@@ -479,7 +478,7 @@ var _ = Describe("rollout related e2e-test,Cloneset based app embed rollout test
verifyRolloutSucceeded(utils.ConstructRevisionName(appName, 2), "2")
})
PIt("Test rollout with trait", func() {
It("Test rollout with trait", func() {
plan := &v1alpha1.RolloutPlan{
RolloutStrategy: v1alpha1.IncreaseFirstRolloutStrategyType,
RolloutBatches: []v1alpha1.RolloutBatch{
+13 -13
View File
@@ -77,7 +77,7 @@ var _ = Describe("Test application cross namespace resource", func() {
Expect(k8sClient.Delete(ctx, &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: crossNamespace}}, client.PropagationPolicy(metav1.DeletePropagationForeground))).Should(Succeed())
})
PIt("Test application containing cluster-scoped trait", func() {
It("Test application containing cluster-scoped trait", func() {
By("Install TraitDefinition")
traitDef := &v1beta1.TraitDefinition{}
Expect(yaml.Unmarshal([]byte(fmt.Sprintf(clusterScopeTraitDefYAML, namespace)), traitDef)).Should(Succeed())
@@ -139,7 +139,7 @@ var _ = Describe("Test application cross namespace resource", func() {
}, 20*time.Second, 500*time.Millisecond).Should(BeNil())
})
PIt("Test GC for cluster-scoped trait", func() {
It("Test GC for cluster-scoped trait", func() {
By("Install cluster-scoped trait's TraitDefinition")
clusterTraitDef := &v1beta1.TraitDefinition{}
Expect(yaml.Unmarshal([]byte(fmt.Sprintf(clusterScopeTraitDefYAML, namespace)), clusterTraitDef)).Should(Succeed())
@@ -253,7 +253,7 @@ var _ = Describe("Test application cross namespace resource", func() {
}, 20*time.Second, 2*time.Second).Should(SatisfyAll(&util.NotFoundMatcher{}))
})
PIt("Test application have cross-namespace workload", func() {
It("Test application have cross-namespace workload", func() {
// install component definition
crossCdJson, _ := yaml.YAMLToJSON([]byte(fmt.Sprintf(crossCompDefYaml, namespace, crossNamespace)))
ccd := new(v1beta1.ComponentDefinition)
@@ -351,7 +351,7 @@ var _ = Describe("Test application cross namespace resource", func() {
}, time.Second*5, time.Millisecond*300).Should(BeNil())
})
PIt("Test update application by add a cross namespace trait resource ", func() {
It("Test update application by add a cross namespace trait resource ", func() {
var (
appName = "test-app-2"
app = new(v1beta1.Application)
@@ -394,7 +394,7 @@ var _ = Describe("Test application cross namespace resource", func() {
if err := k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: appName}, app); err != nil {
return fmt.Errorf("error to create application %v", err)
}
if app.Status.Phase != common.ApplicationRunning {
if app.Status.Phase != common.ApplicationRunning || app.Status.ObservedGeneration != app.Generation {
return fmt.Errorf("application status not running")
}
depolys := new(appsv1.DeploymentList)
@@ -461,13 +461,13 @@ var _ = Describe("Test application cross namespace resource", func() {
return fmt.Errorf("trait owner reference missmatch")
}
if len(resourceTracker.Status.TrackedResources) != 2 {
return fmt.Errorf("expect track %q resources, but got %q", 2, len(resourceTracker.Status.TrackedResources))
return fmt.Errorf("expect track %d resources, but got %d", 2, len(resourceTracker.Status.TrackedResources))
}
return nil
}, time.Second*5, time.Millisecond*500).Should(BeNil())
})
PIt("Test update application by delete a cross namespace trait resource", func() {
It("Test update application by delete a cross namespace trait resource", func() {
var (
appName = "test-app-3"
app = new(v1beta1.Application)
@@ -516,7 +516,7 @@ var _ = Describe("Test application cross namespace resource", func() {
if err := k8sClient.Get(ctx, types.NamespacedName{Namespace: namespace, Name: appName}, app); err != nil {
return fmt.Errorf("error to get application %v", err)
}
if app.Status.Phase != common.ApplicationRunning {
if app.Status.Phase != common.ApplicationRunning || app.Status.ObservedGeneration != app.Generation {
return fmt.Errorf("application status not running")
}
err := k8sClient.Get(ctx, generateResourceTrackerKey(app.Namespace, app.Name, 1), resourceTracker)
@@ -578,7 +578,7 @@ var _ = Describe("Test application cross namespace resource", func() {
}, time.Second*5, time.Millisecond*500).Should(BeNil())
})
PIt("Test application have two different workload", func() {
It("Test application have two different workload", func() {
var (
appName = "test-app-4"
app = new(v1beta1.Application)
@@ -717,7 +717,7 @@ var _ = Describe("Test application cross namespace resource", func() {
}, time.Second*5, time.Millisecond*300).Should(BeNil())
})
PIt("Update a cross namespace workload of application", func() {
It("Update a cross namespace workload of application", func() {
// install component definition
crossCdJson, _ := yaml.YAMLToJSON([]byte(fmt.Sprintf(crossCompDefYaml, namespace, crossNamespace)))
ccd := new(v1beta1.ComponentDefinition)
@@ -857,7 +857,7 @@ var _ = Describe("Test application cross namespace resource", func() {
}, time.Second*5, time.Millisecond*500).Should(BeNil())
})
PIt("Test cross-namespace resource gc logic, delete a cross-ns component", func() {
It("Test cross-namespace resource gc logic, delete a cross-ns component", func() {
var (
appName = "test-app-6"
app = new(v1beta1.Application)
@@ -1006,7 +1006,7 @@ var _ = Describe("Test application cross namespace resource", func() {
}, time.Second*5, time.Millisecond*500).Should(BeNil())
})
PIt("Test cross-namespace resource gc logic, delete a cross-ns trait", func() {
It("Test cross-namespace resource gc logic, delete a cross-ns trait", func() {
var (
appName = "test-app-7"
app = new(v1beta1.Application)
@@ -1167,7 +1167,7 @@ var _ = Describe("Test application cross namespace resource", func() {
}, time.Second*5, time.Millisecond*500).Should(BeNil())
})
PIt("Test cross-namespace resource gc logic, update a cross-ns workload's namespace", func() {
It("Test cross-namespace resource gc logic, update a cross-ns workload's namespace", func() {
// install related definition
crossCdJson, _ := yaml.YAMLToJSON([]byte(fmt.Sprintf(crossCompDefYaml, namespace, crossNamespace)))
ccd := new(v1beta1.ComponentDefinition)
+23 -9
View File
@@ -71,11 +71,10 @@ var _ = Describe("Test application controller clean up appRevision", func() {
k8sClient.DeleteAllOf(ctx, &v1beta1.ComponentDefinition{}, client.InNamespace(namespace))
k8sClient.DeleteAllOf(ctx, &v1beta1.WorkloadDefinition{}, client.InNamespace(namespace))
k8sClient.DeleteAllOf(ctx, &v1beta1.TraitDefinition{}, client.InNamespace(namespace))
Expect(k8sClient.Delete(ctx, &v1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: namespace}}, client.PropagationPolicy(metav1.DeletePropagationForeground))).Should(Succeed())
})
PIt("Test clean up appRevision", func() {
It("Test clean up appRevision", func() {
appName := "app-1"
appKey := types.NamespacedName{Namespace: namespace, Name: appName}
app := getApp(appName, namespace, "normal-worker")
@@ -100,6 +99,15 @@ var _ = Describe("Test application controller clean up appRevision", func() {
}
return nil
}, time.Second*10, time.Millisecond*500).Should(BeNil())
Eventually(func() error {
checkApp = new(v1beta1.Application)
Expect(k8sClient.Get(ctx, appKey, checkApp)).Should(BeNil())
if checkApp.Status.ObservedGeneration == checkApp.Generation && checkApp.Status.Phase == common.ApplicationRunning {
return nil
}
return fmt.Errorf("application is not observed or status %s is not running", checkApp.Status.Phase)
}, time.Second*10, time.Millisecond*500).Should(BeNil())
}
listOpts := []client.ListOption{
client.InNamespace(namespace),
@@ -118,11 +126,17 @@ var _ = Describe("Test application controller clean up appRevision", func() {
}
return nil
}, time.Second*10, time.Millisecond*500).Should(BeNil())
By("create new appRevision will remove appRevison1")
Expect(k8sClient.Get(ctx, appKey, checkApp)).Should(BeNil())
property := fmt.Sprintf(`{"cmd":["sleep","1000"],"image":"busybox:%d"}`, 5)
checkApp.Spec.Components[0].Properties = runtime.RawExtension{Raw: []byte(property)}
Expect(k8sClient.Update(ctx, checkApp)).Should(BeNil())
By("create new appRevision will remove appRevision v1")
Eventually(func() error {
err := k8sClient.Get(ctx, appKey, checkApp)
if err != nil {
return err
}
property := fmt.Sprintf(`{"cmd":["sleep","1000"],"image":"busybox:%d"}`, 5)
checkApp.Spec.Components[0].Properties = runtime.RawExtension{Raw: []byte(property)}
return k8sClient.Update(ctx, checkApp)
}, time.Second*10, time.Millisecond*500).Should(BeNil())
deletedRevison := new(v1beta1.ApplicationRevision)
revKey := types.NamespacedName{Namespace: namespace, Name: appName + "-v1"}
Eventually(func() error {
@@ -148,7 +162,7 @@ var _ = Describe("Test application controller clean up appRevision", func() {
if err := k8sClient.Get(ctx, appKey, checkApp); err != nil {
return err
}
property = fmt.Sprintf(`{"cmd":["sleep","1000"],"image":"busybox:%d"}`, 6)
property := fmt.Sprintf(`{"cmd":["sleep","1000"],"image":"busybox:%d"}`, 6)
checkApp.Spec.Components[0].Properties = runtime.RawExtension{Raw: []byte(property)}
if err := k8sClient.Update(ctx, checkApp); err != nil {
return err
@@ -175,7 +189,7 @@ var _ = Describe("Test application controller clean up appRevision", func() {
}, time.Second*10, time.Millisecond*500).Should(BeNil())
})
PIt("Test clean up rollout appRevision", func() {
It("Test clean up rollout appRevision", func() {
appName := "app-2"
appKey := types.NamespacedName{Namespace: namespace, Name: appName}
app := getApp(appName, namespace, "normal-worker")
+2 -2
View File
@@ -136,7 +136,7 @@ var _ = Describe("Finalizer for HealthScope in ApplicationConfiguration", func()
})
When("AppConfig has no scopes", func() {
PIt("should not register finalizer", func() {
It("should not register finalizer", func() {
appConfig.Spec.Components = []v1alpha2.ApplicationConfigurationComponent{
{
ComponentName: componentName,
@@ -166,7 +166,7 @@ var _ = Describe("Finalizer for HealthScope in ApplicationConfiguration", func()
})
When("AppConfig has scopes", func() {
PIt("should handle finalizer before being deleted", func() {
It("should handle finalizer before being deleted", func() {
// create health scope definition
sd := v1alpha2.ScopeDefinition{
ObjectMeta: metav1.ObjectMeta{
@@ -80,7 +80,7 @@ var _ = Describe("AppConfig renders workloads", func() {
Expect(k8sClient.Delete(ctx, &ns, client.PropagationPolicy(metav1.DeletePropagationForeground))).Should(BeNil())
})
PIt("Test AppConfig controller renders workloads", func() {
It("Test AppConfig controller renders workloads", func() {
By("Create WorkloadDefinition")
d := wd(wdNameAndDef(wdName))
Expect(k8sClient.Create(ctx, d)).Should(Succeed())
+2 -2
View File
@@ -64,7 +64,7 @@ var _ = Describe("Test compatibility for deprecation of appContext", func() {
Expect(k8sClient.DeleteAllOf(ctx, &corev1.PersistentVolume{})).Should(Succeed())
})
PIt("Test application can update its resources' owners", func() {
It("Test application can update its resources' owners", func() {
var err error
var appCtxKey, rtKey *client.ObjectKey
@@ -162,7 +162,7 @@ var _ = Describe("Test compatibility for deprecation of appContext", func() {
}, 30*time.Second, 500*time.Millisecond).Should(util.NotFoundMatcher{})
})
PIt("Test delete an application with a legacy finalizer", func() {
It("Test delete an application with a legacy finalizer", func() {
var err error
var rtKey *client.ObjectKey
// simulate a resource tracker created by a legacy application
+6 -6
View File
@@ -160,7 +160,7 @@ var _ = Describe("Application Normal tests", func() {
Expect(k8sClient.Delete(ctx, &ns, client.PropagationPolicy(metav1.DeletePropagationBackground))).Should(BeNil())
})
PIt("Test app created normally", func() {
It("Test app created normally", func() {
applyApp("app1.yaml")
By("Apply the application rollout go directly to the target")
verifyWorkloadRunningExpected("myweb", 1, "stefanprodan/podinfo:4.0.3")
@@ -185,7 +185,7 @@ var _ = Describe("Application Normal tests", func() {
verifyComponentRevision("myweb", 4)
})
PIt("Test app have component with multiple same type traits", func() {
It("Test app have component with multiple same type traits", func() {
traitDef := new(v1beta1.TraitDefinition)
Expect(common.ReadYamlToObject("testdata/app/trait_config.yaml", traitDef)).Should(BeNil())
traitDef.Namespace = namespaceName
@@ -216,7 +216,7 @@ var _ = Describe("Application Normal tests", func() {
Expect(testApp.Status.Services[0].Traits[1].Message).Should(Equal("secret:app-env-config"))
})
PIt("Test app have rollout-template false annotation", func() {
It("Test app have rollout-template false annotation", func() {
By("Apply an application")
var newApp v1beta1.Application
Expect(common.ReadYamlToObject("testdata/app/app5.yaml", &newApp)).Should(BeNil())
@@ -224,7 +224,7 @@ var _ = Describe("Application Normal tests", func() {
Expect(k8sClient.Create(ctx, &newApp)).ShouldNot(BeNil())
})
PIt("Test app have empty rollingBatches rolloutPlan", func() {
It("Test app have empty rollingBatches rolloutPlan", func() {
By("Apply an application")
var newApp v1beta1.Application
Expect(common.ReadYamlToObject("testdata/app/app6.yaml", &newApp)).Should(BeNil())
@@ -232,7 +232,7 @@ var _ = Describe("Application Normal tests", func() {
Expect(k8sClient.Create(ctx, &newApp)).ShouldNot(BeNil())
})
PIt("Test app have components with same name", func() {
It("Test app have components with same name", func() {
By("Apply an application")
var newApp v1beta1.Application
Expect(common.ReadYamlToObject("testdata/app/app8.yaml", &newApp)).Should(BeNil())
@@ -240,7 +240,7 @@ var _ = Describe("Application Normal tests", func() {
Expect(k8sClient.Create(ctx, &newApp)).ShouldNot(BeNil())
})
PIt("Test two app have component with same name", func() {
It("Test two app have component with same name", func() {
By("Apply an application")
var firstApp v1beta1.Application
Expect(common.ReadYamlToObject("testdata/app/app9.yaml", &firstApp)).Should(BeNil())
+1 -1
View File
@@ -594,7 +594,7 @@ var _ = Describe("Component revision", func() {
}
Context("Attach a revision-enable trait the first time, workload should not be recreated", func() {
PIt("should create Component and ApplicationConfiguration", func() {
It("should create Component and ApplicationConfiguration", func() {
By("submit Component")
Expect(k8sClient.Create(ctx, &component)).Should(Succeed())
By("check Component exist")
+2 -2
View File
@@ -227,7 +227,7 @@ var _ = Describe("ContainerizedWorkload", func() {
Expect(k8sClient.Delete(ctx, &ns, client.PropagationPolicy(metav1.DeletePropagationForeground))).Should(BeNil())
})
PIt("apply an application config", func() {
It("apply an application config", func() {
logf.Log.Info("Creating workload definition")
// For some reason, WorkloadDefinition is created as a Cluster scope object
Expect(k8sClient.Create(ctx, &wd)).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{}))
@@ -325,7 +325,7 @@ var _ = Describe("ContainerizedWorkload", func() {
time.Second*15, time.Millisecond*500).Should(BeTrue())
})
PIt("checking appConfig status changed outside of the controller loop is preserved", func() {
It("checking appConfig status changed outside of the controller loop is preserved", func() {
logf.Log.Info("Creating workload definition")
// For some reason, WorkloadDefinition is created as a Cluster scope object
Expect(k8sClient.Create(ctx, &wd)).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{}))
+7 -7
View File
@@ -62,7 +62,7 @@ var _ = Describe("ComponentDefinition Normal tests", func() {
Context("Test dynamic admission control for componentDefinition", func() {
PIt("Test componentDefinition which only set type field", func() {
It("Test componentDefinition which only set type field", func() {
workDef := &v1beta1.WorkloadDefinition{
TypeMeta: metav1.TypeMeta{
Kind: "ComponentDefinition",
@@ -95,7 +95,7 @@ var _ = Describe("ComponentDefinition Normal tests", func() {
}).Should(BeNil())
})
PIt("Test componentDefinition only set definition field", func() {
It("Test componentDefinition only set definition field", func() {
testCd := webServiceWithNoTemplate.DeepCopy()
testCd.Spec.Schematic.CUE.Template = webServiceV1Template
testCd.SetName("test-componentdef-v1")
@@ -121,7 +121,7 @@ var _ = Describe("ComponentDefinition Normal tests", func() {
Expect(newWd.Spec.Reference.Version).To(Equal("v1"))
})
PIt("Test componentDefinition which definition and type fields are all empty", func() {
It("Test componentDefinition which definition and type fields are all empty", func() {
testCd1 := webServiceWithNoTemplate.DeepCopy()
testCd1.SetName("test-componentdef-v2")
testCd1.Spec.Workload.Definition = common.WorkloadGVK{}
@@ -136,7 +136,7 @@ var _ = Describe("ComponentDefinition Normal tests", func() {
Expect(newCd.Spec.Workload.Type).Should(Equal(types.AutoDetectWorkloadDefinition))
})
PIt("Test componentDefinition which definition and type point to same workload type", func() {
It("Test componentDefinition which definition and type point to same workload type", func() {
testCd2 := webServiceWithNoTemplate.DeepCopy()
testCd2.SetName("test-componentdef-v3")
testCd2.Spec.Workload.Type = "deployments.apps"
@@ -145,7 +145,7 @@ var _ = Describe("ComponentDefinition Normal tests", func() {
Expect(k8sClient.Create(ctx, testCd2)).Should(Succeed())
})
PIt("Test componentDefinition which definition and type point to different workload type", func() {
It("Test componentDefinition which definition and type point to different workload type", func() {
testCd3 := webServiceWithNoTemplate.DeepCopy()
testCd3.SetName("test-componentdef-v4")
testCd3.Spec.Workload.Type = "jobs.batch"
@@ -154,7 +154,7 @@ var _ = Describe("ComponentDefinition Normal tests", func() {
Expect(k8sClient.Create(ctx, testCd3)).Should(HaveOccurred())
})
PIt("Test componentDefinition which specify the name of definitionRevision", func() {
It("Test componentDefinition which specify the name of definitionRevision", func() {
By("create componentDefinition")
cd := webServiceWithNoTemplate.DeepCopy()
cd.SetNamespace(namespace)
@@ -184,7 +184,7 @@ var _ = Describe("ComponentDefinition Normal tests", func() {
})
Context("Test dynamic admission control for traitDefinition", func() {
PIt("Test traitDefinition which specify the name of definitionRevision", func() {
It("Test traitDefinition which specify the name of definitionRevision", func() {
By("create traitDefinition")
td := exposeWithNoTemplate.DeepCopy()
td.SetNamespace(namespace)
+13 -12
View File
@@ -23,6 +23,8 @@ import (
"strings"
"time"
"github.com/oam-dev/kubevela/apis/types"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -116,13 +118,13 @@ var _ = Describe("Test application containing helm module", func() {
AfterEach(func() {
By("Clean up resources after a test")
k8sClient.DeleteAllOf(ctx, &v1beta1.Application{}, client.InNamespace(namespace))
k8sClient.DeleteAllOf(ctx, &v1beta1.ComponentDefinition{}, client.InNamespace(namespace))
k8sClient.DeleteAllOf(ctx, &v1beta1.WorkloadDefinition{}, client.InNamespace(namespace))
k8sClient.DeleteAllOf(ctx, &v1beta1.TraitDefinition{}, client.InNamespace(namespace))
By(fmt.Sprintf("Delete the entire namespaceName %s", ns.Name))
Expect(k8sClient.Delete(ctx, &ns, client.PropagationPolicy(metav1.DeletePropagationForeground))).Should(Succeed())
By("Remove 'deployments.apps' from scaler's appliesToWorkloads")
scalerTd := v1beta1.TraitDefinition{}
Expect(k8sClient.Get(ctx, client.ObjectKey{Name: "scaler", Namespace: "vela-system"}, &scalerTd)).Should(Succeed())
@@ -131,7 +133,7 @@ var _ = Describe("Test application containing helm module", func() {
Expect(k8sClient.Patch(ctx, &scalerTd, client.Merge)).Should(Succeed())
})
PIt("Test deploy an application containing helm module", func() {
It("Test deploy an application containing helm module", func() {
app = v1beta1.Application{
ObjectMeta: metav1.ObjectMeta{
Name: appName,
@@ -151,7 +153,7 @@ var _ = Describe("Test application containing helm module", func() {
{
Type: "scaler",
Properties: util.Object2RawExtension(map[string]interface{}{
"replicas": 2,
"replicas": 0,
}),
},
{
@@ -190,7 +192,7 @@ var _ = Describe("Test application containing helm module", func() {
return false
}
By("Verify scaler trait is applied")
if *deploy.Spec.Replicas != 2 {
if *deploy.Spec.Replicas != 0 {
return false
}
By("Verify application's settings override chart default values")
@@ -212,14 +214,14 @@ var _ = Describe("Test application containing helm module", func() {
Type: cdName,
Properties: util.Object2RawExtension(map[string]interface{}{
"image": map[string]interface{}{
"tag": "5.1.3", // change 5.1.4 => 5.1.3
"tag": "5.1.3", // change 5.1.2 => 5.1.3
},
}),
Traits: []common.ApplicationTrait{
{
Type: "scaler",
Properties: util.Object2RawExtension(map[string]interface{}{
"replicas": 3, // change 2 => 3
"replicas": 1, // change 0 => 1
}),
},
{
@@ -248,9 +250,7 @@ var _ = Describe("Test application containing helm module", func() {
return false
}
By("Verify new scaler trait is applied")
// TODO(roywang) how to enforce scaler controller reconcile
// immediately? e2e test cannot wait 5min for reconciliation.
if *deploy.Spec.Replicas == 2 {
if *deploy.Spec.Replicas != 1 {
return false
}
By("Verify new application's settings override chart default values")
@@ -258,7 +258,7 @@ var _ = Describe("Test application containing helm module", func() {
}, 120*time.Second, 10*time.Second).Should(BeTrue())
})
PIt("Test deploy an application containing helm module defined by workloadDefinition", func() {
It("Test deploy an application containing helm module defined by workloadDefinition", func() {
workloaddef := v1beta1.WorkloadDefinition{}
workloaddef.SetName(wdName)
@@ -315,7 +315,7 @@ var _ = Describe("Test application containing helm module", func() {
}, 240*time.Second, 5*time.Second).Should(Succeed())
})
PIt("Test deploy an application containing helm module and the componet refer to autodetect type workload", func() {
It("Test deploy an application containing helm module and the component refer to autodetect type workload", func() {
cd := v1beta1.ComponentDefinition{}
cd.SetName("podinfo")
cd.SetNamespace(namespace)
@@ -334,6 +334,7 @@ var _ = Describe("Test application containing helm module", func() {
}),
},
}
cd.Spec.Workload.Type = types.AutoDetectWorkloadDefinition
Expect(k8sClient.Create(ctx, &cd)).Should(Succeed())
newAppName := "test-autodetect"
@@ -369,7 +370,7 @@ var _ = Describe("Test application containing helm module", func() {
}, 120*time.Second, 5*time.Second).Should(Succeed())
})
PIt("Test store JSON schema of Helm Chart in ConfigMap", func() {
It("Test store JSON schema of Helm Chart in ConfigMap", func() {
By("Get the ConfigMap")
cmName := fmt.Sprintf("schema-%s", cdName)
Eventually(func() error {
+6 -6
View File
@@ -72,7 +72,7 @@ var _ = Describe("Initializer Normal tests", func() {
Expect(k8sClient.Delete(ctx, &ns, client.PropagationPolicy(metav1.DeletePropagationForeground))).Should(Succeed())
})
PIt("Test apply initializer without dependsOn", func() {
It("Test apply initializer without dependsOn", func() {
compName := "env1-comp"
init := &v1beta1.Initializer{
TypeMeta: metav1.TypeMeta{
@@ -125,7 +125,7 @@ var _ = Describe("Initializer Normal tests", func() {
}, 30*time.Second, 5*time.Second).Should(Succeed())
})
PIt("Test apply initializer which will create namespace", func() {
It("Test apply initializer which will create namespace", func() {
randomNs := randomNamespaceName("initializer-createns")
init := &v1beta1.Initializer{
TypeMeta: metav1.TypeMeta{
@@ -182,7 +182,7 @@ var _ = Describe("Initializer Normal tests", func() {
Context("Test apply initializer depends on other initializer", func() {
PIt("initializer depends on existing initializer", func() {
It("initializer depends on existing initializer", func() {
compName := "env2-comp"
init := &v1beta1.Initializer{
@@ -279,7 +279,7 @@ var _ = Describe("Initializer Normal tests", func() {
}, 30*time.Second, 5*time.Second).Should(Succeed())
})
PIt("initializer depends on not non-built-in initializer not found, should be rejected by webhook", func() {
It("initializer depends on not non-built-in initializer not found, should be rejected by webhook", func() {
init := &v1beta1.Initializer{
TypeMeta: metav1.TypeMeta{
Kind: "Initializer",
@@ -319,7 +319,7 @@ var _ = Describe("Initializer Normal tests", func() {
Expect(k8sClient.Create(ctx, init)).Should(HaveOccurred())
})
PIt("initializer depends on built-in initializer", func() {
It("initializer depends on built-in initializer", func() {
initCm := &corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{
Kind: "ConfigMap",
@@ -406,7 +406,7 @@ var _ = Describe("Initializer Normal tests", func() {
}, 120*time.Second, 500*time.Millisecond).Should(Succeed())
})
PIt("Deleting initializer depended by other initializer should be rejected by webhook", func() {
It("Deleting initializer depended by other initializer should be rejected by webhook", func() {
initA := &v1beta1.Initializer{
TypeMeta: metav1.TypeMeta{
Kind: "Initializer",
+3 -3
View File
@@ -163,7 +163,7 @@ spec:
Expect(k8sClient.Patch(ctx, &scalerTd, client.Merge)).Should(Succeed())
})
PIt("Test deploy an application containing kube module", func() {
It("Test deploy an application containing kube module", func() {
app = v1beta1.Application{
ObjectMeta: metav1.ObjectMeta{
Name: appName,
@@ -286,7 +286,7 @@ spec:
}, 60*time.Second, 10*time.Second).Should(BeTrue())
})
PIt("Test deploy an application containing kube module defined by workloadDefinition", func() {
It("Test deploy an application containing kube module defined by workloadDefinition", func() {
workloaddef := v1beta1.WorkloadDefinition{}
workloaddef.SetName(wdName)
workloaddef.SetNamespace(namespace)
@@ -339,7 +339,7 @@ spec:
}, 15*time.Second, 3*time.Second).Should(Succeed())
})
PIt("Test store JSON schema of Kube parameter in ConfigMap", func() {
It("Test store JSON schema of Kube parameter in ConfigMap", func() {
By("Get the ConfigMap")
cmName := fmt.Sprintf("schema-%s", cdName)
Eventually(func() error {
+1 -1
View File
@@ -75,7 +75,7 @@ var _ = Describe("Test kubernetes native workloads", func() {
Expect(k8sClient.Delete(ctx, &ns, client.PropagationPolicy(metav1.DeletePropagationForeground))).Should(BeNil())
})
PIt("use deployment workload", func() {
It("use deployment workload", func() {
label := map[string]string{"workload": "deployment"}
// create a workload definition for
wd := v1alpha2.WorkloadDefinition{
+12 -35
View File
@@ -360,7 +360,7 @@ var _ = Describe("rollout related e2e-test,Cloneset based rollout tests", func()
Expect(k8sClient.Delete(ctx, &ns, client.PropagationPolicy(metav1.DeletePropagationBackground))).Should(BeNil())
})
PIt("Test cloneset basic scale", func() {
It("Test cloneset basic scale", func() {
CreateClonesetDef()
applySourceApp("app-no-replica.yaml")
By("Apply the application rollout go directly to the target")
@@ -375,7 +375,7 @@ var _ = Describe("rollout related e2e-test,Cloneset based rollout tests", func()
verifyRolloutSucceeded(appRollout.Spec.TargetAppRevisionName)
})
PIt("Test cloneset rollout with a manual check", func() {
It("Test cloneset rollout with a manual check", func() {
applyTwoAppVersion()
// scale to v1
initialScale()
@@ -431,7 +431,7 @@ var _ = Describe("rollout related e2e-test,Cloneset based rollout tests", func()
verifyRolloutSucceeded(appRollout.Spec.TargetAppRevisionName)
})
PIt("Test pause and modify rollout plan after rolling succeeded", func() {
It("Test pause and modify rollout plan after rolling succeeded", func() {
CreateClonesetDef()
applySourceApp("app-no-replica.yaml")
By("Apply the application rollout go directly to the target")
@@ -502,7 +502,7 @@ var _ = Describe("rollout related e2e-test,Cloneset based rollout tests", func()
Expect(appRollout.Status.GetCondition(oamstd.RolloutSucceed).LastTransitionTime).Should(BeEquivalentTo(lt))
})
PIt("Test rolling forward after a successful rollout", func() {
It("Test rolling forward after a successful rollout", func() {
applyTwoAppVersion()
// scale to v1
initialScale()
@@ -529,7 +529,7 @@ var _ = Describe("rollout related e2e-test,Cloneset based rollout tests", func()
rollForwardToSource()
})
PIt("Test rolling forward in the middle of rollout", func() {
It("Test rolling forward in the middle of rollout", func() {
applyTwoAppVersion()
// scale to v1
initialScale()
@@ -555,7 +555,7 @@ var _ = Describe("rollout related e2e-test,Cloneset based rollout tests", func()
rollForwardToSource()
})
PIt("Test delete rollout plan should not remove workload", func() {
It("Test delete rollout plan should not remove workload", func() {
CreateClonesetDef()
applyTwoAppVersion()
// scale to v1
@@ -598,7 +598,7 @@ var _ = Describe("rollout related e2e-test,Cloneset based rollout tests", func()
}, time.Second*30, time.Second).Should(BeTrue())
})
PIt("Test revert the rollout plan in the middle of rollout", func() {
It("Test revert the rollout plan in the middle of rollout", func() {
CreateClonesetDef()
applyTwoAppVersion()
// scale to v1
@@ -648,7 +648,7 @@ var _ = Describe("rollout related e2e-test,Cloneset based rollout tests", func()
}, time.Second*30, time.Second).Should(BeEquivalentTo(v1beta1.ResourceTrackerKind))
})
PIt("Test rollout will update same name trait", func() {
It("Test rollout will update same name trait", func() {
CreateClonesetDef()
CreateIngressDef()
applySourceApp("app-with-ingress-source.yaml")
@@ -680,7 +680,7 @@ var _ = Describe("rollout related e2e-test,Cloneset based rollout tests", func()
verifyIngress("test-1.example.com")
})
PIt("Test rollout succeed will gc useless trait", func() {
It("Test rollout succeed will gc useless trait", func() {
CreateClonesetDef()
CreateIngressDef()
applySourceApp("app-with-ingress-source.yaml")
@@ -716,7 +716,7 @@ var _ = Describe("rollout related e2e-test,Cloneset based rollout tests", func()
}, time.Second*30, 300*time.Microsecond).Should(util.NotFoundMatcher{})
})
PIt("Test scale again by modify targetSize", func() {
It("Test scale again by modify targetSize", func() {
var err error
CreateClonesetDef()
applySourceApp("app-no-replica.yaml")
@@ -784,30 +784,7 @@ var _ = Describe("rollout related e2e-test,Cloneset based rollout tests", func()
verifyRolloutSucceeded(appRollout.Spec.TargetAppRevisionName)
})
PIt("Test rolling by changing the definition", func() {
CreateClonesetDef()
applySourceApp("app-source.yaml")
By("Apply the definition change")
var cd, newCD v1beta1.ComponentDefinition
Expect(common.ReadYamlToObject("testdata/rollout/cloneset/clonesetDefinitionModified.yaml.yaml", &newCD)).Should(BeNil())
Eventually(
func() error {
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: newCD.Name}, &cd)
cd.Spec = newCD.Spec
return k8sClient.Update(ctx, &cd)
},
time.Second*3, time.Millisecond*300).Should(Succeed())
By("Apply the application rollout")
var newAppRollout v1beta1.AppRollout
Expect(common.ReadYamlToObject("testdata/rollout/cloneset/appRollout.yaml", &newAppRollout)).Should(BeNil())
Expect(common.ReadYamlToObject("testdata/rollout/cloneset/appRollout.yaml", &newAppRollout)).Should(BeNil())
newAppRollout.Namespace = namespaceName
newAppRollout.Spec.RolloutPlan.BatchPartition = pointer.Int32Ptr(int32(len(newAppRollout.Spec.RolloutPlan.
RolloutBatches) - 1))
createAppRolling(&newAppRollout)
verifyRolloutSucceeded(appRollout.Spec.TargetAppRevisionName)
// Clean up
k8sClient.Delete(ctx, &appRollout)
It("Test rolling by changing the definition", func() {
//TODO(@wonderflow): we should support rollout by changing definition
})
})
+1 -1
View File
@@ -164,7 +164,7 @@ var _ = Describe("rollout related e2e-test,rollout trait test", func() {
Expect(k8sClient.Delete(ctx, &ns, client.PropagationPolicy(metav1.DeletePropagationBackground))).Should(BeNil())
})
PIt("rollout as a trait whole process e2e-test", func() {
It("rollout as a trait whole process e2e-test", func() {
By("first scale operation")
Expect(common.ReadYamlToObject("testdata/rollout/deployment/application.yaml", &app)).Should(BeNil())
app.Namespace = namespaceName