fix appRollout CRD version (#1303)

* fix appRollout CRD version

* make rollout e2e more robust
This commit is contained in:
Ryan Zhang
2021-03-25 17:23:10 -07:00
committed by GitHub
parent 94b7cbff21
commit 0926469541
26 changed files with 163 additions and 156 deletions

View File

@@ -40,18 +40,18 @@ webhooks:
service:
name: {{ template "kubevela.name" . }}-webhook
namespace: {{ .Release.Namespace }}
path: /mutating-core-oam-dev-v1alpha2-approllout
path: /mutating-core-oam-dev-v1beta1-approllout
{{- if .Values.admissionWebhooks.patch.enabled }}
failurePolicy: Ignore
{{- else }}
failurePolicy: Fail
{{- end }}
name: mutating.core.oam.dev.v1alpha2.approllouts
name: mutating.core.oam.dev.v1beta1.approllouts
rules:
- apiGroups:
- core.oam.dev
apiVersions:
- v1alpha2
- v1beta1
operations:
- CREATE
- UPDATE

View File

@@ -40,18 +40,18 @@ webhooks:
service:
name: {{ template "kubevela.name" . }}-webhook
namespace: {{ .Release.Namespace }}
path: /validating-core-oam-dev-v1alpha2-approllout
path: /validating-core-oam-dev-v1beta1-approllout
{{- if .Values.admissionWebhooks.patch.enabled }}
failurePolicy: Ignore
{{- else }}
failurePolicy: {{ .Values.admissionWebhooks.failurePolicy }}
{{- end }}
name: validating.core.oam.dev.v1alpha2.approllouts
name: validating.core.oam.dev.v1beta1.approllouts
rules:
- apiGroups:
- core.oam.dev
apiVersions:
- v1alpha2
- v1beta1
operations:
- CREATE
- UPDATE

View File

@@ -19,7 +19,7 @@ kubectl apply -f docs/examples/cloneset-rollout/clonesetDefinition.yaml
2. Apply an application for rolling out
```shell
kubectl apply -f docs/examples/cloneset-rollout/app-source.yaml
kubectl apply -f docs/examples/cloneset-rollout/app-rollout-source.yaml
kubectl apply -f docs/examples/cloneset-rollout/appRollout-scale.yaml
```
Check the status of the ApplicationRollout and wait for the rollout to complete.
@@ -30,7 +30,7 @@ kubectl apply -f docs/examples/cloneset-rollout/app-target.yaml
4. Apply the application rollout that stops at the second batch and mrk the application as normal
```shell
kubectl apply -f docs/examples/cloneset-rollout/app-rollout-pause.yaml
kubectl apply -f docs/examples/cloneset-rollout/appRollout-pause.yaml
```
Check the status of the ApplicationRollout and see the step by step rolling out. This rollout
@@ -38,7 +38,7 @@ will pause after the second batch.
5. Apply the application rollout that completes the rollout
```shell
kubectl apply -f docs/examples/cloneset-rollout/app-rollout-finish.yaml
kubectl apply -f docs/examples/cloneset-rollout/appRollout-finish.yaml
```
Check the status of the ApplicationRollout and see the rollout completes, and the

View File

@@ -15,4 +15,5 @@ spec:
- stress-cpu=1
image: stefanprodan/podinfo:4.0.6
port: 8080
updateStrategyType: InPlaceIfPossible
updateStrategyType: InPlaceIfPossible
replicas: 5

View File

@@ -1,15 +0,0 @@
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: test-rolling
spec:
components:
- name: metrics-provider
type: clonesetservice
properties:
cmd:
- ./podinfo
- stress-cpu=1
image: stefanprodan/podinfo:5.0.2
port: 8080
updateStrategyType: InPlaceIfPossible

View File

@@ -15,4 +15,5 @@ spec:
- stress-cpu=1
image: stefanprodan/podinfo:5.0.2
port: 8080
updateStrategyType: InPlaceIfPossible
updateStrategyType: InPlaceIfPossible
replicas: 5

View File

@@ -1,7 +1,7 @@
apiVersion: core.oam.dev/v1beta1
kind: AppRollout
metadata:
name: rolling-test
name: rolling-example
spec:
# application (revision) reference
sourceAppRevisionName: test-rolling-v1

View File

@@ -1,7 +1,7 @@
apiVersion: core.oam.dev/v1beta1
kind: AppRollout
metadata:
name: rolling-test
name: rolling-example
spec:
# application (revision) reference
sourceAppRevisionName: test-rolling-v1
@@ -14,4 +14,4 @@ spec:
- replicas: 10%
- replicas: 2
- replicas: 2
batchPartition: 1
batchPartition: 1

View File

@@ -1,7 +1,7 @@
apiVersion: core.oam.dev/v1beta1
kind: AppRollout
metadata:
name: rolling-test
name: rolling-example
spec:
# application (revision) reference
sourceAppRevisionName: test-rolling-v2

View File

@@ -1,7 +1,7 @@
apiVersion: core.oam.dev/v1alpha2
apiVersion: core.oam.dev/v1beta1
kind: AppRollout
metadata:
name: rolling-test
name: rolling-example
spec:
# application (revision) reference
targetAppRevisionName: test-rolling-v1

View File

@@ -1,14 +1,17 @@
# Code generated by KubeVela templates. DO NOT EDIT.
apiVersion: core.oam.dev/v1alpha2
kind: WorkloadDefinition
apiVersion: core.oam.dev/v1beta1
kind: ComponentDefinition
metadata:
name: clonesetservice
namespace: vela-system
annotations:
definition.oam.dev/description: "Describes long-running, scalable, containerized services that have a stable network endpoint to receive external network traffic from customers.
If workload type is skipped for any service defined in Appfile, it will be defaulted to `webservice` type."
spec:
definitionRef:
name: clonesets.apps.kruise.io
workload:
definition:
apiVersion: apps.kruise.io/v1alpha1
kind: CloneSet
schematic:
cue:
template: |
@@ -19,7 +22,9 @@ spec:
"app.oam.dev/component": context.name
}
spec: {
replicas: parameter.replicas
if parameter["replicas"] != _|_ {
replicas: parameter.replicas
}
selector: matchLabels: {
"app.oam.dev/component": context.name
}
@@ -101,5 +106,5 @@ spec:
// +usage=Cloneset updateStrategy, candidates are `ReCreate`/`InPlaceIfPossible`/`InPlaceOnly`
updateStrategyType?: string
// +usage=Number of pods in the cloneset
replicas: *5 | int
replicas?: int
}

