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