From a7b68884ed933b4e498bca27eef44c5743dccceb Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Mon, 30 Oct 2023 23:10:21 +0100 Subject: [PATCH] add scaffolding for heartbeats --- api/v1/api.go | 7 ++++ api/v1/heartbeats.go | 91 ++++++++++++++++++++++++++++++++++++++++++++ api/v1/types.go | 5 +++ store/heartbeats.go | 56 +++++++++++++++++++++++++++ store/types.go | 10 +++++ 5 files changed, 169 insertions(+) create mode 100644 api/v1/heartbeats.go create mode 100644 store/heartbeats.go diff --git a/api/v1/api.go b/api/v1/api.go index 3e02b61..e25a469 100644 --- a/api/v1/api.go +++ b/api/v1/api.go @@ -57,6 +57,13 @@ func InstallHTTPHandler(r *gin.RouterGroup, st *store.Store) { alerts.PATCH(":alert-id/state", api.UpdateAlertState) alerts.DELETE(":alert-id", api.DeleteAlert) } + heartbeats := r.Group("heartbeats") + { + heartbeats.GET("", api.ListHeartbeats) + heartbeats.POST("", api.CreateHeartbeat) + heartbeats.GET(":heartbeat-id", api.ReadHeartbeat) + heartbeats.DELETE(":heartbeat-id", api.DeleteAlert) + } submit := r.Group("submit") { diff --git a/api/v1/heartbeats.go b/api/v1/heartbeats.go new file mode 100644 index 0000000..bab78b9 --- /dev/null +++ b/api/v1/heartbeats.go @@ -0,0 +1,91 @@ +// +// Copyright (c) 2023 whawty contributors (see AUTHORS file) +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of whawty.alerts nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +package v1 + +import ( + "encoding/json" + "net/http" + + "github.com/gin-gonic/gin" + "github.com/oklog/ulid/v2" + "github.com/whawty/alerts/store" +) + +func (api *API) ListHeartbeats(c *gin.Context) { + offset, limit, ok := getPaginationParameter(c) + if !ok { + return + } + + heartbeats, err := api.store.ListHeartbeats(offset, limit) + if err != nil { + sendError(c, err) + return + } + c.JSON(http.StatusOK, HeartbeatsListing{heartbeats}) +} + +func (api *API) CreateHeartbeat(c *gin.Context) { + heartbeat := &store.Heartbeat{} + err := json.NewDecoder(c.Request.Body).Decode(heartbeat) + if err != nil { + c.JSON(http.StatusBadRequest, ErrorResponse{Error: "error decoding heartbeat: " + err.Error()}) + return + } + heartbeat.ID = ulid.Make().String() + + if heartbeat, err = api.store.CreateHeartbeat(heartbeat); err != nil { + sendError(c, err) + return + } + c.JSON(http.StatusCreated, heartbeat) +} + +func (api *API) ReadHeartbeat(c *gin.Context) { + id := c.Param("heartbeat-id") + + heartbeat, err := api.store.GetHeartbeat(id) + if err != nil { + sendError(c, err) + return + } + c.JSON(http.StatusOK, heartbeat) +} + +func (api *API) DeleteHeartbeat(c *gin.Context) { + id := c.Param("heartbeat-id") + + if err := api.store.DeleteHeartbeat(id); err != nil { + sendError(c, err) + return + } + c.JSON(http.StatusNoContent, nil) +} diff --git a/api/v1/types.go b/api/v1/types.go index a21a8e6..27070a4 100644 --- a/api/v1/types.go +++ b/api/v1/types.go @@ -44,3 +44,8 @@ type ErrorResponse struct { type AlertsListing struct { Alerts []store.Alert `json:"results"` } + +// Heartbeats +type HeartbeatsListing struct { + Heartbeats []store.Heartbeat `json:"results"` +} diff --git a/store/heartbeats.go b/store/heartbeats.go new file mode 100644 index 0000000..63cb41b --- /dev/null +++ b/store/heartbeats.go @@ -0,0 +1,56 @@ +// +// Copyright (c) 2023 whawty contributors (see AUTHORS file) +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, this +// list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * Neither the name of whawty.alerts nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +package store + +func (s *Store) CreateHeartbeat(alert *Heartbeat) (*Heartbeat, error) { + // TODO: implement this + return nil, ErrNotImplemented +} + +func (s *Store) ListHeartbeats(offset, limit int) ([]Heartbeat, error) { + // TODO: implement this + return nil, ErrNotImplemented +} + +func (s *Store) GetHeartbeat(id string) (*Heartbeat, error) { + // TODO: implement this + return nil, ErrNotImplemented +} + +func (s *Store) RefreshHeartbeat(id string) (*Heartbeat, error) { + // TODO: implement this + return nil, ErrNotImplemented +} + +func (s *Store) DeleteHeartbeat(id string) error { + // TODO: implement this + return ErrNotImplemented +} diff --git a/store/types.go b/store/types.go index a050aae..03daafe 100644 --- a/store/types.go +++ b/store/types.go @@ -193,8 +193,18 @@ type Alert struct { Name string `json:"name"` State AlertState `json:"state"` Severity AlertSeverity `json:"severity"` + // TODO: additinial fields } func (a Alert) String() string { return a.ID } + +// Heartbeats + +type Heartbeat struct { + ID string `json:"id"` + CreatedAt time.Time `json:"created"` + UpdatedAt time.Time `json:"updated"` + // TODO: additinial fields +}