mirror of
https://github.com/kubevela/kubevela.git
synced 2026-05-05 08:57:24 +00:00
* add webhook for app and avoid controller panic neat imports * add test for rollout verify
400 lines
11 KiB
Go
400 lines
11 KiB
Go
/*
|
|
Copyright 2021 The KubeVela Authors.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package workloads
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"k8s.io/utils/pointer"
|
|
|
|
"k8s.io/apimachinery/pkg/util/intstr"
|
|
|
|
"github.com/oam-dev/kubevela/apis/standard.oam.dev/v1alpha1"
|
|
)
|
|
|
|
var (
|
|
rolloutPercentSpec = &v1alpha1.RolloutPlan{
|
|
RolloutBatches: []v1alpha1.RolloutBatch{
|
|
{
|
|
Replicas: intstr.FromString("20%"),
|
|
},
|
|
{
|
|
Replicas: intstr.FromString("40%"),
|
|
},
|
|
{
|
|
Replicas: intstr.FromString("30%"),
|
|
},
|
|
{
|
|
Replicas: intstr.FromString("10%"),
|
|
},
|
|
},
|
|
}
|
|
|
|
rolloutNumericSpec = &v1alpha1.RolloutPlan{
|
|
RolloutBatches: []v1alpha1.RolloutBatch{
|
|
{
|
|
Replicas: intstr.FromInt(1),
|
|
},
|
|
{
|
|
Replicas: intstr.FromInt(2),
|
|
},
|
|
{
|
|
Replicas: intstr.FromInt(4),
|
|
},
|
|
{
|
|
Replicas: intstr.FromInt(3),
|
|
},
|
|
},
|
|
}
|
|
|
|
rolloutMixedSpec = &v1alpha1.RolloutPlan{
|
|
RolloutBatches: []v1alpha1.RolloutBatch{
|
|
{
|
|
Replicas: intstr.FromInt(1),
|
|
},
|
|
{
|
|
Replicas: intstr.FromString("20%"),
|
|
},
|
|
{
|
|
Replicas: intstr.FromString("50%"),
|
|
},
|
|
{
|
|
Replicas: intstr.FromInt(2),
|
|
},
|
|
},
|
|
}
|
|
|
|
rolloutRelaxSpec = &v1alpha1.RolloutPlan{
|
|
RolloutBatches: []v1alpha1.RolloutBatch{
|
|
{
|
|
Replicas: intstr.FromString("20%"),
|
|
},
|
|
{
|
|
Replicas: intstr.FromInt(2),
|
|
},
|
|
{
|
|
Replicas: intstr.FromInt(2),
|
|
},
|
|
{
|
|
Replicas: intstr.FromString("50%"),
|
|
},
|
|
},
|
|
}
|
|
|
|
rolloutOverFlowSpec = &v1alpha1.RolloutPlan{
|
|
RolloutBatches: []v1alpha1.RolloutBatch{
|
|
{
|
|
Replicas: intstr.FromString("140%"),
|
|
},
|
|
{
|
|
Replicas: intstr.FromInt(1),
|
|
},
|
|
{
|
|
Replicas: intstr.FromString("40%"),
|
|
},
|
|
},
|
|
}
|
|
)
|
|
|
|
func TestCalculateNewBatchTarget(t *testing.T) {
|
|
// test common rollout
|
|
if got := calculateNewBatchTarget(rolloutMixedSpec, 0, 10, 0); got != 1 {
|
|
t.Errorf("calculateNewBatchTarget() = %v, want %v", got, 1)
|
|
}
|
|
if got := calculateNewBatchTarget(rolloutMixedSpec, 0, 10, 1); got != 3 {
|
|
t.Errorf("calculateNewBatchTarget() = %v, want %v", got, 3)
|
|
}
|
|
if got := calculateNewBatchTarget(rolloutMixedSpec, 0, 10, 2); got != 8 {
|
|
t.Errorf("calculateNewBatchTarget() = %v, want %v", got, 8)
|
|
}
|
|
if got := calculateNewBatchTarget(rolloutMixedSpec, 0, 10, 3); got != 10 {
|
|
t.Errorf("calculateNewBatchTarget() = %v, want %v", got, 10)
|
|
}
|
|
|
|
// test scale up
|
|
if got := calculateNewBatchTarget(rolloutMixedSpec, 2, 12, 0); got != 3 {
|
|
t.Errorf("calculateNewBatchTarget() = %v, want %v", got, 3)
|
|
}
|
|
if got := calculateNewBatchTarget(rolloutMixedSpec, 3, 13, 1); got != 6 {
|
|
t.Errorf("calculateNewBatchTarget() = %v, want %v", got, 6)
|
|
}
|
|
if got := calculateNewBatchTarget(rolloutMixedSpec, 4, 14, 2); got != 12 {
|
|
t.Errorf("calculateNewBatchTarget() = %v, want %v", got, 12)
|
|
}
|
|
if got := calculateNewBatchTarget(rolloutMixedSpec, 5, 15, 3); got != 15 {
|
|
t.Errorf("calculateNewBatchTarget() = %v, want %v", got, 15)
|
|
}
|
|
|
|
// test scale down
|
|
if got := calculateNewBatchTarget(rolloutMixedSpec, 10, 0, 0); got != 9 {
|
|
t.Errorf("calculateNewBatchTarget() = %v, want %v", got, 9)
|
|
}
|
|
if got := calculateNewBatchTarget(rolloutMixedSpec, 20, 5, 1); got != 16 {
|
|
t.Errorf("calculateNewBatchTarget() = %v, want %v", got, 16)
|
|
}
|
|
if got := calculateNewBatchTarget(rolloutMixedSpec, 30, 15, 2); got != 18 {
|
|
t.Errorf("calculateNewBatchTarget() = %v, want %v", got, 18)
|
|
}
|
|
if got := calculateNewBatchTarget(rolloutMixedSpec, 40, 10, 3); got != 10 {
|
|
t.Errorf("calculateNewBatchTarget() = %v, want %v", got, 10)
|
|
}
|
|
}
|
|
|
|
func TestCalculateNewBatchTargetCornerCases(t *testing.T) {
|
|
// test current batch overflow
|
|
if got := calculateNewBatchTarget(rolloutMixedSpec, 2, 12, 4); got != 12 {
|
|
t.Errorf("calculateNewBatchTarget() = %v, want %v", got, 12)
|
|
}
|
|
if got := calculateNewBatchTarget(rolloutMixedSpec, 13, 3, 5); got != 3 {
|
|
t.Errorf("calculateNewBatchTarget() = %v, want %v", got, 3)
|
|
}
|
|
// numeric value doesn't match the range
|
|
if got := calculateNewBatchTarget(rolloutNumericSpec, 16, 10, 0); got != 15 {
|
|
t.Errorf("calculateNewBatchTarget() = %v, want %v", got, 15)
|
|
}
|
|
if got := calculateNewBatchTarget(rolloutPercentSpec, 10, 10, 2); got != 10 {
|
|
t.Errorf("calculateNewBatchTarget() = %v, want %v", got, 10)
|
|
}
|
|
}
|
|
|
|
func TestVerifyBatchesWithRolloutNormal(t *testing.T) {
|
|
if err := verifyBatchesWithRollout(rolloutMixedSpec, 10); err != nil {
|
|
t.Errorf("verifyBatchesWithRollout() = %v, want nil", err)
|
|
}
|
|
if err := verifyBatchesWithRollout(rolloutMixedSpec, 12); err != nil {
|
|
t.Errorf("verifyBatchesWithRollout() = %v, want nil", err)
|
|
}
|
|
if err := verifyBatchesWithRollout(rolloutMixedSpec, 13); err != nil {
|
|
t.Errorf("verifyBatchesWithRollout() = %v, want nil", err)
|
|
}
|
|
if err := verifyBatchesWithRollout(rolloutMixedSpec, 20); err == nil {
|
|
t.Errorf("verifyBatchesWithRollout() = %v, want error", nil)
|
|
}
|
|
if err := verifyBatchesWithRollout(rolloutMixedSpec, 6); err == nil {
|
|
t.Errorf("verifyBatchesWithRollout() = %v, want error", nil)
|
|
}
|
|
}
|
|
|
|
func TestVerifyBatchesWithRolloutRelaxed(t *testing.T) {
|
|
// last batch as a percentage always succeeds
|
|
if err := verifyBatchesWithRollout(rolloutRelaxSpec, 10); err != nil {
|
|
t.Errorf("verifyBatchesWithRollout() = %v, want nil", err)
|
|
}
|
|
if err := verifyBatchesWithRollout(rolloutRelaxSpec, 100); err != nil {
|
|
t.Errorf("verifyBatchesWithRollout() = %v, want nil", err)
|
|
}
|
|
if err := verifyBatchesWithRollout(rolloutRelaxSpec, 31); err != nil {
|
|
t.Errorf("verifyBatchesWithRollout() = %v, want nil", err)
|
|
}
|
|
// last can't be zero
|
|
if err := verifyBatchesWithRollout(rolloutRelaxSpec, 6); err == nil {
|
|
t.Errorf("verifyBatchesWithRollout() = %v, want error", nil)
|
|
}
|
|
// overflow always fail
|
|
if err := verifyBatchesWithRollout(rolloutOverFlowSpec, 10); err == nil {
|
|
t.Errorf("verifyBatchesWithRollout() = %v, want error", nil)
|
|
}
|
|
if err := verifyBatchesWithRollout(rolloutOverFlowSpec, 100); err == nil {
|
|
t.Errorf("verifyBatchesWithRollout() = %v, want error", nil)
|
|
}
|
|
if err := verifyBatchesWithRollout(rolloutOverFlowSpec, 1); err == nil {
|
|
t.Errorf("verifyBatchesWithRollout() = %v, want error", nil)
|
|
}
|
|
if err := verifyBatchesWithRollout(rolloutOverFlowSpec, 0); err == nil {
|
|
t.Errorf("verifyBatchesWithRollout() = %v, want error", nil)
|
|
}
|
|
}
|
|
|
|
func TestVerifyEmptyRolloutBatches(t *testing.T) {
|
|
plan := &v1alpha1.RolloutPlan{
|
|
TargetSize: pointer.Int32Ptr(2),
|
|
}
|
|
if err := verifyBatchesWithRollout(plan, 3); err == nil {
|
|
t.Errorf("verifyBatchesWithRollout() = %v, want error", nil)
|
|
}
|
|
}
|
|
|
|
func TestVerifyBatchesWithRolloutNumeric(t *testing.T) {
|
|
// test hard number
|
|
if err := verifyBatchesWithRollout(rolloutNumericSpec, 6); err == nil {
|
|
t.Errorf("verifyBatchesWithRollout() = %v, want error", nil)
|
|
}
|
|
if err := verifyBatchesWithRollout(rolloutNumericSpec, 11); err == nil {
|
|
t.Errorf("verifyBatchesWithRollout() = %v, want error", nil)
|
|
}
|
|
if err := verifyBatchesWithRollout(rolloutNumericSpec, 10); err != nil {
|
|
t.Errorf("verifyBatchesWithRollout() = %v, want nil", err)
|
|
}
|
|
}
|
|
|
|
func Test_VerifyBatchesWithScalePassCases(t *testing.T) {
|
|
tests := map[string]struct {
|
|
rolloutSpec *v1alpha1.RolloutPlan
|
|
originalSize int
|
|
targetSize int
|
|
}{
|
|
"percent equal case 1": {
|
|
rolloutSpec: rolloutPercentSpec,
|
|
originalSize: 12,
|
|
targetSize: 12,
|
|
},
|
|
"percent equal case 2": {
|
|
rolloutSpec: rolloutPercentSpec,
|
|
originalSize: 0,
|
|
targetSize: 0,
|
|
},
|
|
"percent increase case": {
|
|
rolloutSpec: rolloutPercentSpec,
|
|
originalSize: 12,
|
|
targetSize: 22,
|
|
},
|
|
"percent decrease case 1": {
|
|
rolloutSpec: rolloutPercentSpec,
|
|
originalSize: 27,
|
|
targetSize: 7,
|
|
},
|
|
"percent decrease case 2": {
|
|
rolloutSpec: rolloutPercentSpec,
|
|
originalSize: 27,
|
|
targetSize: 0,
|
|
},
|
|
"relax increase 1": {
|
|
rolloutSpec: rolloutRelaxSpec,
|
|
originalSize: 12,
|
|
targetSize: 32,
|
|
},
|
|
"relax increase 2": {
|
|
rolloutSpec: rolloutRelaxSpec,
|
|
originalSize: 12,
|
|
targetSize: 22,
|
|
},
|
|
"mix increase 1": {
|
|
rolloutSpec: rolloutMixedSpec,
|
|
originalSize: 13,
|
|
targetSize: 26,
|
|
},
|
|
"mix increase 2": {
|
|
rolloutSpec: rolloutMixedSpec,
|
|
originalSize: 30,
|
|
targetSize: 42,
|
|
},
|
|
"mix decrease 1": {
|
|
rolloutSpec: rolloutMixedSpec,
|
|
originalSize: 32,
|
|
targetSize: 20,
|
|
},
|
|
"mix decrease 2": {
|
|
rolloutSpec: rolloutMixedSpec,
|
|
originalSize: 12,
|
|
targetSize: 0,
|
|
},
|
|
"numeric increase": {
|
|
rolloutSpec: rolloutNumericSpec,
|
|
originalSize: 16,
|
|
targetSize: 26,
|
|
},
|
|
"numeric decrease": {
|
|
rolloutSpec: rolloutNumericSpec,
|
|
originalSize: 13,
|
|
targetSize: 3,
|
|
},
|
|
}
|
|
for name, tt := range tests {
|
|
t.Run(name, func(t *testing.T) {
|
|
if err := verifyBatchesWithScale(tt.rolloutSpec, tt.originalSize, tt.targetSize); err != nil {
|
|
t.Errorf("verifyBatchesWithScale() error = %v, want pass", err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_VerifyBatchesWithScaleFailCases(t *testing.T) {
|
|
tests := map[string]struct {
|
|
rolloutSpec *v1alpha1.RolloutPlan
|
|
originalSize int
|
|
targetSize int
|
|
}{
|
|
"total percent more than 100 increase": {
|
|
rolloutSpec: rolloutOverFlowSpec,
|
|
originalSize: 12,
|
|
targetSize: 115,
|
|
},
|
|
"total percent more than 100 decrease": {
|
|
rolloutSpec: rolloutOverFlowSpec,
|
|
originalSize: 312,
|
|
targetSize: 15,
|
|
},
|
|
"total percent more than 100 equal": {
|
|
rolloutSpec: rolloutOverFlowSpec,
|
|
originalSize: 12,
|
|
targetSize: 12,
|
|
},
|
|
"percent increase case less than batch number": {
|
|
rolloutSpec: rolloutPercentSpec,
|
|
originalSize: 12,
|
|
targetSize: 15,
|
|
},
|
|
"percent decrease case": {
|
|
rolloutSpec: rolloutPercentSpec,
|
|
originalSize: 10,
|
|
targetSize: 7,
|
|
},
|
|
"relax increase too little": {
|
|
rolloutSpec: rolloutRelaxSpec,
|
|
originalSize: 12,
|
|
targetSize: 17,
|
|
},
|
|
"mix increase": {
|
|
rolloutSpec: rolloutMixedSpec,
|
|
originalSize: 13,
|
|
targetSize: 20,
|
|
},
|
|
"mix decrease": {
|
|
rolloutSpec: rolloutMixedSpec,
|
|
originalSize: 42,
|
|
targetSize: 33,
|
|
},
|
|
"numeric increase": {
|
|
rolloutSpec: rolloutNumericSpec,
|
|
originalSize: 16,
|
|
targetSize: 32,
|
|
},
|
|
"numeric decrease 1": {
|
|
rolloutSpec: rolloutNumericSpec,
|
|
originalSize: 13,
|
|
targetSize: 10,
|
|
},
|
|
"numeric decrease 2": {
|
|
rolloutSpec: rolloutNumericSpec,
|
|
originalSize: 16,
|
|
targetSize: 10,
|
|
},
|
|
"empty rollingBatches": {
|
|
rolloutSpec: &v1alpha1.RolloutPlan{},
|
|
targetSize: 3,
|
|
originalSize: 2,
|
|
},
|
|
}
|
|
for name, tt := range tests {
|
|
t.Run(name, func(t *testing.T) {
|
|
if err := verifyBatchesWithScale(tt.rolloutSpec, tt.originalSize, tt.targetSize); err == nil {
|
|
t.Errorf("verifyBatchesWithScale passed, want fail")
|
|
}
|
|
})
|
|
}
|
|
}
|