mirror of
https://github.com/fluxcd/flagger.git
synced 2026-04-15 06:57:34 +00:00
add unit tests for hpa reconciler
Signed-off-by: Sanskar Jaiswal <sanskar.jaiswal@weave.works>
This commit is contained in:
@@ -50,10 +50,6 @@ func TestDeploymentController_Sync_ConsistentNaming(t *testing.T) {
|
||||
|
||||
annotation := depPrimary.Annotations["kustomize.toolkit.fluxcd.io/checksum"]
|
||||
assert.Equal(t, "", annotation)
|
||||
|
||||
hpaPrimary, err := mocks.kubeClient.AutoscalingV2beta2().HorizontalPodAutoscalers("default").Get(context.TODO(), "podinfo-primary", metav1.GetOptions{})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, depPrimary.Name, hpaPrimary.Spec.ScaleTargetRef.Name)
|
||||
}
|
||||
|
||||
func TestDeploymentController_Sync_InconsistentNaming(t *testing.T) {
|
||||
@@ -71,10 +67,6 @@ func TestDeploymentController_Sync_InconsistentNaming(t *testing.T) {
|
||||
|
||||
primarySelectorValue := depPrimary.Spec.Selector.MatchLabels[dc.label]
|
||||
assert.Equal(t, primarySelectorValue, fmt.Sprintf("%s-primary", dc.labelValue))
|
||||
|
||||
hpaPrimary, err := mocks.kubeClient.AutoscalingV2beta2().HorizontalPodAutoscalers("default").Get(context.TODO(), "podinfo-primary", metav1.GetOptions{})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, depPrimary.Name, hpaPrimary.Spec.ScaleTargetRef.Name)
|
||||
}
|
||||
|
||||
func TestDeploymentController_Promote(t *testing.T) {
|
||||
@@ -90,15 +82,6 @@ func TestDeploymentController_Promote(t *testing.T) {
|
||||
_, err = mocks.kubeClient.CoreV1().ConfigMaps("default").Update(context.TODO(), config2, metav1.UpdateOptions{})
|
||||
require.NoError(t, err)
|
||||
|
||||
hpa, err := mocks.kubeClient.AutoscalingV2beta2().HorizontalPodAutoscalers("default").Get(context.TODO(), "podinfo", metav1.GetOptions{})
|
||||
require.NoError(t, err)
|
||||
|
||||
hpaClone := hpa.DeepCopy()
|
||||
hpaClone.Spec.MaxReplicas = 2
|
||||
|
||||
_, err = mocks.kubeClient.AutoscalingV2beta2().HorizontalPodAutoscalers("default").Update(context.TODO(), hpaClone, metav1.UpdateOptions{})
|
||||
require.NoError(t, err)
|
||||
|
||||
err = mocks.controller.Promote(mocks.canary)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -121,18 +104,6 @@ func TestDeploymentController_Promote(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, config2.Data["color"], configPrimary.Data["color"])
|
||||
|
||||
hpaPrimary, err := mocks.kubeClient.AutoscalingV2beta2().HorizontalPodAutoscalers("default").Get(context.TODO(), "podinfo-primary", metav1.GetOptions{})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, int32(2), hpaPrimary.Spec.MaxReplicas)
|
||||
|
||||
hpaPrimaryLabels := hpaPrimary.ObjectMeta.Labels
|
||||
hpaSourceLabels := hpa.ObjectMeta.Labels
|
||||
assert.Equal(t, hpaSourceLabels["app.kubernetes.io/test-label-1"], hpaPrimaryLabels["app.kubernetes.io/test-label-1"])
|
||||
|
||||
hpaPrimaryAnnotations := hpaPrimary.ObjectMeta.Annotations
|
||||
hpaSourceAnnotations := hpa.ObjectMeta.Annotations
|
||||
assert.Equal(t, hpaSourceAnnotations["app.kubernetes.io/test-annotation-1"], hpaPrimaryAnnotations["app.kubernetes.io/test-annotation-1"])
|
||||
|
||||
value := depPrimary.Spec.Template.Spec.Affinity.PodAntiAffinity.PreferredDuringSchedulingIgnoredDuringExecution[0].PodAffinityTerm.LabelSelector.MatchExpressions[0].Values[0]
|
||||
assert.Equal(t, "podinfo-primary", value)
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/zap"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
hpav2 "k8s.io/api/autoscaling/v2beta2"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@@ -91,7 +90,6 @@ func newCustomizableFixture(dc deploymentConfigs) (deploymentControllerFixture,
|
||||
// init kube clientset and register mock objects
|
||||
kubeClient := fake.NewSimpleClientset(
|
||||
newDeploymentControllerTest(dc),
|
||||
newDeploymentControllerTestHPA(),
|
||||
newDeploymentControllerTestConfigMap(),
|
||||
newDeploymentControllerTestConfigMapEnv(),
|
||||
newDeploymentControllerTestConfigMapVol(),
|
||||
@@ -1000,33 +998,3 @@ func newDeploymentControllerTestV2() *appsv1.Deployment {
|
||||
|
||||
return d
|
||||
}
|
||||
|
||||
func newDeploymentControllerTestHPA() *hpav2.HorizontalPodAutoscaler {
|
||||
h := &hpav2.HorizontalPodAutoscaler{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: hpav2.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
Name: "podinfo",
|
||||
},
|
||||
Spec: hpav2.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: hpav2.CrossVersionObjectReference{
|
||||
Name: "podinfo",
|
||||
APIVersion: "apps/v1",
|
||||
Kind: "Deployment",
|
||||
},
|
||||
Metrics: []hpav2.MetricSpec{
|
||||
{
|
||||
Type: "Resource",
|
||||
Resource: &hpav2.ResourceMetricSource{
|
||||
Name: "cpu",
|
||||
Target: hpav2.MetricTarget{
|
||||
AverageUtilization: int32p(99),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return h
|
||||
}
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
package canary
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
hpav2 "k8s.io/api/autoscaling/v2"
|
||||
hpav2beta2 "k8s.io/api/autoscaling/v2beta2"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
func Test_reconcilePrimaryHpa(t *testing.T) {
|
||||
mocks := newScalerReconcilerFixture(scalerConfig{
|
||||
targetName: "podinfo",
|
||||
scaler: "HorizontalPodAutoscaler",
|
||||
// avoid creating a v2 HPA.
|
||||
excludeObjs: []string{"HPAV2"},
|
||||
})
|
||||
hpaReconciler := mocks.scalerReconciler.(*HPAReconciler)
|
||||
|
||||
err := hpaReconciler.reconcilePrimaryHpa(mocks.canary, true)
|
||||
require.NoError(t, err)
|
||||
|
||||
// assert that we fallback to v2beta2, when HPAv2 fails.
|
||||
_, err = mocks.kubeClient.AutoscalingV2().HorizontalPodAutoscalers("default").Get(context.TODO(), "podinfo-primary", metav1.GetOptions{})
|
||||
assert.True(t, errors.IsNotFound(err))
|
||||
|
||||
hpa, err := mocks.kubeClient.AutoscalingV2beta2().HorizontalPodAutoscalers("default").Get(context.TODO(), "podinfo-primary", metav1.GetOptions{})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, hpa)
|
||||
|
||||
mocks = newScalerReconcilerFixture(scalerConfig{
|
||||
targetName: "podinfo",
|
||||
scaler: "HorizontalPodAutoscaler",
|
||||
// avoid creating _any_ HPAs.
|
||||
excludeObjs: []string{"HPAV2", "HPAV2Beta2"},
|
||||
})
|
||||
hpaReconciler = mocks.scalerReconciler.(*HPAReconciler)
|
||||
// assert that we return an error if no HPAs are found.
|
||||
err = hpaReconciler.reconcilePrimaryHpa(mocks.canary, true)
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func Test_reconcilePrimaryHpaV2(t *testing.T) {
|
||||
mocks := newScalerReconcilerFixture(scalerConfig{
|
||||
targetName: "podinfo",
|
||||
scaler: "HorizontalPodAutoscaler",
|
||||
})
|
||||
hpaReconciler := mocks.scalerReconciler.(*HPAReconciler)
|
||||
|
||||
hpa, err := mocks.kubeClient.AutoscalingV2().HorizontalPodAutoscalers("default").Get(context.TODO(), "podinfo", metav1.GetOptions{})
|
||||
require.NoError(t, err)
|
||||
|
||||
err = hpaReconciler.reconcilePrimaryHpaV2(mocks.canary, hpa, true)
|
||||
require.NoError(t, err)
|
||||
|
||||
primaryHPA, err := mocks.kubeClient.AutoscalingV2().HorizontalPodAutoscalers("default").Get(context.TODO(), "podinfo-primary", metav1.GetOptions{})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, primaryHPA.Spec.ScaleTargetRef.Name, "podinfo-primary")
|
||||
assert.Equal(t, int(*primaryHPA.Spec.Metrics[0].Resource.Target.AverageUtilization), 99)
|
||||
|
||||
hpa.Spec.Metrics[0].Resource.Target = hpav2.MetricTarget{AverageUtilization: int32p(50)}
|
||||
_, err = mocks.kubeClient.AutoscalingV2().HorizontalPodAutoscalers("default").Update(context.TODO(), hpa, metav1.UpdateOptions{})
|
||||
require.NoError(t, err)
|
||||
|
||||
err = hpaReconciler.reconcilePrimaryHpaV2(mocks.canary, hpa, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
primaryHPA, err = mocks.kubeClient.AutoscalingV2().HorizontalPodAutoscalers("default").Get(context.TODO(), "podinfo-primary", metav1.GetOptions{})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, int(*primaryHPA.Spec.Metrics[0].Resource.Target.AverageUtilization), 50)
|
||||
}
|
||||
|
||||
func Test_reconcilePrimaryHpaV2Beta2(t *testing.T) {
|
||||
mocks := newScalerReconcilerFixture(scalerConfig{
|
||||
targetName: "podinfo",
|
||||
scaler: "HorizontalPodAutoscaler",
|
||||
})
|
||||
|
||||
hpaReconciler := mocks.scalerReconciler.(*HPAReconciler)
|
||||
|
||||
hpa, err := mocks.kubeClient.AutoscalingV2beta2().HorizontalPodAutoscalers("default").Get(context.TODO(), "podinfo", metav1.GetOptions{})
|
||||
require.NoError(t, err)
|
||||
|
||||
err = hpaReconciler.reconcilePrimaryHpaV2Beta2(mocks.canary, hpa, true)
|
||||
require.NoError(t, err)
|
||||
|
||||
primaryHPA, err := mocks.kubeClient.AutoscalingV2beta2().HorizontalPodAutoscalers("default").Get(context.TODO(), "podinfo-primary", metav1.GetOptions{})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, primaryHPA.Spec.ScaleTargetRef.Name, "podinfo-primary")
|
||||
assert.Equal(t, int(*primaryHPA.Spec.Metrics[0].Resource.Target.AverageUtilization), 99)
|
||||
|
||||
hpa.Spec.Metrics[0].Resource.Target = hpav2beta2.MetricTarget{AverageUtilization: int32p(50)}
|
||||
_, err = mocks.kubeClient.AutoscalingV2beta2().HorizontalPodAutoscalers("default").Update(context.TODO(), hpa, metav1.UpdateOptions{})
|
||||
require.NoError(t, err)
|
||||
|
||||
err = hpaReconciler.reconcilePrimaryHpaV2Beta2(mocks.canary, hpa, false)
|
||||
require.NoError(t, err)
|
||||
|
||||
primaryHPA, err = mocks.kubeClient.AutoscalingV2beta2().HorizontalPodAutoscalers("default").Get(context.TODO(), "podinfo-primary", metav1.GetOptions{})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, int(*primaryHPA.Spec.Metrics[0].Resource.Target.AverageUtilization), 50)
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
package canary
|
||||
|
||||
import (
|
||||
"go.uber.org/zap"
|
||||
hpav2 "k8s.io/api/autoscaling/v2"
|
||||
hpav2beta2 "k8s.io/api/autoscaling/v2beta2"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
|
||||
flaggerv1 "github.com/fluxcd/flagger/pkg/apis/flagger/v1beta1"
|
||||
clientset "github.com/fluxcd/flagger/pkg/client/clientset/versioned"
|
||||
fakeFlagger "github.com/fluxcd/flagger/pkg/client/clientset/versioned/fake"
|
||||
"github.com/fluxcd/flagger/pkg/logger"
|
||||
)
|
||||
|
||||
type scalerReconcilerFixture struct {
|
||||
canary *flaggerv1.Canary
|
||||
kubeClient kubernetes.Interface
|
||||
flaggerClient clientset.Interface
|
||||
scalerReconciler ScalerReconciler
|
||||
logger *zap.SugaredLogger
|
||||
}
|
||||
|
||||
type scalerConfig struct {
|
||||
targetName string
|
||||
excludeObjs []string
|
||||
scaler string
|
||||
}
|
||||
|
||||
func newScalerReconcilerFixture(cfg scalerConfig) scalerReconcilerFixture {
|
||||
canary := newDeploymentControllerTestCanary(canaryConfigs{targetName: cfg.targetName})
|
||||
flaggerClient := fakeFlagger.NewSimpleClientset(canary)
|
||||
|
||||
kubeClient := fake.NewSimpleClientset(
|
||||
newScalerReconcilerTestHPAV2(),
|
||||
newScalerReconcilerTestHPAV2Beta2(),
|
||||
)
|
||||
for _, obj := range cfg.excludeObjs {
|
||||
if obj == "HPAV2" {
|
||||
kubeClient.Tracker().Delete(schema.GroupVersionResource{
|
||||
Group: "autoscaling",
|
||||
Version: "v2",
|
||||
Resource: "horizontalpodautoscalers",
|
||||
}, "default", "podinfo")
|
||||
}
|
||||
if obj == "HPAV2Beta2" {
|
||||
kubeClient.Tracker().Delete(schema.GroupVersionResource{
|
||||
Group: "autoscaling",
|
||||
Version: "v2beta2",
|
||||
Resource: "horizontalpodautoscalers",
|
||||
}, "default", "podinfo")
|
||||
}
|
||||
}
|
||||
|
||||
logger, _ := logger.NewLogger("debug")
|
||||
var hpaReconciler HPAReconciler
|
||||
|
||||
if cfg.scaler == "HorizontalPodAutoscaler" {
|
||||
hpaReconciler = HPAReconciler{
|
||||
kubeClient: kubeClient,
|
||||
flaggerClient: flaggerClient,
|
||||
logger: logger,
|
||||
includeLabelPrefix: []string{"app.kubernetes.io"},
|
||||
}
|
||||
}
|
||||
|
||||
return scalerReconcilerFixture{
|
||||
canary: canary,
|
||||
kubeClient: kubeClient,
|
||||
flaggerClient: flaggerClient,
|
||||
scalerReconciler: &hpaReconciler,
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
func newScalerReconcilerTestHPAV2Beta2() *hpav2beta2.HorizontalPodAutoscaler {
|
||||
h := &hpav2beta2.HorizontalPodAutoscaler{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: hpav2beta2.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
Name: "podinfo",
|
||||
},
|
||||
Spec: hpav2beta2.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: hpav2beta2.CrossVersionObjectReference{
|
||||
Name: "podinfo",
|
||||
APIVersion: "apps/v1",
|
||||
Kind: "Deployment",
|
||||
},
|
||||
Metrics: []hpav2beta2.MetricSpec{
|
||||
{
|
||||
Type: "Resource",
|
||||
Resource: &hpav2beta2.ResourceMetricSource{
|
||||
Name: "cpu",
|
||||
Target: hpav2beta2.MetricTarget{
|
||||
AverageUtilization: int32p(99),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return h
|
||||
}
|
||||
|
||||
func newScalerReconcilerTestHPAV2() *hpav2.HorizontalPodAutoscaler {
|
||||
h := &hpav2.HorizontalPodAutoscaler{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: hpav2.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
Name: "podinfo",
|
||||
},
|
||||
Spec: hpav2.HorizontalPodAutoscalerSpec{
|
||||
ScaleTargetRef: hpav2.CrossVersionObjectReference{
|
||||
Name: "podinfo",
|
||||
APIVersion: "apps/v1",
|
||||
Kind: "Deployment",
|
||||
},
|
||||
Metrics: []hpav2.MetricSpec{
|
||||
{
|
||||
Type: "Resource",
|
||||
Resource: &hpav2.ResourceMetricSource{
|
||||
Name: "cpu",
|
||||
Target: hpav2.MetricTarget{
|
||||
AverageUtilization: int32p(99),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return h
|
||||
}
|
||||
Reference in New Issue
Block a user