mirror of
https://github.com/kubevela/kubevela.git
synced 2026-08-18 20:17:04 +00:00
rollout OCM demo and defer rollout pass owner to handleSucceed (#2121)
* finish test fix demo finish test finish docs fix rollout template add more test add comment * impove test coverage and wrap error fix checkdiff add more time
This commit is contained in:
@@ -26,7 +26,9 @@ spec:
|
||||
rolloutStrategy: "IncreaseFirst"
|
||||
rolloutBatches: parameter.rolloutBatches
|
||||
targetSize: parameter.targetSize
|
||||
batchPartition: parameter.batchPartition
|
||||
if parameter["batchPartition"] != _|_ {
|
||||
batchPartition: parameter.batchPartition
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,5 +39,4 @@ spec:
|
||||
batchPartition?: int
|
||||
}
|
||||
rolloutBatch: replicas: int
|
||||
skipRevisionAffect: true
|
||||
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
# Rollout with OCM
|
||||
|
||||
In this tutorial, you will use rollout in runtime cluster with OCM.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Have a multi-cluster environment witch have installed OCM by following this [guid](../README.md). The name of managed cluster generally is `poc-01`.
|
||||
|
||||
- install vela-rollout chart in managed-cluster with Helm.
|
||||
```shell
|
||||
$ helm repo add kubevela https://charts.kubevela.net/core
|
||||
```
|
||||
```shell
|
||||
$ helm isntall vela-rollout --create-namespace -n vela-system kubevela/vela-rollout
|
||||
```
|
||||
|
||||
## Install workflowStepDefinition
|
||||
|
||||
Apply workflowStepDefinitions in control-plane cluster.
|
||||
|
||||
```shell
|
||||
$ kubectl apply -f dispatchRevDef.yaml
|
||||
```
|
||||
|
||||
```shell
|
||||
$ kubectl apply -f dispatchTraits.yaml
|
||||
```
|
||||
|
||||
## Deploy and rollout
|
||||
|
||||
1. Apply application in control-plane cluster.
|
||||
|
||||
```shell
|
||||
$ kubectl apply -f app-first-scale.yaml
|
||||
```
|
||||
|
||||
Wait a few minute, check rollout and workload status in managed cluster.
|
||||
```shell
|
||||
$ kubectl get rollout
|
||||
NAME TARGET UPGRADED READY BATCH-STATE ROLLING-STATE AGE
|
||||
nginx-server 2 2 2 batchReady rolloutSucceed 25h
|
||||
```
|
||||
```shell
|
||||
$ kubectl get deploy
|
||||
NAME READY UP-TO-DATE AVAILABLE AGE
|
||||
nginx-server-v1 2/2 2 2 25h
|
||||
```
|
||||
|
||||
2. Update application to v2.
|
||||
|
||||
```shell
|
||||
$ kubectl apply -f app-update-v2.yaml
|
||||
```
|
||||
|
||||
check rollout and workload status.
|
||||
```shell
|
||||
$ kubectl get rollout
|
||||
NAME TARGET UPGRADED READY BATCH-STATE ROLLING-STATE AGE
|
||||
nginx-server 2 2 2 batchReady rolloutSucceed 25h
|
||||
```
|
||||
```shell
|
||||
$ kubectl get deploy
|
||||
NAME READY UP-TO-DATE AVAILABLE AGE
|
||||
nginx-server-v2 2/2 2 2 25h
|
||||
```
|
||||
|
||||
3. Scale up.
|
||||
|
||||
```shell
|
||||
$ kubectl apply -f app-v2-scale.yaml
|
||||
```
|
||||
|
||||
check the status of rollout and workload.
|
||||
```shell
|
||||
$ kubectl get rollout
|
||||
NAME TARGET UPGRADED READY BATCH-STATE ROLLING-STATE AGE
|
||||
nginx-server 4 4 4 batchReady rolloutSucceed 25h
|
||||
```
|
||||
```shell
|
||||
$ kubectl get deploy
|
||||
NAME READY UP-TO-DATE AVAILABLE AGE
|
||||
nginx-server-v2 4/4 4 4 25h
|
||||
```
|
||||
|
||||
4. Roll back to v1.
|
||||
```shell
|
||||
$ kubectl apply -f app-revert.yaml
|
||||
```
|
||||
|
||||
check rollout and workload status.
|
||||
```shell
|
||||
$ kubectl get rollout
|
||||
NAME TARGET UPGRADED READY BATCH-STATE ROLLING-STATE AGE
|
||||
nginx-server 4 4 4 batchReady rolloutSucceed 25h
|
||||
```
|
||||
|
||||
```shell
|
||||
$ kubectl get deploy
|
||||
NAME READY UP-TO-DATE AVAILABLE AGE
|
||||
nginx-server-v1 4/4 4 4 25h
|
||||
```
|
||||
|
||||
5. Scale down.
|
||||
```shell
|
||||
$ kubectl apply -f app-scale-down-v1.yaml
|
||||
```
|
||||
|
||||
check rollout and workload status.
|
||||
```shell
|
||||
$ kubectl get rollout
|
||||
NAME TARGET UPGRADED READY BATCH-STATE ROLLING-STATE AGE
|
||||
nginx-server 2 2 2 batchReady rolloutSucceed 25h
|
||||
```
|
||||
|
||||
```shell
|
||||
$ kubectl get deploy
|
||||
NAME READY UP-TO-DATE AVAILABLE AGE
|
||||
nginx-server-v1 2/2 2 2 25h
|
||||
```
|
||||
@@ -0,0 +1,35 @@
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: workflow-rollout-demo
|
||||
namespace: default
|
||||
spec:
|
||||
components:
|
||||
- name: nginx-server
|
||||
externalRevision: nginx-server-v1
|
||||
type: webservice
|
||||
properties:
|
||||
image: nginx:1.20.0
|
||||
port: 80
|
||||
traits:
|
||||
- type: rollout
|
||||
properties:
|
||||
targetRevision: nginx-server-v1
|
||||
targetSize: 2
|
||||
rolloutBatches:
|
||||
- replicas: 1
|
||||
- replicas: 1
|
||||
|
||||
workflow:
|
||||
steps:
|
||||
- name: dispatch-comp-rev-v1
|
||||
type: dispatch-comp-rev
|
||||
properties:
|
||||
compRev: nginx-server-v1
|
||||
cluster: poc-01
|
||||
|
||||
- name: dispatchRollout
|
||||
type: dispatch-traits
|
||||
properties:
|
||||
component: nginx-server
|
||||
cluster: poc-01
|
||||
@@ -0,0 +1,41 @@
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: workflow-rollout-demo
|
||||
namespace: default
|
||||
spec:
|
||||
components:
|
||||
- name: nginx-server
|
||||
externalRevision: nginx-server-v2
|
||||
type: webservice
|
||||
properties:
|
||||
image: nginx:1.21
|
||||
port: 80
|
||||
traits:
|
||||
- type: rollout
|
||||
properties:
|
||||
targetRevision: nginx-server-v1
|
||||
targetSize: 4
|
||||
rolloutBatches:
|
||||
- replicas: 2
|
||||
- replicas: 2
|
||||
|
||||
workflow:
|
||||
steps:
|
||||
- name: dispatch-comp-rev-v1
|
||||
type: dispatch-comp-rev
|
||||
properties:
|
||||
compRev: nginx-server-v1
|
||||
cluster: poc-01
|
||||
|
||||
- name: dispatch-comp-rev-v2
|
||||
type: dispatch-comp-rev
|
||||
properties:
|
||||
compRev: nginx-server-v2
|
||||
cluster: poc-01
|
||||
|
||||
- name: dispatchRollout
|
||||
type: dispatch-traits
|
||||
properties:
|
||||
component: nginx-server
|
||||
cluster: poc-01
|
||||
@@ -0,0 +1,41 @@
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: workflow-rollout-demo
|
||||
namespace: default
|
||||
spec:
|
||||
components:
|
||||
- name: nginx-server
|
||||
externalRevision: nginx-server-v2
|
||||
type: webservice
|
||||
properties:
|
||||
image: nginx:1.21
|
||||
port: 80
|
||||
traits:
|
||||
- type: rollout
|
||||
properties:
|
||||
targetRevision: nginx-server-v1
|
||||
targetSize: 2
|
||||
rolloutBatches:
|
||||
- replicas: 1
|
||||
- replicas: 1
|
||||
|
||||
workflow:
|
||||
steps:
|
||||
- name: dispatch-comp-rev-v1
|
||||
type: dispatch-comp-rev
|
||||
properties:
|
||||
compRev: nginx-server-v1
|
||||
cluster: cluster2
|
||||
|
||||
- name: dispatch-comp-rev-v2
|
||||
type: dispatch-comp-rev
|
||||
properties:
|
||||
compRev: nginx-server-v2
|
||||
cluster: cluster2
|
||||
|
||||
- name: dispatchRollout
|
||||
type: dispatch-traits
|
||||
properties:
|
||||
component: nginx-server
|
||||
cluster: cluster2
|
||||
@@ -0,0 +1,41 @@
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: workflow-rollout-demo
|
||||
namespace: default
|
||||
spec:
|
||||
components:
|
||||
- name: nginx-server
|
||||
externalRevision: nginx-server-v2
|
||||
type: webservice
|
||||
properties:
|
||||
image: nginx:1.21
|
||||
port: 80
|
||||
traits:
|
||||
- type: rollout
|
||||
properties:
|
||||
targetRevision: nginx-server-v2
|
||||
targetSize: 2
|
||||
rolloutBatches:
|
||||
- replicas: 1
|
||||
- replicas: 1
|
||||
|
||||
workflow:
|
||||
steps:
|
||||
- name: dispatch-comp-rev-v1
|
||||
type: dispatch-comp-rev
|
||||
properties:
|
||||
compRev: nginx-server-v1
|
||||
cluster: poc-01
|
||||
|
||||
- name: dispatch-comp-rev-v2
|
||||
type: dispatch-comp-rev
|
||||
properties:
|
||||
compRev: nginx-server-v2
|
||||
cluster: poc-01
|
||||
|
||||
- name: dispatchRollout
|
||||
type: dispatch-traits
|
||||
properties:
|
||||
component: nginx-server
|
||||
cluster: poc-01
|
||||
@@ -0,0 +1,41 @@
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: workflow-rollout-demo
|
||||
namespace: default
|
||||
spec:
|
||||
components:
|
||||
- name: nginx-server
|
||||
externalRevision: nginx-server-v2
|
||||
type: webservice
|
||||
properties:
|
||||
image: nginx:1.21
|
||||
port: 80
|
||||
traits:
|
||||
- type: rollout
|
||||
properties:
|
||||
targetRevision: nginx-server-v2
|
||||
targetSize: 4
|
||||
rolloutBatches:
|
||||
- replicas: 1
|
||||
- replicas: 1
|
||||
|
||||
workflow:
|
||||
steps:
|
||||
- name: dispatch-comp-rev-v1
|
||||
type: dispatch-comp-rev
|
||||
properties:
|
||||
compRev: nginx-server-v1
|
||||
cluster: poc-01
|
||||
|
||||
- name: dispatch-comp-rev-v2
|
||||
type: dispatch-comp-rev
|
||||
properties:
|
||||
compRev: nginx-server-v2
|
||||
cluster: poc-01
|
||||
|
||||
- name: dispatchRollout
|
||||
type: dispatch-traits
|
||||
properties:
|
||||
component: nginx-server
|
||||
cluster: poc-01
|
||||
@@ -0,0 +1,60 @@
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: WorkflowStepDefinition
|
||||
metadata:
|
||||
name: dispatch-comp-rev
|
||||
namespace: vela-system
|
||||
spec:
|
||||
schematic:
|
||||
cue:
|
||||
template: |
|
||||
import ("vela/op")
|
||||
|
||||
componentRev: op.#Read & {
|
||||
value: {
|
||||
kind: "ControllerRevision"
|
||||
apiVersion: "apps/v1"
|
||||
metadata: {
|
||||
name: parameter.compRev
|
||||
namespace: context.namespace
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
apply: op.#Apply & {
|
||||
value: {
|
||||
apiVersion: "work.open-cluster-management.io/v1"
|
||||
kind: "ManifestWork"
|
||||
metadata: {
|
||||
namespace: parameter.cluster
|
||||
name: "comprevision-" + parameter.compRev
|
||||
}
|
||||
spec: {
|
||||
workload: {
|
||||
manifests: [{
|
||||
kind: "ControllerRevision"
|
||||
apiVersion: "apps/v1"
|
||||
metadata: {
|
||||
name: parameter.compRev
|
||||
namespace: context.namespace
|
||||
}
|
||||
data: {
|
||||
apiVersion: "core.oam.dev/v1alpha2"
|
||||
kind: "Component"
|
||||
metadata:
|
||||
name: context.name
|
||||
namespace: context.namespace
|
||||
spec:
|
||||
workload: {
|
||||
componentRev.value.data.spec.workload
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parameter: {
|
||||
compRev: string
|
||||
cluster: string
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
apiVersion: core.oam.dev/v1beta1
|
||||
kind: WorkflowStepDefinition
|
||||
metadata:
|
||||
name: dispatch-traits
|
||||
namespace: vela-system
|
||||
spec:
|
||||
schematic:
|
||||
cue:
|
||||
template: |
|
||||
import ("vela/op")
|
||||
|
||||
comp: op.#Load & {
|
||||
component: parameter.component
|
||||
}
|
||||
|
||||
apply: op.#Apply & {
|
||||
value: {
|
||||
apiVersion: "work.open-cluster-management.io/v1"
|
||||
kind: "ManifestWork"
|
||||
metadata: {
|
||||
namespace: parameter.cluster
|
||||
name: parameter.component + "-traits"
|
||||
}
|
||||
spec: {
|
||||
workload: manifests : comp.value.auxiliaries
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
parameter: {
|
||||
component: string
|
||||
cluster: string
|
||||
}
|
||||
@@ -22,6 +22,8 @@ import (
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
v1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
@@ -123,10 +125,6 @@ func (h *handler) applyTargetWorkload(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := h.recordWorkloadInResourceTracker(ctx); err != nil {
|
||||
return errors.Wrap(err, "fail to add resourceTracker as owner for workload")
|
||||
}
|
||||
|
||||
klog.InfoS("template rollout target workload", "namespace", h.rollout.Namespace,
|
||||
"rollout", h.rollout.Name, "targetWorkload", h.targetWorkload.GetName())
|
||||
return nil
|
||||
@@ -134,7 +132,22 @@ func (h *handler) applyTargetWorkload(ctx context.Context) error {
|
||||
|
||||
// handleFinalizeSucceed gc source workload if target and source are not same one
|
||||
func (h *handler) handleFinalizeSucceed(ctx context.Context) error {
|
||||
// this is a scale operation
|
||||
// patch target workload to pass rollout owner to workload
|
||||
targetWl := h.targetWorkload.DeepCopy()
|
||||
if err := h.Get(ctx, types.NamespacedName{Namespace: targetWl.GetNamespace(), Name: targetWl.GetName()}, targetWl); err != nil {
|
||||
return errors.Wrap(err, "fail to get targetWorkload")
|
||||
}
|
||||
wlPatch := client.MergeFrom(targetWl.DeepCopy())
|
||||
h.passOwnerToTargetWorkload(targetWl)
|
||||
if err := h.Patch(ctx, targetWl, wlPatch); err != nil {
|
||||
return errors.Wrap(err, "fail to patch workload to pass rollout owners to workload")
|
||||
}
|
||||
|
||||
// recode targetWorkload
|
||||
if err := h.recordWorkloadInResourceTracker(ctx); err != nil {
|
||||
return errors.Wrap(err, "fail to add resourceTracker as owner for workload")
|
||||
}
|
||||
|
||||
if h.sourceWorkload != nil && (h.sourceWorkload.GetName() != h.targetWorkload.GetName()) {
|
||||
if err := h.Delete(ctx, h.sourceWorkload); err != nil {
|
||||
return err
|
||||
@@ -183,9 +196,6 @@ func (h *handler) setWorkloadBaseInfo() {
|
||||
util.AddLabels(h.targetWorkload, map[string]string{oam.LabelAppComponentRevision: h.targetRevName})
|
||||
util.AddAnnotations(h.targetWorkload, map[string]string{oam.AnnotationSkipGC: "true"})
|
||||
|
||||
// pass rollout's ownerReference to workload
|
||||
h.passOwnerToTargetWorkload()
|
||||
|
||||
if h.sourceWorkload != nil {
|
||||
h.sourceWorkload.SetName(h.compName)
|
||||
util.AddLabels(h.sourceWorkload, map[string]string{oam.LabelAppComponentRevision: h.sourceRevName})
|
||||
@@ -270,11 +280,11 @@ func (h *handler) recordWorkloadInResourceTracker(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *handler) passOwnerToTargetWorkload() {
|
||||
func (h *handler) passOwnerToTargetWorkload(wl *unstructured.Unstructured) {
|
||||
var owners []metav1.OwnerReference
|
||||
for _, reference := range h.rollout.OwnerReferences {
|
||||
reference.Controller = pointer.Bool(false)
|
||||
owners = append(owners, reference)
|
||||
}
|
||||
h.targetWorkload.SetOwnerReferences(owners)
|
||||
wl.SetOwnerReferences(owners)
|
||||
}
|
||||
|
||||
@@ -292,6 +292,75 @@ var _ = Describe("Test rollout related handler func", func() {
|
||||
Expect(checkRt.Status.TrackedResources[0].Name).Should(BeEquivalentTo("test-workload"))
|
||||
Expect(checkRt.Status.TrackedResources[0].UID).Should(BeEquivalentTo("test-uid"))
|
||||
})
|
||||
|
||||
It("Test handle succeed func", func() {
|
||||
ctx := context.Background()
|
||||
namespaceName := "default"
|
||||
rtName := "resourcetracker-v1-test-default"
|
||||
rt := v1beta1.ResourceTracker{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: rtName,
|
||||
},
|
||||
}
|
||||
Expect(k8sClient.Create(ctx, &rt)).Should(BeNil())
|
||||
rollout := v1alpha1.Rollout{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
OwnerReferences: []metav1.OwnerReference{
|
||||
*metav1.NewControllerRef(&rt, v1beta1.ResourceTrackerKindVersionKind),
|
||||
},
|
||||
},
|
||||
}
|
||||
deploy := &appsv1.Deployment{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "Deployment",
|
||||
APIVersion: "apps/v1",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Labels: map[string]string{
|
||||
"workload.oam.dev/type": "worker",
|
||||
},
|
||||
Name: "test-workload",
|
||||
Namespace: namespaceName,
|
||||
},
|
||||
Spec: appsv1.DeploymentSpec{
|
||||
Selector: &metav1.LabelSelector{MatchLabels: map[string]string{
|
||||
"workload.oam.dev/type": "worker",
|
||||
}},
|
||||
Template: v1.PodTemplateSpec{
|
||||
ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{
|
||||
"workload.oam.dev/type": "worker",
|
||||
}},
|
||||
Spec: v1.PodSpec{Containers: []v1.Container{{
|
||||
Image: "busybox",
|
||||
Name: "comp-name",
|
||||
Command: []string{"sleep", "1000"},
|
||||
},
|
||||
}}},
|
||||
},
|
||||
}
|
||||
u, err := util.Object2Unstructured(deploy)
|
||||
Expect(err).Should(BeNil())
|
||||
Expect(k8sClient.Create(ctx, u)).Should(BeNil())
|
||||
h := &handler{
|
||||
reconciler: &reconciler{
|
||||
Client: k8sClient,
|
||||
record: event.NewNopRecorder(),
|
||||
},
|
||||
rollout: &rollout,
|
||||
targetWorkload: u,
|
||||
}
|
||||
Expect(h.handleFinalizeSucceed(ctx)).Should(BeNil())
|
||||
checkDeploy := new(appsv1.Deployment)
|
||||
Expect(k8sClient.Get(ctx, types.NamespacedName{Namespace: u.GetNamespace(), Name: u.GetName()}, checkDeploy)).Should(BeNil())
|
||||
Expect(len(checkDeploy.OwnerReferences)).Should(BeEquivalentTo(1))
|
||||
Expect(checkDeploy.OwnerReferences[0].Kind).Should(BeEquivalentTo(v1beta1.ResourceTrackerKind))
|
||||
Expect(checkDeploy.OwnerReferences[0].Name).Should(BeEquivalentTo(rtName))
|
||||
checkRt := v1beta1.ResourceTracker{}
|
||||
Expect(k8sClient.Get(ctx, types.NamespacedName{Name: rtName}, &checkRt)).Should(BeNil())
|
||||
Expect(len(checkRt.Status.TrackedResources)).Should(BeEquivalentTo(1))
|
||||
Expect(checkRt.Status.TrackedResources[0].Name).Should(BeEquivalentTo("test-workload"))
|
||||
Expect(checkRt.Status.TrackedResources[0].UID).Should(BeEquivalentTo(u.GetUID()))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -17,8 +17,14 @@ limitations under the License.
|
||||
package rollout
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/crossplane/crossplane-runtime/pkg/test"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
"gotest.tools/assert"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
@@ -324,10 +330,72 @@ func TestPassOwnerReference(t *testing.T) {
|
||||
u := &unstructured.Unstructured{}
|
||||
u.SetName("test-workload")
|
||||
h := &handler{
|
||||
rollout: &rollout,
|
||||
targetWorkload: u,
|
||||
rollout: &rollout,
|
||||
}
|
||||
h.passOwnerToTargetWorkload(u)
|
||||
assert.Assert(t, len(u.GetOwnerReferences()) == 1)
|
||||
assert.Assert(t, *u.GetOwnerReferences()[0].Controller == false)
|
||||
}
|
||||
|
||||
func TestHandleSucceedError(t *testing.T) {
|
||||
getErr := fmt.Errorf("got error")
|
||||
patchErr := fmt.Errorf("patch error")
|
||||
object := &unstructured.Unstructured{}
|
||||
object.SetName("name")
|
||||
object.SetNamespace("namespace")
|
||||
getClient := test.NewMockGetFn(getErr)
|
||||
rollout := oamstandard.Rollout{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
OwnerReferences: []metav1.OwnerReference{
|
||||
{
|
||||
UID: "test-UID",
|
||||
Kind: v1beta1.ResourceTrackerKind,
|
||||
},
|
||||
},
|
||||
}}
|
||||
ctx := context.Background()
|
||||
patchClient := test.MockClient{
|
||||
MockGet: func(_ context.Context, _ client.ObjectKey, obj client.Object) error {
|
||||
if obj != nil {
|
||||
obj = object
|
||||
}
|
||||
return nil
|
||||
},
|
||||
MockPatch: test.NewMockPatchFn(patchErr),
|
||||
}
|
||||
testCase := map[string]struct {
|
||||
h handler
|
||||
err error
|
||||
}{
|
||||
"Test get error": {
|
||||
h: handler{
|
||||
targetWorkload: object,
|
||||
reconciler: &reconciler{
|
||||
Client: &test.MockClient{
|
||||
MockGet: getClient,
|
||||
},
|
||||
},
|
||||
},
|
||||
err: getErr,
|
||||
},
|
||||
"Test patch error": {
|
||||
h: handler{
|
||||
targetWorkload: object,
|
||||
reconciler: &reconciler{
|
||||
Client: &patchClient,
|
||||
},
|
||||
rollout: &rollout,
|
||||
},
|
||||
err: patchErr,
|
||||
},
|
||||
}
|
||||
|
||||
for testName, oneCase := range testCase {
|
||||
t.Run(testName, func(t *testing.T) {
|
||||
got := oneCase.h.handleFinalizeSucceed(ctx)
|
||||
if got == nil || !strings.Contains(oneCase.err.Error(), oneCase.err.Error()) {
|
||||
t.Errorf("handleSucceed () got %v, want %v", got, oneCase.err)
|
||||
}
|
||||
})
|
||||
}
|
||||
h.passOwnerToTargetWorkload()
|
||||
assert.Assert(t, len(h.targetWorkload.GetOwnerReferences()) == 1)
|
||||
assert.Assert(t, *h.targetWorkload.GetOwnerReferences()[0].Controller == false)
|
||||
}
|
||||
|
||||
@@ -126,6 +126,7 @@ var _ = Describe("rollout related e2e-test,rollout trait test", func() {
|
||||
if len(targerDeploy.OwnerReferences) != 1 {
|
||||
return fmt.Errorf("workload ownerReference missMatch")
|
||||
}
|
||||
// guarantee rollout's owners and workload's owners are same
|
||||
if targerDeploy.OwnerReferences[0].Kind != rollout.OwnerReferences[0].Kind ||
|
||||
targerDeploy.OwnerReferences[0].Name != rollout.OwnerReferences[0].Name {
|
||||
return fmt.Errorf("workload ownerReference missMatch")
|
||||
@@ -236,6 +237,57 @@ var _ = Describe("rollout related e2e-test,rollout trait test", func() {
|
||||
return nil
|
||||
}, 30*time.Second, 300*time.Millisecond).Should(BeNil())
|
||||
verifySuccess("express-server-v4")
|
||||
By("update application batch upgrade to v5")
|
||||
Eventually(func() error {
|
||||
if err = k8sClient.Get(ctx, appKey, checkApp); err != nil {
|
||||
return err
|
||||
}
|
||||
checkApp.Spec.Components[0].Properties.Raw = []byte(`{"image":"stefanprodan/podinfo:4.0.3","cpu":"0.5"}`)
|
||||
checkApp.Spec.Components[0].Traits[0].Properties.Raw =
|
||||
[]byte(`{"firstBatchReplicas":2,"secondBatchReplicas":2,"targetSize":4,"batchPartition":0}`)
|
||||
if err = k8sClient.Update(ctx, checkApp); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}, 30*time.Second, 300*time.Millisecond).Should(BeNil())
|
||||
// check rollout paused in partition 0
|
||||
time.Sleep(5 * time.Second)
|
||||
Eventually(func() error {
|
||||
rolloutKey := types.NamespacedName{Namespace: namespaceName, Name: componentName}
|
||||
if err := k8sClient.Get(ctx, rolloutKey, &rollout); err != nil {
|
||||
return err
|
||||
}
|
||||
if rollout.Spec.TargetRevisionName != "express-server-v5" {
|
||||
return fmt.Errorf("rollout have not point to right targetRevision")
|
||||
}
|
||||
if rollout.Status.RollingState != v1alpha1.RollingInBatchesState {
|
||||
return fmt.Errorf("error rollout status state %s", rollout.Status.RollingState)
|
||||
}
|
||||
if rollout.Status.CurrentBatch != 0 {
|
||||
return fmt.Errorf("current batchPartition missmatch accutally %d", rollout.Status.CurrentBatch)
|
||||
}
|
||||
deployKey := types.NamespacedName{Namespace: namespaceName, Name: compRevName}
|
||||
if err := k8sClient.Get(ctx, deployKey, &targerDeploy); err != nil {
|
||||
return err
|
||||
}
|
||||
if *targerDeploy.Spec.Replicas != 2 {
|
||||
return fmt.Errorf("targetDeploy replicas missMatch %d", *targerDeploy.Spec.Replicas)
|
||||
}
|
||||
return nil
|
||||
}, 60*time.Second, 300*time.Millisecond).Should(BeNil())
|
||||
By("continue rollout upgrade legacy batches")
|
||||
Eventually(func() error {
|
||||
if err = k8sClient.Get(ctx, appKey, checkApp); err != nil {
|
||||
return err
|
||||
}
|
||||
checkApp.Spec.Components[0].Traits[0].Properties.Raw =
|
||||
[]byte(`{"firstBatchReplicas":2,"secondBatchReplicas":2,"targetSize":4,"batchPartition":1}`)
|
||||
if err = k8sClient.Update(ctx, checkApp); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}, 30*time.Second, 300*time.Millisecond).Should(BeNil())
|
||||
verifySuccess("express-server-v5")
|
||||
By("delete the application, check workload have been removed")
|
||||
Expect(k8sClient.Delete(ctx, checkApp)).Should(BeNil())
|
||||
listOptions := []client.ListOption{
|
||||
@@ -312,7 +364,6 @@ metadata:
|
||||
name: rollout
|
||||
spec:
|
||||
manageWorkload: true
|
||||
skipRevisionAffect: true
|
||||
schematic:
|
||||
cue:
|
||||
template: |
|
||||
@@ -332,7 +383,10 @@ spec:
|
||||
{ replicas: parameter.firstBatchReplicas},
|
||||
{ replicas: parameter.secondBatchReplicas}]
|
||||
targetSize: parameter.targetSize
|
||||
}
|
||||
if parameter["batchPartition"] != _|_ {
|
||||
batchPartition: parameter.batchPartition
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -341,5 +395,6 @@ spec:
|
||||
targetSize: *2|int
|
||||
firstBatchReplicas: *1|int
|
||||
secondBatchReplicas: *1|int
|
||||
batchPartition?: int
|
||||
}`
|
||||
)
|
||||
|
||||
@@ -4,8 +4,7 @@ rollout: {
|
||||
labels: {}
|
||||
description: "rollout the component"
|
||||
attributes: {
|
||||
manageWorkload: true
|
||||
skipRevisionAffect: true
|
||||
manageWorkload: true
|
||||
}
|
||||
}
|
||||
template: {
|
||||
@@ -23,7 +22,9 @@ template: {
|
||||
rolloutStrategy: "IncreaseFirst"
|
||||
rolloutBatches: parameter.rolloutBatches
|
||||
targetSize: parameter.targetSize
|
||||
batchPartition: parameter.batchPartition
|
||||
if parameter["batchPartition"] != _|_ {
|
||||
batchPartition: parameter.batchPartition
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user