From c211ba0d07ef5c4e1a881767b41b85d0984cd12d Mon Sep 17 00:00:00 2001
From: Alex <alexellis2@gmail.com>
Date: Mon, 30 Jan 2017 21:16:54 +0000
Subject: [PATCH] Cover replica scaling with tests.

---
 gateway/handlers/alerthandler.go   | 49 ++++++++++++++++--------------
 gateway/tests/alerthandler_test.go | 47 ++++++++++++++++++++++++++++
 gateway/tests/isalexa_test.go      | 27 ----------------
 3 files changed, 74 insertions(+), 49 deletions(-)
 create mode 100644 gateway/tests/alerthandler_test.go
 delete mode 100644 gateway/tests/isalexa_test.go

diff --git a/gateway/handlers/alerthandler.go b/gateway/handlers/alerthandler.go
index 0017954b..10d0271a 100644
--- a/gateway/handlers/alerthandler.go
+++ b/gateway/handlers/alerthandler.go
@@ -12,38 +12,43 @@ import (
 	"github.com/docker/docker/client"
 )
 
+// CalculateReplicas decides what replica count to set depending on a Prometheus alert
+func CalculateReplicas(status string, currentReplicas uint64) uint64 {
+	newReplicas := currentReplicas
+
+	if status == "firing" {
+		if currentReplicas == 1 {
+			newReplicas = 5
+		} else {
+			if currentReplicas+5 > 20 {
+				newReplicas = 20
+			} else {
+				newReplicas = currentReplicas + 5
+			}
+		}
+	} else { // Resolved event.
+		newReplicas = 1
+	}
+	return newReplicas
+}
+
 func scaleService(req requests.PrometheusAlert, c *client.Client) error {
 	var err error
 	//Todo: convert to loop / handler.
 	serviceName := req.Alerts[0].Labels.FunctionName
 	service, _, inspectErr := c.ServiceInspectWithRaw(context.Background(), serviceName)
 	if inspectErr == nil {
-		var replicas uint64
 
-		if req.Status == "firing" {
-			if *service.Spec.Mode.Replicated.Replicas < 20 {
-				replicas = *service.Spec.Mode.Replicated.Replicas + uint64(5)
-			} else {
-				return err
-			}
-		} else { // Resolved event.
-			// Previously decremented by 5, but event only fires once, so set to 1/1.
-			if *service.Spec.Mode.Replicated.Replicas > 1 {
-				// replicas = *service.Spec.Mode.Replicated.Replicas - uint64(5)
-				// if replicas < 1 {
-				// replicas = 1
-				// }
-				// return nil
+		currentReplicas := *service.Spec.Mode.Replicated.Replicas
+		status := req.Status
+		newReplicas := CalculateReplicas(status, currentReplicas)
 
-				replicas = 1
-			} else {
-				return nil
-			}
+		if newReplicas == currentReplicas {
+			return nil
 		}
 
-		log.Printf("Scaling %s to %d replicas.\n", serviceName, replicas)
-
-		service.Spec.Mode.Replicated.Replicas = &replicas
+		log.Printf("Scaling %s to %d replicas.\n", serviceName, newReplicas)
+		service.Spec.Mode.Replicated.Replicas = &newReplicas
 		updateOpts := types.ServiceUpdateOptions{}
 		updateOpts.RegistryAuthFrom = types.RegistryAuthFromSpec
 
diff --git a/gateway/tests/alerthandler_test.go b/gateway/tests/alerthandler_test.go
new file mode 100644
index 00000000..8475be20
--- /dev/null
+++ b/gateway/tests/alerthandler_test.go
@@ -0,0 +1,47 @@
+package tests
+
+import (
+	"testing"
+
+	"github.com/alexellis/faas/gateway/handlers"
+)
+
+func TestScale1to5(t *testing.T) {
+	newReplicas := handlers.CalculateReplicas("firing", 1)
+	if newReplicas != 5 {
+		t.Log("Expected increment in blocks of 5 from 1 to 5")
+		t.Fail()
+	}
+}
+
+func TestScale5to10(t *testing.T) {
+	newReplicas := handlers.CalculateReplicas("firing", 5)
+	if newReplicas != 10 {
+		t.Log("Expected increment in blocks of 5 from 5 to 10")
+		t.Fail()
+	}
+}
+
+func TestScaleCeilingOf20Replicas_Noaction(t *testing.T) {
+	newReplicas := handlers.CalculateReplicas("firing", 20)
+	if newReplicas != 20 {
+		t.Log("Expected ceiling of 20 replicas")
+		t.Fail()
+	}
+}
+
+func TestScaleCeilingOf20Replicas(t *testing.T) {
+	newReplicas := handlers.CalculateReplicas("firing", 19)
+	if newReplicas != 20 {
+		t.Log("Expected ceiling of 20 replicas")
+		t.Fail()
+	}
+}
+
+func TestBackingOff10to1(t *testing.T) {
+	newReplicas := handlers.CalculateReplicas("resolved", 10)
+	if newReplicas != 1 {
+		t.Log("Expected backing off to 1 replica")
+		t.Fail()
+	}
+}
diff --git a/gateway/tests/isalexa_test.go b/gateway/tests/isalexa_test.go
deleted file mode 100644
index 89c86370..00000000
--- a/gateway/tests/isalexa_test.go
+++ /dev/null
@@ -1,27 +0,0 @@
-package tests
-
-import (
-	"testing"
-
-	"io/ioutil"
-
-	"github.com/alexellis/faas/gateway/handlers"
-	"github.com/alexellis/faas/gateway/requests"
-)
-
-func TestIsAlexa(t *testing.T) {
-	requestBody, _ := ioutil.ReadFile("./alexhostname_request.json")
-	var result requests.AlexaRequestBody
-
-	result = handlers.IsAlexa(requestBody)
-
-	if len(result.Session.Application.ApplicationId) == 0 {
-		t.Fail()
-	}
-	if len(result.Session.SessionId) == 0 {
-		t.Fail()
-	}
-	if len(result.Request.Intent.Name) == 0 {
-		t.Fail()
-	}
-}
-- 
GitLab