Skip to content

Commit

Permalink
Merge pull request #1471 from flanksource/postgrest-persist-canary
Browse files Browse the repository at this point in the history
feat: add postgrest response modifier
  • Loading branch information
moshloop authored Nov 28, 2023
2 parents f73cd63 + 9ea8cad commit d7a10e3
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 4 deletions.
34 changes: 32 additions & 2 deletions cmd/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ package cmd

import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
_ "net/http/pprof" // required by serve
"net/url"
"os"
"os/signal"
"strings"
"time"

"github.com/labstack/echo/v4"
Expand Down Expand Up @@ -81,6 +84,32 @@ func setup() {
go push.Start()
}

func postgrestResponseModifier(r *http.Response) error {
shouldPersistCanary := r.Request.Method == http.MethodPost &&
strings.TrimSuffix(r.Request.URL.Path, "/") == "/canaries" &&
r.StatusCode == http.StatusCreated

// If a new canary is inserted via postgrest, we need to persist the canary
// again so that all the checks of that canary are created in the database
if shouldPersistCanary {
var canaries []pkg.Canary
body, err := io.ReadAll(r.Body)
if err != nil {
return fmt.Errorf("error reading response body: %w", err)
}
if err := json.Unmarshal(body, &canaries); err != nil {
return fmt.Errorf("error unmarshaling response body to json: %w", err)
}
for _, c := range canaries {
if _, err := db.PersistCanaryModel(c); err != nil {
logger.Errorf("Error persisting canary[%s]: %v", c.ID, err)
}
}
}

return nil
}

func serve() {
var allowedCors string
e := echo.New()
Expand All @@ -106,7 +135,7 @@ func serve() {

if !disablePostgrest {
go db.StartPostgrest()
forward(e, "/db", db.PostgRESTEndpoint())
forward(e, "/db", db.PostgRESTEndpoint(), postgrestResponseModifier)
}

e.Use(middleware.Logger())
Expand Down Expand Up @@ -158,7 +187,7 @@ func serve() {
}
}

func forward(e *echo.Echo, prefix string, target string) {
func forward(e *echo.Echo, prefix string, target string, respModifierFunc func(*http.Response) error) {
targetURL, err := url.Parse(target)
if err != nil {
e.Logger.Fatal(err)
Expand All @@ -172,6 +201,7 @@ func forward(e *echo.Echo, prefix string, target string) {
URL: targetURL,
},
}),
ModifyResponse: respModifierFunc,
}))
}

Expand Down
11 changes: 9 additions & 2 deletions pkg/db/canary.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,15 @@ import (
dutyTypes "github.com/flanksource/duty/types"
"github.com/google/uuid"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgconn"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)

var (
PostgresDuplicateKeyError = &pgconn.PgError{Code: "23505"}
)

func GetAllCanariesForSync(ctx context.Context, namespace string) ([]pkg.Canary, error) {
query := `
SELECT json_agg(
Expand Down Expand Up @@ -335,9 +340,11 @@ func PersistCanaryModel(model pkg.Canary) (*pkg.Canary, error) {

// Duplicate key happens when an already created canary is persisted
// We will ignore this error but act on other errors
// In this scenario PostgresDuplicateKeyError is checked primarily and
// gorm.ErrDuplicatedKey is just for fallback but does not work
if err != nil {
if !errors.Is(err, gorm.ErrDuplicatedKey) {
return nil, err
if !errors.As(err, &PostgresDuplicateKeyError) && !errors.Is(err, gorm.ErrDuplicatedKey) {
return nil, fmt.Errorf("error persisting canary to db: %w", err)
}
}

Expand Down

0 comments on commit d7a10e3

Please sign in to comment.