View File

@@ -64,8 +64,8 @@ func (h *appHandler) GenerateRevision(ctx context.Context, ac *v1alpha2.Applicat
appRev.SetAnnotations(h.app.GetAnnotations())
appRev.SetLabels(h.app.GetLabels())
appRev.SetOwnerReferences([]metav1.OwnerReference{{
APIVersion: v1alpha2.SchemeGroupVersion.String(),
Kind: v1alpha2.ApplicationKind,
APIVersion: v1beta1.SchemeGroupVersion.String(),
Kind: v1beta1.ApplicationKind,
Name: h.app.Name,
UID: h.app.UID,
Controller: pointer.BoolPtr(false),

View File

@@ -12,7 +12,6 @@ import (
"k8s.io/klog/v2"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/oam-dev/kubevela/pkg/controller/common"
"github.com/oam-dev/kubevela/pkg/oam"
)
@@ -72,10 +71,10 @@ type APIApplicator struct {
func loggingApply(msg string, desired runtime.Object) {
d, ok := desired.(metav1.Object)
if !ok {
klog.V(common.LogDebug).InfoS(msg, "resource", desired.GetObjectKind().GroupVersionKind().String())
klog.InfoS(msg, "resource", desired.GetObjectKind().GroupVersionKind().String())
return
}
klog.V(common.LogDebug).InfoS(msg, "name", d.GetName(), "resource", desired.GetObjectKind().GroupVersionKind().String())
klog.InfoS(msg, "name", d.GetName(), "resource", desired.GetObjectKind().GroupVersionKind().String())
}
// Apply applies new state to an object or create it if not exist

View File

@@ -1,10 +1,12 @@
package rollout
import (
"fmt"
"net/http"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/klog/v2"
"github.com/oam-dev/kubevela/apis/standard.oam.dev/v1alpha1"
)
@@ -27,6 +29,10 @@ func DefaultRolloutPlan(rollout *v1alpha1.RolloutPlan) {
total--
}
}
for i, batch := range rollout.RolloutBatches {
klog.Info(fmt.Sprintf("mutation webhook assigns rollout plan replica %d to batch `%d`",
batch.Replicas.IntValue(), i))
}
}
}

View File

@@ -13,7 +13,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/webhook"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
"github.com/oam-dev/kubevela/pkg/controller/common"
util "github.com/oam-dev/kubevela/pkg/utils"
"github.com/oam-dev/kubevela/pkg/webhook/common/rollout"
@@ -31,7 +31,7 @@ var _ admission.Handler = &MutatingHandler{}
// Handle handles admission requests.
func (h *MutatingHandler) Handle(ctx context.Context, req admission.Request) admission.Response {
obj := &v1alpha2.AppRollout{}
obj := &v1beta1.AppRollout{}
err := h.Decoder.Decode(req, obj)
if err != nil {
@@ -52,8 +52,8 @@ func (h *MutatingHandler) Handle(ctx context.Context, req admission.Request) adm
}
// DefaultAppRollout will set the default value for the AppRollout®
func DefaultAppRollout(obj *v1alpha2.AppRollout) {
klog.InfoS("default", "name", obj.Name)
func DefaultAppRollout(obj *v1beta1.AppRollout) {
klog.InfoS("create default for approllout", "name", obj.Name)
if obj.Spec.RevertOnDelete == nil {
klog.V(common.LogDebug).Info("default RevertOnDelete as false")
obj.Spec.RevertOnDelete = pointer.BoolPtr(false)
@@ -82,6 +82,6 @@ func (h *MutatingHandler) InjectDecoder(d *admission.Decoder) error {
// RegisterMutatingHandler will register component mutation handler to the webhook
func RegisterMutatingHandler(mgr manager.Manager) {
server := mgr.GetWebhookServer()
server.Register("/mutating-core-oam-dev-v1alpha2-approllout",
server.Register("/mutating-core-oam-dev-v1beta1-approllout",
&webhook.Admission{Handler: &MutatingHandler{}})
}

View File

@@ -12,7 +12,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/webhook"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
)
// ValidatingHandler handles AppRollout
@@ -27,7 +27,7 @@ var _ admission.Handler = &ValidatingHandler{}
// Handle handles admission requests.
func (h *ValidatingHandler) Handle(ctx context.Context, req admission.Request) admission.Response {
obj := &v1alpha2.AppRollout{}
obj := &v1beta1.AppRollout{}
err := h.Decoder.Decode(req, obj)
if err != nil {
@@ -42,7 +42,7 @@ func (h *ValidatingHandler) Handle(ctx context.Context, req admission.Request) a
return admission.Errored(http.StatusUnprocessableEntity, allErrs.ToAggregate())
}
case admissionv1beta1.Update:
oldObj := &v1alpha2.AppRollout{}
oldObj := &v1beta1.AppRollout{}
if err := h.Decoder.DecodeRaw(req.AdmissionRequest.OldObject, oldObj); err != nil {
return admission.Errored(http.StatusBadRequest, err)
}
@@ -76,6 +76,6 @@ func (h *ValidatingHandler) InjectDecoder(d *admission.Decoder) error {
// RegisterValidatingHandler will register application configuration validation to webhook
func RegisterValidatingHandler(mgr manager.Manager) {
server := mgr.GetWebhookServer()
server.Register("/validating-core-oam-dev-v1alpha2-approllout",
server.Register("/validating-core-oam-dev-v1beta1-approllout",
&webhook.Admission{Handler: &ValidatingHandler{}})
}

View File

@@ -12,13 +12,14 @@ import (
"k8s.io/kubectl/pkg/util/slice"
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
"github.com/oam-dev/kubevela/apis/standard.oam.dev/v1alpha1"
oamutil "github.com/oam-dev/kubevela/pkg/oam/util"
"github.com/oam-dev/kubevela/pkg/webhook/common/rollout"
)
// ValidateCreate validates the AppRollout on creation
func (h *ValidatingHandler) ValidateCreate(appRollout *v1alpha2.AppRollout) field.ErrorList {
func (h *ValidatingHandler) ValidateCreate(appRollout *v1beta1.AppRollout) field.ErrorList {
klog.InfoS("validate create", "name", appRollout.Name)
allErrs := apimachineryvalidation.ValidateObjectMeta(&appRollout.ObjectMeta, true,
apimachineryvalidation.NameIsDNSSubdomain, field.NewPath("metadata"))
@@ -32,8 +33,8 @@ func (h *ValidatingHandler) ValidateCreate(appRollout *v1alpha2.AppRollout) fiel
return allErrs
}
var targetAppRevision v1alpha2.ApplicationRevision
sourceAppRevision := &v1alpha2.ApplicationRevision{}
var targetAppRevision v1beta1.ApplicationRevision
sourceAppRevision := &v1beta1.ApplicationRevision{}
targetAppName := appRollout.Spec.TargetAppRevisionName
if err := h.Get(context.Background(), ktypes.NamespacedName{Namespace: appRollout.Namespace, Name: targetAppName},
&targetAppRevision); err != nil {
@@ -123,7 +124,7 @@ func validateComponent(componentList []string, targetApp, sourceApp *v1alpha2.Ap
}
// ValidateUpdate validates the AppRollout on update
func (h *ValidatingHandler) ValidateUpdate(new, old *v1alpha2.AppRollout) field.ErrorList {
func (h *ValidatingHandler) ValidateUpdate(new, old *v1beta1.AppRollout) field.ErrorList {
klog.InfoS("validate update", "name", new.Name)
errList := h.ValidateCreate(new)
fldPath := field.NewPath("spec").Child("rolloutPlan")

View File

@@ -26,21 +26,21 @@ import (
"github.com/oam-dev/kubevela/pkg/utils/common"
)
var _ = Describe("Cloneset based rollout tests", func() {
var _ = FDescribe("Cloneset based rollout tests", func() {
ctx := context.Background()
var namespace string
var namespaceName, appRolloutName string
var ns corev1.Namespace
var app v1beta1.Application
var kc kruise.CloneSet
var appRollout v1beta1.AppRollout
createNamespace := func(namespace string) {
createNamespace := func() {
ns = corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: namespace,
Name: namespaceName,
},
}
// delete the namespace with all its resources
// delete the namespaceName with all its resources
Eventually(
func() error {
return k8sClient.Delete(ctx, &ns, client.PropagationPolicy(metav1.DeletePropagationForeground))
@@ -48,7 +48,7 @@ var _ = Describe("Cloneset based rollout tests", func() {
time.Second*120, time.Millisecond*500).Should(SatisfyAny(BeNil(), &util.NotFoundMatcher{}))
By("make sure all the resources are removed")
objectKey := client.ObjectKey{
Name: namespace,
Name: namespaceName,
}
res := &corev1.Namespace{}
Eventually(
@@ -75,17 +75,17 @@ var _ = Describe("Cloneset based rollout tests", func() {
time.Second*3, time.Millisecond*300).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{}))
}
applySourceApp := func() {
applySourceApp := func(source string) {
By("Apply an application")
var newApp v1beta1.Application
Expect(common.ReadYamlToObject("testdata/rollout/cloneset/app-source.yaml", &newApp)).Should(BeNil())
newApp.Namespace = namespace
Expect(common.ReadYamlToObject("testdata/rollout/cloneset/"+source, &newApp)).Should(BeNil())
newApp.Namespace = namespaceName
Expect(k8sClient.Create(ctx, &newApp)).Should(Succeed())
By("Get Application latest status")
Eventually(
func() *oamcomm.Revision {
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespace, Name: newApp.Name}, &app)
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: newApp.Name}, &app)
if app.Status.LatestRevision != nil {
return app.Status.LatestRevision
}
@@ -94,14 +94,14 @@ var _ = Describe("Cloneset based rollout tests", func() {
time.Second*30, time.Millisecond*500).ShouldNot(BeNil())
}
applyTargetApp := func() {
updateApp := func(target string) {
By("Update the application to target spec during rolling")
var targetApp v1beta1.Application
Expect(common.ReadYamlToObject("testdata/rollout/cloneset/app-target.yaml", &targetApp)).Should(BeNil())
Expect(common.ReadYamlToObject("testdata/rollout/cloneset/"+target, &targetApp)).Should(BeNil())
Eventually(
func() error {
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespace, Name: app.Name}, &app)
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: app.Name}, &app)
app.Spec = targetApp.Spec
return k8sClient.Update(ctx, &app)
}, time.Second*5, time.Millisecond*500).Should(Succeed())
@@ -120,7 +120,7 @@ var _ = Describe("Cloneset based rollout tests", func() {
clonesetName := appRollout.Spec.ComponentList[0]
Eventually(
func() string {
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespace, Name: clonesetName}, &kc)
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: clonesetName}, &kc)
clonesetOwner := metav1.GetControllerOf(&kc)
if clonesetOwner == nil {
return ""
@@ -135,10 +135,11 @@ var _ = Describe("Cloneset based rollout tests", func() {
By("Wait for the rollout phase change to succeed")
Eventually(
func() oamstd.RollingState {
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespace, Name: appRollout.Name}, &appRollout)
appRollout = v1beta1.AppRollout{}
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: appRolloutName}, &appRollout)
return appRollout.Status.RollingState
},
time.Second*300, time.Second).Should(Equal(oamstd.RolloutSucceedState))
time.Second*120, time.Second).Should(Equal(oamstd.RolloutSucceedState))
Expect(appRollout.Status.UpgradedReadyReplicas).Should(BeEquivalentTo(appRollout.Status.RolloutTargetTotalSize))
Expect(appRollout.Status.UpgradedReplicas).Should(BeEquivalentTo(appRollout.Status.RolloutTargetTotalSize))
@@ -147,7 +148,7 @@ var _ = Describe("Cloneset based rollout tests", func() {
Eventually(
func() types.RollingStatus {
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespace, Name: targetAppName}, &appConfig)
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: targetAppName}, &appConfig)
return appConfig.Status.RollingStatus
},
time.Second*60, time.Second).Should(BeEquivalentTo(types.RollingCompleted))
@@ -157,7 +158,7 @@ var _ = Describe("Cloneset based rollout tests", func() {
clonesetName := appRollout.Spec.ComponentList[0]
Eventually(
func() string {
err := k8sClient.Get(ctx, client.ObjectKey{Namespace: namespace, Name: clonesetName}, &kc)
err := k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: clonesetName}, &kc)
if err != nil {
return ""
}
@@ -178,7 +179,7 @@ var _ = Describe("Cloneset based rollout tests", func() {
By("Verify AppConfig is inactive")
Eventually(
func() types.RollingStatus {
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespace, Name: appConfigName}, &appConfig)
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: appConfigName}, &appConfig)
return appConfig.Status.RollingStatus
},
time.Second*30, time.Millisecond*500).Should(BeEquivalentTo(types.InactiveAfterRollingCompleted))
@@ -186,27 +187,18 @@ var _ = Describe("Cloneset based rollout tests", func() {
applyTwoAppVersion := func() {
CreateClonesetDef()
applySourceApp()
applyTargetApp()
applySourceApp("app-source.yaml")
updateApp("app-target.yaml")
}
revertBackToSource := func() {
By("Revert the application back to source")
var sourceApp v1beta1.Application
Expect(common.ReadYamlToObject("testdata/rollout/cloneset/app-source.yaml", &sourceApp)).Should(BeNil())
Eventually(
func() error {
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespace, Name: app.Name}, &app)
app.Spec = sourceApp.Spec
return k8sClient.Update(ctx, &app)
},
time.Second*60, time.Millisecond*500).Should(Succeed())
updateApp("app-source.yaml")
By("Modify the application rollout with new target and source")
Eventually(
func() error {
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespace, Name: appRollout.Name}, &appRollout)
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: appRollout.Name}, &appRollout)
appRollout.Spec.SourceAppRevisionName = utils.ConstructRevisionName(app.GetName(), 2)
appRollout.Spec.TargetAppRevisionName = utils.ConstructRevisionName(app.GetName(), 3)
appRollout.Spec.RolloutPlan.BatchPartition = nil
@@ -217,48 +209,42 @@ var _ = Describe("Cloneset based rollout tests", func() {
By("Wait for the rollout phase change to rolling in batches")
Eventually(
func() oamstd.RollingState {
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespace, Name: appRollout.Name}, &appRollout)
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: appRollout.Name}, &appRollout)
return appRollout.Status.RollingState
},
time.Second*10, time.Millisecond*10).Should(BeEquivalentTo(oamstd.RollingInBatchesState))
verifyRolloutSucceeded(appRollout.Spec.TargetAppRevisionName)
verifyAppConfigInactive(appRollout.Spec.SourceAppRevisionName)
// Clean up
k8sClient.Delete(ctx, &appRollout)
}
BeforeEach(func() {
By("Start to run a test, clean up previous resources")
namespace = "rolling-e2e-test" + "-" + strconv.FormatInt(rand.Int63(), 16)
createNamespace(namespace)
namespaceName = "rolling-e2e-test" + "-" + strconv.FormatInt(rand.Int63(), 16)
createNamespace()
})
AfterEach(func() {
By("Clean up resources after a test")
k8sClient.Delete(ctx, &app)
By(fmt.Sprintf("Delete the entire namespace %s", ns.Name))
// delete the namespace with all its resources
Expect(k8sClient.Delete(ctx, &ns, client.PropagationPolicy(metav1.DeletePropagationForeground))).Should(BeNil())
time.Sleep(15 * time.Second)
k8sClient.Delete(ctx, &appRollout)
By(fmt.Sprintf("Delete the entire namespaceName %s", ns.Name))
// delete the namespaceName with all its resources
Expect(k8sClient.Delete(ctx, &ns, client.PropagationPolicy(metav1.DeletePropagationBackground))).Should(BeNil())
})
It("Test cloneset rollout first time (no source)", func() {
CreateClonesetDef()
applySourceApp()
applySourceApp("app-source.yaml")
By("Apply the application rollout go directly to the target")
var newAppRollout v1beta1.AppRollout
Expect(common.ReadYamlToObject("testdata/rollout/cloneset/app-rollout.yaml", &newAppRollout)).Should(BeNil())
newAppRollout.Namespace = namespace
Expect(common.ReadYamlToObject("testdata/rollout/cloneset/appRollout.yaml", &newAppRollout)).Should(BeNil())
newAppRollout.Namespace = namespaceName
newAppRollout.Spec.SourceAppRevisionName = ""
newAppRollout.Spec.TargetAppRevisionName = utils.ConstructRevisionName(app.GetName(), 1)
createAppRolling(&newAppRollout)
appRollout.Name = newAppRollout.Name
appRolloutName = newAppRollout.Name
verifyRolloutSucceeded(newAppRollout.Spec.TargetAppRevisionName)
// Clean up
k8sClient.Delete(ctx, &appRollout)
})
It("Test cloneset rollout with a manual check", func() {
@@ -266,19 +252,19 @@ var _ = Describe("Cloneset based rollout tests", func() {
By("Apply the application rollout to deploy the source")
var newAppRollout v1beta1.AppRollout
Expect(common.ReadYamlToObject("testdata/rollout/cloneset/app-rollout.yaml", &newAppRollout)).Should(BeNil())
newAppRollout.Namespace = namespace
Expect(common.ReadYamlToObject("testdata/rollout/cloneset/appRollout.yaml", &newAppRollout)).Should(BeNil())
newAppRollout.Namespace = namespaceName
newAppRollout.Spec.SourceAppRevisionName = ""
newAppRollout.Spec.TargetAppRevisionName = utils.ConstructRevisionName(app.GetName(), 1)
createAppRolling(&newAppRollout)
appRollout.Name = newAppRollout.Name
appRolloutName = newAppRollout.Name
verifyRolloutSucceeded(newAppRollout.Spec.TargetAppRevisionName)
By("Apply the application rollout that stops after the first batch")
batchPartition := 0
Eventually(
func() error {
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespace, Name: appRollout.Name}, &appRollout)
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: appRollout.Name}, &appRollout)
appRollout.Spec.SourceAppRevisionName = utils.ConstructRevisionName(app.GetName(), 1)
appRollout.Spec.TargetAppRevisionName = utils.ConstructRevisionName(app.GetName(), 2)
appRollout.Spec.RolloutPlan.BatchPartition = pointer.Int32Ptr(int32(batchPartition))
@@ -288,7 +274,7 @@ var _ = Describe("Cloneset based rollout tests", func() {
By("Wait for the rollout phase change to rolling in batches")
Eventually(
func() oamstd.RollingState {
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespace, Name: newAppRollout.Name}, &appRollout)
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: newAppRollout.Name}, &appRollout)
return appRollout.Status.RollingState
},
time.Second*60, time.Millisecond*500).Should(BeEquivalentTo(oamstd.RollingInBatchesState))
@@ -296,7 +282,7 @@ var _ = Describe("Cloneset based rollout tests", func() {
By("Wait for rollout to finish one batch")
Eventually(
func() int32 {
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespace, Name: appRollout.Name}, &appRollout)
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: appRollout.Name}, &appRollout)
return appRollout.Status.CurrentBatch
},
time.Second*15, time.Millisecond*500).Should(BeEquivalentTo(batchPartition))
@@ -305,13 +291,13 @@ var _ = Describe("Cloneset based rollout tests", func() {
// wait for the batch to be ready
Eventually(
func() oamstd.BatchRollingState {
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespace, Name: appRollout.Name}, &appRollout)
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: appRollout.Name}, &appRollout)
return appRollout.Status.BatchRollingState
},
time.Second*30, time.Millisecond*500).Should(Equal(oamstd.BatchReadyState))
// wait for 15 seconds, it should stop at 1
time.Sleep(15 * time.Second)
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespace, Name: appRollout.Name}, &appRollout)
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: appRollout.Name}, &appRollout)
Expect(appRollout.Status.RollingState).Should(BeEquivalentTo(oamstd.RollingInBatchesState))
Expect(appRollout.Status.BatchRollingState).Should(BeEquivalentTo(oamstd.BatchReadyState))
Expect(appRollout.Status.CurrentBatch).Should(BeEquivalentTo(batchPartition))
@@ -326,31 +312,31 @@ var _ = Describe("Cloneset based rollout tests", func() {
verifyRolloutSucceeded(appRollout.Spec.TargetAppRevisionName)
verifyAppConfigInactive(appRollout.Spec.SourceAppRevisionName)
// Clean up
k8sClient.Delete(ctx, &appRollout)
})
It("Test pause and modify rollout plan after rolling succeeded", func() {
CreateClonesetDef()
applySourceApp()
applySourceApp("app-more-replica.yaml")
By("Apply the application rollout go directly to the target")
var newAppRollout v1beta1.AppRollout
Expect(common.ReadYamlToObject("testdata/rollout/cloneset/app-rollout.yaml", &newAppRollout)).Should(BeNil())
newAppRollout.Namespace = namespace
Expect(common.ReadYamlToObject("testdata/rollout/cloneset/appRollout.yaml", &newAppRollout)).Should(BeNil())
newAppRollout.Namespace = namespaceName
newAppRollout.Spec.SourceAppRevisionName = ""
newAppRollout.Spec.TargetAppRevisionName = utils.ConstructRevisionName(app.GetName(), 1)
newAppRollout.Spec.RolloutPlan.BatchPartition = nil
newAppRollout.Spec.RolloutPlan.RolloutBatches = nil
// webhook would fill the batches
newAppRollout.Spec.RolloutPlan.TargetSize = pointer.Int32Ptr(5)
newAppRollout.Spec.RolloutPlan.NumBatches = pointer.Int32Ptr(5)
var replicas int32 = 10
newAppRollout.Spec.RolloutPlan.TargetSize = pointer.Int32Ptr(replicas)
newAppRollout.Spec.RolloutPlan.NumBatches = pointer.Int32Ptr(replicas)
appRolloutName = newAppRollout.Name
createAppRolling(&newAppRollout)
By("Wait for the rollout phase change to initialize")
Eventually(
func() oamstd.RollingState {
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespace, Name: newAppRollout.Name}, &appRollout)
appRollout = v1beta1.AppRollout{}
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: appRolloutName}, &appRollout)
return appRollout.Status.RollingState
},
time.Second*10, time.Millisecond).Should(BeEquivalentTo(oamstd.RollingInBatchesState))
@@ -358,7 +344,7 @@ var _ = Describe("Cloneset based rollout tests", func() {
By("Pause the rollout")
Eventually(
func() error {
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespace, Name: appRollout.Name}, &appRollout)
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: appRollout.Name}, &appRollout)
appRollout.Spec.RolloutPlan.Paused = true
err := k8sClient.Update(ctx, &appRollout)
return err
@@ -367,7 +353,7 @@ var _ = Describe("Cloneset based rollout tests", func() {
By("Verify that the rollout pauses")
Eventually(
func() corev1.ConditionStatus {
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespace, Name: appRollout.Name}, &appRollout)
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: appRollout.Name}, &appRollout)
return appRollout.Status.GetCondition(oamstd.BatchPaused).Status
},
time.Second*30, time.Millisecond*500).Should(Equal(corev1.ConditionTrue))
@@ -375,10 +361,10 @@ var _ = Describe("Cloneset based rollout tests", func() {
preBatch := appRollout.Status.CurrentBatch
// wait for 15 seconds, the batch should not move
time.Sleep(15 * time.Second)
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespace, Name: appRollout.Name}, &appRollout)
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: appRollout.Name}, &appRollout)
Expect(appRollout.Status.RollingState).Should(BeEquivalentTo(oamstd.RollingInBatchesState))
Expect(appRollout.Status.CurrentBatch).Should(BeEquivalentTo(preBatch))
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespace, Name: appRollout.Name}, &appRollout)
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: appRollout.Name}, &appRollout)
lt := appRollout.Status.GetCondition(oamstd.BatchPaused).LastTransitionTime
beforeSleep := metav1.Time{
Time: time.Now().Add(-15 * time.Second),
@@ -394,17 +380,14 @@ var _ = Describe("Cloneset based rollout tests", func() {
verifyRolloutSucceeded(appRollout.Spec.TargetAppRevisionName)
// record the transition time
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespace, Name: appRollout.Name}, &appRollout)
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: appRollout.Name}, &appRollout)
lt = appRollout.Status.GetCondition(oamstd.RolloutSucceed).LastTransitionTime
// nothing should happen, the transition time should be the same
verifyRolloutSucceeded(appRollout.Spec.TargetAppRevisionName)
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespace, Name: appRollout.Name}, &appRollout)
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: appRollout.Name}, &appRollout)
Expect(appRollout.Status.RollingState).Should(BeEquivalentTo(oamstd.RolloutSucceedState))
Expect(appRollout.Status.GetCondition(oamstd.RolloutSucceed).LastTransitionTime).Should(BeEquivalentTo(lt))
// Clean up
k8sClient.Delete(ctx, &appRollout)
})
It("Test rolling back after a successful rollout", func() {
@@ -412,18 +395,18 @@ var _ = Describe("Cloneset based rollout tests", func() {
By("Apply the application rollout to deploy the source")
var newAppRollout v1beta1.AppRollout
Expect(common.ReadYamlToObject("testdata/rollout/cloneset/app-rollout.yaml", &newAppRollout)).Should(BeNil())
newAppRollout.Namespace = namespace
Expect(common.ReadYamlToObject("testdata/rollout/cloneset/appRollout.yaml", &newAppRollout)).Should(BeNil())
newAppRollout.Namespace = namespaceName
newAppRollout.Spec.SourceAppRevisionName = ""
newAppRollout.Spec.TargetAppRevisionName = utils.ConstructRevisionName(app.GetName(), 1)
createAppRolling(&newAppRollout)
appRollout.Name = newAppRollout.Name
appRolloutName = newAppRollout.Name
verifyRolloutSucceeded(newAppRollout.Spec.TargetAppRevisionName)
By("Finish the application rollout")
Eventually(
func() error {
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespace, Name: appRollout.Name}, &appRollout)
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: appRollout.Name}, &appRollout)
appRollout.Spec.SourceAppRevisionName = utils.ConstructRevisionName(app.GetName(), 1)
appRollout.Spec.TargetAppRevisionName = utils.ConstructRevisionName(app.GetName(), 2)
appRollout.Spec.RolloutPlan.BatchPartition = nil
@@ -433,7 +416,7 @@ var _ = Describe("Cloneset based rollout tests", func() {
By("Wait for the rollout phase change to rolling in batches")
Eventually(
func() oamstd.RollingState {
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespace, Name: appRollout.Name}, &appRollout)
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: appRollout.Name}, &appRollout)
return appRollout.Status.RollingState
},
time.Second*10, time.Millisecond*10).Should(BeEquivalentTo(oamstd.RollingInBatchesState))
@@ -449,18 +432,18 @@ var _ = Describe("Cloneset based rollout tests", func() {
By("Apply the application rollout to deploy the source")
var newAppRollout v1beta1.AppRollout
Expect(common.ReadYamlToObject("testdata/rollout/cloneset/app-rollout.yaml", &newAppRollout)).Should(BeNil())
newAppRollout.Namespace = namespace
Expect(common.ReadYamlToObject("testdata/rollout/cloneset/appRollout.yaml", &newAppRollout)).Should(BeNil())
newAppRollout.Namespace = namespaceName
newAppRollout.Spec.SourceAppRevisionName = ""
newAppRollout.Spec.TargetAppRevisionName = utils.ConstructRevisionName(app.GetName(), 1)
createAppRolling(&newAppRollout)
appRollout.Name = newAppRollout.Name
appRolloutName = newAppRollout.Name
verifyRolloutSucceeded(newAppRollout.Spec.TargetAppRevisionName)
By("Finish the application rollout")
Eventually(
func() error {
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespace, Name: appRollout.Name}, &appRollout)
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: appRollout.Name}, &appRollout)
appRollout.Spec.SourceAppRevisionName = utils.ConstructRevisionName(app.GetName(), 1)
appRollout.Spec.TargetAppRevisionName = utils.ConstructRevisionName(app.GetName(), 2)
appRollout.Spec.RolloutPlan.BatchPartition = nil
@@ -470,7 +453,7 @@ var _ = Describe("Cloneset based rollout tests", func() {
By("Wait for the rollout phase change to rolling in batches")
Eventually(
func() oamstd.RollingState {
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespace, Name: appRollout.Name}, &appRollout)
k8sClient.Get(ctx, client.ObjectKey{Namespace: namespaceName, Name: appRollout.Name}, &appRollout)
return appRollout.Status.RollingState
},
time.Second*10, time.Millisecond*10).Should(BeEquivalentTo(oamstd.RollingInBatchesState))
@@ -480,21 +463,22 @@ var _ = Describe("Cloneset based rollout tests", func() {
PIt("Test rolling by changing the definition", func() {
CreateClonesetDef()
applySourceApp()
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: namespace, Name: newCD.Name}, &cd)
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/app-rollout.yaml", &newAppRollout)).Should(BeNil())
newAppRollout.Namespace = namespace
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)

View File

@@ -18,6 +18,7 @@ package controllers_test
import (
"context"
"encoding/json"
"math/rand"
"testing"
"time"
@@ -72,6 +73,7 @@ func TestAPIs(t *testing.T) {
var _ = BeforeSuite(func(done Done) {
By("Bootstrapping test environment")
rand.Seed(time.Now().UnixNano())
logf.SetLogger(zap.New(zap.UseDevMode(true), zap.WriteTo(GinkgoWriter)))
err := clientgoscheme.AddToScheme(scheme)
Expect(err).Should(BeNil())
@@ -116,8 +118,6 @@ var _ = BeforeSuite(func(done Done) {
}
// For some reason, traitDefinition is created as a Cluster scope object
Expect(k8sClient.Create(context.Background(), &manualscalertrait)).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{}))
By("Created manual scalar trait definition")
// Create manual scaler trait definition with spec.extension field
definitionExtension := DefinitionExtension{
Alias: "ManualScaler",

View File

@@ -0,0 +1,19 @@
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: test-rolling-pause
annotations:
"app.oam.dev/rolling-components": "metrics-provider"
"app.oam.dev/rollout-template": "true"
spec:
components:
- name: metrics-provider
type: clonesetservice
properties:
cmd:
- ./podinfo
- stress-cpu=1
image: stefanprodan/podinfo:4.0.3
port: 8080
updateStrategyType: InPlaceIfPossible
replicas: 10

View File

@@ -1,7 +1,7 @@
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
name: test-rolling
name: test-e2e-rolling
annotations:
"app.oam.dev/rolling-components": "metrics-provider"
"app.oam.dev/rollout-template": "true"
@@ -13,6 +13,6 @@ spec:
cmd:
- ./podinfo
- stress-cpu=1
image: stefanprodan/podinfo:4.0.6
image: stefanprodan/podinfo:4.0.3
port: 8080
updateStrategyType: InPlaceIfPossible

View File

@@ -15,4 +15,5 @@ spec:
- stress-cpu=1
image: stefanprodan/podinfo:4.0.3
port: 8080
updateStrategyType: InPlaceIfPossible
updateStrategyType: InPlaceIfPossible
replicas: 5

View File

@@ -15,4 +15,5 @@ spec:
- stress-cpu=1
image: stefanprodan/podinfo:5.0.2
port: 8080
updateStrategyType: InPlaceIfPossible
updateStrategyType: InPlaceIfPossible
replicas: 5

View File

@@ -22,7 +22,9 @@ spec:
"app.oam.dev/component": context.name
}
spec: {
replicas: parameter.replicas
if parameter["replicas"] != _|_ {
replicas: parameter.replicas
}
selector: matchLabels: {
"app.oam.dev/component": context.name
}
@@ -104,5 +106,5 @@ spec:
// +usage=Cloneset updateStrategy, candidates are `ReCreate`/`InPlaceIfPossible`/`InPlaceOnly`
updateStrategyType?: string
// +usage=Number of pods in the cloneset
replicas: *5 | int
replicas?: int
}

View File

@@ -22,7 +22,9 @@ spec:
"app.oam.dev/component": context.name
}
spec: {
replicas: parameter.replicas
if parameter["replicas"] != _|_ {
replicas: parameter.replicas
}
selector: matchLabels: {
"app.oam.dev/component": context.name
}
@@ -35,7 +37,7 @@ spec:
spec: {
containers: [{
name: context.name
image: "stefanprodan/podinfo:5.0.2"
image: parameter.image
if parameter["cmd"] != _|_ {
command: parameter.cmd
@@ -104,5 +106,5 @@ spec:
// +usage=Cloneset updateStrategy, candidates are `ReCreate`/`InPlaceIfPossible`/`InPlaceOnly`
updateStrategyType?: string
// +usage=Number of pods in the cloneset
replicas: *5 | int
replicas?: int
}