133 lines
3.4 KiB
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
|
|
}
|