http-add-on/operator/controllers/scaled_object_test.go

133 lines
3.4 KiB
Go

package controllers
import (
"context"
"fmt"
"testing"
"time"
"github.com/stretchr/testify/require"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/kedacore/http-add-on/operator/api/v1alpha1"
"github.com/kedacore/http-add-on/operator/controllers/config"
"github.com/kedacore/http-add-on/pkg/k8s"
)
func TestCreateOrUpdateScaledObject(t *testing.T) {
r := require.New(t)
const externalScalerHostName = "mysvc.myns.svc.cluster.local:9090"
testInfra := newCommonTestInfra("testns", "testapp")
r.NoError(createOrUpdateScaledObject(
testInfra.ctx,
testInfra.cl,
testInfra.logger,
externalScalerHostName,
&testInfra.httpso,
))
// make sure that httpso has the AppScaledObjectCreated
// condition on it
r.Equal(1, len(testInfra.httpso.Status.Conditions))
cond1 := testInfra.httpso.Status.Conditions[0]
cond1ts, err := time.Parse(time.RFC3339, cond1.Timestamp)
r.NoError(err)
r.GreaterOrEqual(time.Since(cond1ts), time.Duration(0))
r.Equal(v1alpha1.Created, cond1.Type)
r.Equal(metav1.ConditionTrue, cond1.Status)
r.Equal(v1alpha1.AppScaledObjectCreated, cond1.Reason)
// check that the app ScaledObject was created
retSO, err := getSO(
testInfra.ctx,
testInfra.cl,
testInfra.httpso,
)
r.NoError(err)
metadata, err := getKeyAsMap(retSO.Object, "metadata")
r.NoError(err)
spec, err := getKeyAsMap(retSO.Object, "spec")
r.NoError(err)
r.Equal(testInfra.ns, metadata["namespace"])
r.Equal(
config.AppScaledObjectName(&testInfra.httpso),
metadata["name"],
)
// HTTPScaledObject min/max replicas are int32s,
// but the ScaledObject's spec is decoded into
// an *unsructured.Unstructured (basically a map[string]interface{})
// which is an int64. we need to convert the
// HTTPScaledObject's values into int64s before we compare
r.Equal(
int64(testInfra.httpso.Spec.Replicas.Min),
spec["minReplicaCount"],
)
r.Equal(
int64(testInfra.httpso.Spec.Replicas.Max),
spec["maxReplicaCount"],
)
// now update the min and max replicas on the httpso
// and call createOrUpdateScaledObject again
testInfra.httpso.Spec.Replicas.Min++
testInfra.httpso.Spec.Replicas.Max++
r.NoError(createOrUpdateScaledObject(
testInfra.ctx,
testInfra.cl,
testInfra.logger,
externalScalerHostName,
&testInfra.httpso,
))
// get the scaledobject again and ensure it has
// the new min/max replicas
retSO, err = getSO(
testInfra.ctx,
testInfra.cl,
testInfra.httpso,
)
r.NoError(err)
spec, err = getKeyAsMap(retSO.Object, "spec")
r.NoError(err)
r.Equal(
int64(testInfra.httpso.Spec.Replicas.Min),
spec["minReplicaCount"],
)
r.Equal(
int64(testInfra.httpso.Spec.Replicas.Max),
spec["maxReplicaCount"],
)
}
func getSO(
ctx context.Context,
cl client.Client,
httpso v1alpha1.HTTPScaledObject,
) (*unstructured.Unstructured, error) {
retSO := k8s.NewEmptyScaledObject()
err := cl.Get(ctx, client.ObjectKey{
Namespace: httpso.GetNamespace(),
Name: config.AppScaledObjectName(&httpso),
}, retSO)
return retSO, err
}
func getKeyAsMap(m map[string]interface{}, key string) (map[string]interface{}, error) {
iface, ok := m[key]
if !ok {
return nil, fmt.Errorf("key %s not found in map", key)
}
val, ok := iface.(map[string]interface{})
if !ok {
return nil, fmt.Errorf("key %s was not a map[string]interface{}", key)
}
return val, nil
}