diff --git a/cmd/e2e-runner/main.go b/cmd/e2e-runner/main.go index 8db72878c..432006b32 100644 --- a/cmd/e2e-runner/main.go +++ b/cmd/e2e-runner/main.go @@ -27,15 +27,14 @@ import ( "github.com/google/exposure-notifications-server/pkg/logging" "github.com/google/exposure-notifications-server/pkg/observability" "github.com/google/exposure-notifications-server/pkg/server" - "go.opencensus.io/stats" "github.com/google/exposure-notifications-verification-server/internal/buildinfo" "github.com/google/exposure-notifications-verification-server/internal/clients" "github.com/google/exposure-notifications-verification-server/internal/envstest" "github.com/google/exposure-notifications-verification-server/internal/project" "github.com/google/exposure-notifications-verification-server/pkg/config" + "github.com/google/exposure-notifications-verification-server/pkg/controller/e2erunner" "github.com/google/exposure-notifications-verification-server/pkg/controller/middleware" - "github.com/google/exposure-notifications-verification-server/pkg/database" "github.com/google/exposure-notifications-verification-server/pkg/render" "github.com/gorilla/handlers" @@ -157,10 +156,11 @@ func realMain(ctx context.Context) error { recovery := middleware.Recovery(h) r.Use(recovery) - r.Handle("/default", handleDefault(cfg, db, h)) - r.Handle("/revise", handleRevise(cfg, db, h)) - r.Handle("/user-report", handleUserReport(cfg, db, h)) - r.Handle("/enx-redirect", handleENXRedirect(enxRedirectClient, h)) + e2erunnerController := e2erunner.New(cfg, db, enxRedirectClient, h) + r.Handle("/default", e2erunnerController.HandleDefault()) + r.Handle("/revise", e2erunnerController.HandleRevise()) + r.Handle("/user-report", e2erunnerController.HandleUserReport()) + r.Handle("/enx-redirect", e2erunnerController.HandleENXRedirect()) mux := http.Handler(r) if cfg.DevMode { @@ -175,77 +175,3 @@ func realMain(ctx context.Context) error { logger.Infow("server listening", "port", cfg.Port) return srv.ServeHTTPHandler(ctx, mux) } - -// handleDefault handles the default end-to-end scenario. -func handleDefault(cfg *config.E2ERunnerConfig, db *database.Database, h *render.Renderer) http.Handler { - c := *cfg - c.DoRevise = false - c.DoUserReport = false - return handleEndToEnd(&c, db, h, mDefaultSuccess) -} - -// handleRevise runs the end-to-end runner with revision tokens. -func handleRevise(cfg *config.E2ERunnerConfig, db *database.Database, h *render.Renderer) http.Handler { - c := *cfg - c.DoRevise = true - c.DoUserReport = false - return handleEndToEnd(&c, db, h, mRevisionSuccess) -} - -// handleUserReport runs the end-to-end runner initiated by a user-report API request. -func handleUserReport(cfg *config.E2ERunnerConfig, db *database.Database, h *render.Renderer) http.Handler { - c := *cfg - c.DoRevise = false - c.DoUserReport = true - return handleEndToEnd(&c, db, h, mUserReportSuccess) -} - -// handleEndToEnd handles the common end-to-end scenario. m is incremented iff -// the run succeeds. -func handleEndToEnd(cfg *config.E2ERunnerConfig, db *database.Database, h *render.Renderer, m *stats.Int64Measure) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - ctx := r.Context() - logger := logging.FromContext(ctx) - - if cfg.DoUserReport { - if err := db.DeleteUserReport(project.TestPhoneNumber); err != nil { - logger.Errorw("error deleting previous user report for test phone number", "error", err) - h.RenderJSON(w, http.StatusInternalServerError, err) - return - } - } - - if err := clients.RunEndToEnd(ctx, cfg); err != nil { - logger.Errorw("failure", "error", err) - h.RenderJSON(w, http.StatusInternalServerError, err) - return - } - - stats.Record(ctx, m.M(1)) - h.RenderJSON(w, http.StatusOK, nil) - }) -} - -// handleENXRedirect handles tests for the redirector service. -func handleENXRedirect(client *clients.ENXRedirectClient, h *render.Renderer) http.Handler { - // If the client doesn't exist, it means the host was not provided. - if client == nil { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - h.RenderJSON(w, http.StatusOK, nil) - }) - } - - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - ctx := r.Context() - logger := logging.FromContext(ctx) - - if err := client.RunE2E(ctx); err != nil { - logger.Errorw("failure", "error", err) - h.RenderJSON(w, http.StatusInternalServerError, err) - return - } - - stats.Record(ctx, mRedirectSuccess.M(1)) - h.RenderJSON(w, http.StatusOK, nil) - }) -} diff --git a/pkg/controller/e2erunner/e2erunner.go b/pkg/controller/e2erunner/e2erunner.go new file mode 100644 index 000000000..83beea2f6 --- /dev/null +++ b/pkg/controller/e2erunner/e2erunner.go @@ -0,0 +1,41 @@ +// Copyright 2021 the Exposure Notifications Verification Server authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package e2erunner implements the end-to-end runner. +package e2erunner + +import ( + "github.com/google/exposure-notifications-verification-server/internal/clients" + "github.com/google/exposure-notifications-verification-server/pkg/config" + "github.com/google/exposure-notifications-verification-server/pkg/database" + "github.com/google/exposure-notifications-verification-server/pkg/render" +) + +// Controller is a controller for the e2e runner service. +type Controller struct { + config *config.E2ERunnerConfig + db *database.Database + client *clients.ENXRedirectClient + h *render.Renderer +} + +// New creates a new cleanup controller. +func New(cfg *config.E2ERunnerConfig, db *database.Database, client *clients.ENXRedirectClient, h *render.Renderer) *Controller { + return &Controller{ + config: cfg, + db: db, + client: client, + h: h, + } +} diff --git a/pkg/controller/e2erunner/handlers.go b/pkg/controller/e2erunner/handlers.go new file mode 100644 index 000000000..460995119 --- /dev/null +++ b/pkg/controller/e2erunner/handlers.go @@ -0,0 +1,100 @@ +// Copyright 2021 the Exposure Notifications Verification Server authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package e2erunner + +import ( + "net/http" + + "github.com/google/exposure-notifications-server/pkg/logging" + "github.com/google/exposure-notifications-verification-server/internal/clients" + "github.com/google/exposure-notifications-verification-server/internal/project" + "github.com/google/exposure-notifications-verification-server/pkg/config" + "go.opencensus.io/stats" +) + +// HandleDefault handles the default end-to-end scenario. +func (c *Controller) HandleDefault() http.Handler { + cfg := *c.config + cfg.DoRevise = false + cfg.DoUserReport = false + return c.handleEndToEnd(&cfg, mDefaultSuccess) +} + +// HandleRevise runs the end-to-end runner with revision tokens. +func (c *Controller) HandleRevise() http.Handler { + cfg := *c.config + cfg.DoRevise = true + cfg.DoUserReport = false + return c.handleEndToEnd(&cfg, mRevisionSuccess) +} + +// HandleUserReport runs the end-to-end runner initiated by a user-report API +// request. +func (c *Controller) HandleUserReport() http.Handler { + cfg := *c.config + cfg.DoRevise = false + cfg.DoUserReport = true + return c.handleEndToEnd(&cfg, mUserReportSuccess) +} + +// handleEndToEnd handles the common end-to-end scenario. m is incremented iff +// the run succeeds. +func (c *Controller) handleEndToEnd(cfg *config.E2ERunnerConfig, m *stats.Int64Measure) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + logger := logging.FromContext(ctx) + + if cfg.DoUserReport { + if err := c.db.DeleteUserReport(project.TestPhoneNumber); err != nil { + logger.Errorw("error deleting previous user report for test phone number", "error", err) + c.h.RenderJSON(w, http.StatusInternalServerError, err) + return + } + } + + if err := clients.RunEndToEnd(ctx, cfg); err != nil { + logger.Errorw("failure", "error", err) + c.h.RenderJSON(w, http.StatusInternalServerError, err) + return + } + + stats.Record(ctx, m.M(1)) + c.h.RenderJSON(w, http.StatusOK, nil) + }) +} + +// HandleENXRedirect handles tests for the redirector service. +func (c *Controller) HandleENXRedirect() http.Handler { + // If the client doesn't exist, it means the host was not provided. + if c.client == nil { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + c.h.RenderJSON(w, http.StatusOK, nil) + }) + } + + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + logger := logging.FromContext(ctx) + + if err := c.client.RunE2E(ctx); err != nil { + logger.Errorw("failure", "error", err) + c.h.RenderJSON(w, http.StatusInternalServerError, err) + return + } + + stats.Record(ctx, mRedirectSuccess.M(1)) + c.h.RenderJSON(w, http.StatusOK, nil) + }) +} diff --git a/cmd/e2e-runner/metrics.go b/pkg/controller/e2erunner/metrics.go similarity index 99% rename from cmd/e2e-runner/metrics.go rename to pkg/controller/e2erunner/metrics.go index 4f32a764e..33b4a2394 100644 --- a/cmd/e2e-runner/metrics.go +++ b/pkg/controller/e2erunner/metrics.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package main +package e2erunner import ( enobs "github.com/google/exposure-notifications-server/pkg/observability"