feature(api,release): prepare for next major release and switch to requiring content-type set to JSON for all incoming requests and expose more CORS environment variables
All checks were successful
/ build (push) Successful in 5m3s
All checks were successful
/ build (push) Successful in 5m3s
- Switched to enforce JSON as Content-Type for all incoming requests - Switched to properly respond with JSON on page not found or method not allowed - Renamed CORS_ALLOW_ORIGIN to CORS_ALLOW_ORIGINS - Added CORS_ALLOW_CREDENTIALS which defaults to true - Added CORS_EXPOSE_HEADERS which defaults to * - Overhauled package visibility for server module
This commit is contained in:
parent
1d79258670
commit
1fc3818d3c
24 changed files with 151 additions and 101 deletions
|
@ -3,9 +3,9 @@ on:
|
|||
tags:
|
||||
- '*'
|
||||
env:
|
||||
VERSION_MAJOR: 2
|
||||
VERSION_MAJOR: 3
|
||||
VERSION_MINOR: 0
|
||||
VERSION_PATCH: 2
|
||||
VERSION_PATCH: 0
|
||||
IMAGE_TAG: varakh/upda
|
||||
IMAGE_TAG_PRIVATE: git.myservermanager.com/varakh/upda
|
||||
FORGEJO_URL: https://git.myservermanager.com
|
||||
|
|
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -2,8 +2,17 @@
|
|||
|
||||
Changes adhere to [semantic versioning](https://semver.org).
|
||||
|
||||
## [2.0.2] - UNRELEASED
|
||||
## [3.0.0] - UNRELEASED
|
||||
|
||||
> This is a major version upgrade. Other versions are incompatible with this release.
|
||||
|
||||
* Added automatic detection of `GOMAXPROCS`
|
||||
* Switched to enforce JSON as `Content-Type` for all incoming requests
|
||||
* Switched to properly respond with JSON on page not found or method not allowed
|
||||
* Renamed `CORS_ALLOW_ORIGIN` to `CORS_ALLOW_ORIGINS`
|
||||
* Added `CORS_ALLOW_CREDENTIALS` which defaults to `true`
|
||||
* Added `CORS_EXPOSE_HEADERS` which defaults to `*`
|
||||
* Overhauled package visibility for server module
|
||||
* Updated dependencies
|
||||
* Updated OCI image base to alpine `3.20` with Go `1.22`
|
||||
|
||||
|
|
|
@ -110,6 +110,7 @@ platform, uploads produced artifacts to that release and publishes docker images
|
|||
built successfully:
|
||||
|
||||
* Adapt `constants_app.go` and change `Version` to the correct version number
|
||||
* Adapt `app.go` and change `version` to the correct version number (CLI)
|
||||
* Adapt `CHANGELOG.md` to reflect changes and ensure a date is properly set in the header, also add a reference link
|
||||
in footer (link to scm git tag source)
|
||||
* Adapt `api.yaml`: `version` attribute must reflect the to be released version
|
||||
|
@ -118,6 +119,7 @@ built successfully:
|
|||
After the release has been created, ensure to change the following settings for the _next development cycle_:
|
||||
|
||||
* Adapt `constants_app.go` and change `Version` to the _next_ version number
|
||||
* Adapt `app.go` and change `version` to the _next_ version number (CLI)
|
||||
* Adapt `CHANGELOG.md` and add an _UNRELEASED_ section
|
||||
* Adapt `api.yaml`: `version` attribute must reflect the _next_ version number
|
||||
* Adapt `env: VERSION_*` in `.forgejo/workflows/release.yaml` to _next_ version number
|
||||
|
|
|
@ -2,7 +2,7 @@ openapi: 3.0.3
|
|||
info:
|
||||
title: upda
|
||||
description: API specification
|
||||
version: 2.0.2
|
||||
version: 3.0.0
|
||||
externalDocs:
|
||||
description: Find out more about the project
|
||||
url: https://git.myservermanager.com/varakh/upda
|
||||
|
|
2
go.sum
2
go.sum
|
@ -201,8 +201,6 @@ github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lne
|
|||
github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY=
|
||||
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
|
||||
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
|
||||
github.com/redis/go-redis/v9 v9.5.2 h1:L0L3fcSNReTRGyZ6AqAEN0K56wYeYAwapBIhkvh0f3E=
|
||||
github.com/redis/go-redis/v9 v9.5.2/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
|
||||
github.com/redis/go-redis/v9 v9.5.3 h1:fOAp1/uJG+ZtcITgZOfYFmTKPE7n4Vclj1wZFgRciUU=
|
||||
github.com/redis/go-redis/v9 v9.5.3/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
|
||||
github.com/redis/rueidis v1.0.19 h1:s65oWtotzlIFN8eMPhyYwxlwLR1lUdhza2KtWprKYSo=
|
||||
|
|
|
@ -19,7 +19,7 @@ func errAbortWithValidatorPayload(c *gin.Context, err error) {
|
|||
errorMap[key] = txt
|
||||
}
|
||||
|
||||
resErr := newServiceError(IllegalArgument, fmt.Errorf("validation error: %v (%w)", util.ValuesString(errorMap), err))
|
||||
resErr := newServiceError(illegalArgument, fmt.Errorf("validation error: %v (%w)", util.ValuesString(errorMap), err))
|
||||
c.Header(headerContentType, headerContentTypeApplicationJson)
|
||||
_ = c.AbortWithError(http.StatusBadRequest, resErr)
|
||||
return
|
||||
|
@ -29,17 +29,19 @@ func errToHttpStatus(err error) int {
|
|||
var e *serviceError
|
||||
switch {
|
||||
case errors.As(err, &e):
|
||||
if e.Status == IllegalArgument {
|
||||
if e.Status == illegalArgument {
|
||||
return http.StatusBadRequest
|
||||
} else if e.Status == Unauthorized {
|
||||
} else if e.Status == unauthorized {
|
||||
return http.StatusUnauthorized
|
||||
} else if e.Status == Forbidden {
|
||||
} else if e.Status == forbidden {
|
||||
return http.StatusForbidden
|
||||
} else if e.Status == NotFound {
|
||||
} else if e.Status == notFound {
|
||||
return http.StatusNotFound
|
||||
} else if e.Status == Conflict {
|
||||
} else if e.Status == methodNotAllowed {
|
||||
return http.StatusMethodNotAllowed
|
||||
} else if e.Status == conflict {
|
||||
return http.StatusConflict
|
||||
} else if e.Status == General {
|
||||
} else if e.Status == general {
|
||||
return http.StatusInternalServerError
|
||||
}
|
||||
default:
|
||||
|
@ -57,7 +59,7 @@ func errCodeToStr(err error) string {
|
|||
return string(e.Status)
|
||||
}
|
||||
|
||||
return string(General)
|
||||
return string(general)
|
||||
}
|
||||
|
||||
func validatorErrorToText(e *validator.FieldError) (string, string) {
|
||||
|
|
|
@ -16,8 +16,8 @@ func newInfoHandler(a *appConfig) *infoHandler {
|
|||
|
||||
func (h *infoHandler) show(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, api.DataResponse{Data: gin.H{
|
||||
"name": Name,
|
||||
"version": Version,
|
||||
"name": name,
|
||||
"version": version,
|
||||
"timeZone": h.appConfig.timeZone,
|
||||
}})
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ func newWebhookInvocationHandler(i *webhookInvocationService, w *webhookService)
|
|||
}
|
||||
|
||||
func (h *webhookInvocationHandler) execute(c *gin.Context) {
|
||||
tokenHeader := c.GetHeader(HeaderWebhookToken)
|
||||
tokenHeader := c.GetHeader(headerWebhookToken)
|
||||
webhookId := c.Param("id")
|
||||
|
||||
var w *Webhook
|
||||
|
@ -52,7 +52,7 @@ func (h *webhookInvocationHandler) execute(c *gin.Context) {
|
|||
}
|
||||
break
|
||||
default:
|
||||
err = newServiceError(IllegalArgument, errors.New("no default handler for webhook type found"))
|
||||
err = newServiceError(illegalArgument, errors.New("no default handler for webhook type found"))
|
||||
_ = c.AbortWithError(errToHttpStatus(err), err)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -5,18 +5,43 @@ import (
|
|||
"git.myservermanager.com/varakh/upda/api"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func middlewareAppName() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
c.Header(HeaderAppName, Name)
|
||||
c.Header(headerAppName, name)
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
func middlewareGlobalNotFound() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
c.AbortWithStatusJSON(http.StatusNotFound, api.NewErrorResponseWithStatusAndMessage(string(notFound), "page not found"))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func middlewareGlobalMethodNotAllowed() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
c.AbortWithStatusJSON(http.StatusMethodNotAllowed, api.NewErrorResponseWithStatusAndMessage(string(methodNotAllowed), "method not allowed"))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func middlewareEnforceJsonContentType() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
if c.Request.Method != http.MethodOptions && !strings.HasPrefix(c.GetHeader(headerContentType), headerContentTypeApplicationJson) {
|
||||
c.AbortWithStatusJSON(http.StatusBadRequest, api.NewErrorResponseWithStatusAndMessage(string(illegalArgument), "content-type must be application/json"))
|
||||
return
|
||||
}
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
func middlewareAppVersion() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
c.Header(HeaderAppVersion, Version)
|
||||
c.Header(headerAppVersion, version)
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +72,7 @@ func middlewareAppErrorRecoveryHandler() gin.HandlerFunc {
|
|||
return func(c *gin.Context) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, api.NewErrorResponseWithStatusAndMessage(string(General), fmt.Sprintf("%s", err)))
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, api.NewErrorResponseWithStatusAndMessage(string(general), fmt.Sprintf("%s", err)))
|
||||
}
|
||||
}()
|
||||
c.Next()
|
||||
|
|
|
@ -100,17 +100,21 @@ func Start() {
|
|||
hh := newHealthHandler()
|
||||
authH := newAuthHandler()
|
||||
|
||||
router.Use(middlewareEnforceJsonContentType())
|
||||
router.Use(middlewareAppName())
|
||||
router.Use(middlewareAppVersion())
|
||||
router.Use(middlewareAppContentType())
|
||||
router.Use(middlewareErrorHandler())
|
||||
router.Use(middlewareAppErrorRecoveryHandler())
|
||||
router.NoRoute(middlewareGlobalNotFound())
|
||||
router.NoMethod(middlewareGlobalMethodNotAllowed())
|
||||
|
||||
router.Use(cors.New(cors.Config{
|
||||
AllowOrigins: env.serverConfig.corsAllowOrigin,
|
||||
AllowOrigins: env.serverConfig.corsAllowOrigins,
|
||||
AllowMethods: env.serverConfig.corsAllowMethods,
|
||||
AllowHeaders: env.serverConfig.corsAllowHeaders,
|
||||
AllowCredentials: true,
|
||||
AllowCredentials: env.serverConfig.corsAllowCredentials,
|
||||
ExposeHeaders: env.serverConfig.corsExposeHeaders,
|
||||
}))
|
||||
|
||||
apiPublicGroup := router.Group("/api/v1")
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package server
|
||||
|
||||
const (
|
||||
HeaderAppName = "X-App-Name"
|
||||
HeaderAppVersion = "X-App-Version"
|
||||
headerAppName = "X-App-Name"
|
||||
headerAppVersion = "X-App-Version"
|
||||
|
||||
HeaderWebhookToken = "X-Webhook-Token"
|
||||
headerWebhookToken = "X-Webhook-Token"
|
||||
|
||||
headerContentType = "Content-Type"
|
||||
headerContentTypeApplicationJson = "application/json"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package server
|
||||
|
||||
const (
|
||||
Name = "upda"
|
||||
Version = "2.0.2"
|
||||
name = "upda"
|
||||
version = "3.0.0"
|
||||
)
|
||||
|
|
|
@ -35,12 +35,16 @@ const (
|
|||
serverTlsEnabledDefault = "false"
|
||||
serverTimeoutDefault = "1s"
|
||||
|
||||
envCorsAllowOrigin = "CORS_ALLOW_ORIGIN"
|
||||
envCorsAllowOrigins = "CORS_ALLOW_ORIGINS"
|
||||
envCorsAllowMethods = "CORS_ALLOW_METHODS"
|
||||
envCorsAllowHeaders = "CORS_ALLOW_HEADERS"
|
||||
corsAllowOriginDefault = "*"
|
||||
envCorsAllowCredentials = "CORS_ALLOW_CREDENTIALS"
|
||||
envCorsExposeHeaders = "CORS_EXPOSE_HEADERS"
|
||||
corsAllowOriginsDefault = "*"
|
||||
corsAllowMethodsDefault = "HEAD, GET, POST, PUT, PATCH, DELETE, OPTIONS"
|
||||
corsAllowHeadersDefault = "Authorization, Content-Type"
|
||||
corsAllowCredentialsDefault = "true"
|
||||
corsExposeHeadersDefault = "*"
|
||||
|
||||
dbTypeSqlite = "sqlite"
|
||||
dbTypePostgres = "postgres"
|
||||
|
|
|
@ -33,9 +33,11 @@ type serverConfig struct {
|
|||
tlsCertPath string
|
||||
tlsKeyPath string
|
||||
timeout time.Duration
|
||||
corsAllowOrigin []string
|
||||
corsAllowCredentials bool
|
||||
corsAllowOrigins []string
|
||||
corsAllowMethods []string
|
||||
corsAllowHeaders []string
|
||||
corsExposeHeaders []string
|
||||
}
|
||||
|
||||
type authConfig struct {
|
||||
|
@ -209,7 +211,9 @@ func bootstrapEnvironment() *Environment {
|
|||
tlsEnabled: serverTlsEnabled,
|
||||
tlsCertPath: os.Getenv(envServerTlsCertPath),
|
||||
tlsKeyPath: os.Getenv(envServerTlsKeyPath),
|
||||
corsAllowOrigin: []string{os.Getenv(envCorsAllowOrigin)},
|
||||
corsAllowCredentials: os.Getenv(envCorsAllowCredentials) == "true",
|
||||
corsExposeHeaders: []string{os.Getenv(envCorsExposeHeaders)},
|
||||
corsAllowOrigins: []string{os.Getenv(envCorsAllowOrigins)},
|
||||
corsAllowMethods: []string{os.Getenv(envCorsAllowMethods)},
|
||||
corsAllowHeaders: []string{os.Getenv(envCorsAllowHeaders)},
|
||||
}
|
||||
|
@ -338,7 +342,7 @@ func bootstrapEnvironment() *Environment {
|
|||
if os.Getenv(envDbType) == dbTypeSqlite {
|
||||
if os.Getenv(envDbSqliteFile) == "" {
|
||||
var defaultDbFile string
|
||||
if defaultDbFile, err = xdg.DataFile(Name + "/" + dbTypeSqliteDbNameDefault); err != nil {
|
||||
if defaultDbFile, err = xdg.DataFile(name + "/" + dbTypeSqliteDbNameDefault); err != nil {
|
||||
zap.L().Sugar().Fatalf("Database file '%s' could not be created. Reason: %v", defaultDbFile, err)
|
||||
}
|
||||
setEnvKeyDefault(envDbSqliteFile, defaultDbFile)
|
||||
|
@ -464,9 +468,11 @@ func bootstrapFromEnvironmentAndValidate() {
|
|||
setEnvKeyDefault(envServerPort, serverPortDefault)
|
||||
setEnvKeyDefault(envServerListen, serverListenDefault)
|
||||
setEnvKeyDefault(envServerTlsEnabled, serverTlsEnabledDefault)
|
||||
setEnvKeyDefault(envCorsAllowOrigin, corsAllowOriginDefault)
|
||||
setEnvKeyDefault(envCorsAllowOrigins, corsAllowOriginsDefault)
|
||||
setEnvKeyDefault(envCorsAllowMethods, corsAllowMethodsDefault)
|
||||
setEnvKeyDefault(envCorsAllowHeaders, corsAllowHeadersDefault)
|
||||
setEnvKeyDefault(envCorsAllowCredentials, corsAllowCredentialsDefault)
|
||||
setEnvKeyDefault(envCorsExposeHeaders, corsExposeHeadersDefault)
|
||||
setEnvKeyDefault(envServerTimeout, serverTimeoutDefault)
|
||||
}
|
||||
|
||||
|
|
|
@ -6,43 +6,44 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
errorValidationNotEmpty = newServiceError(IllegalArgument, errors.New("assert: empty values are not allowed"))
|
||||
errorValidationNotBlank = newServiceError(IllegalArgument, errors.New("assert: blank values are not allowed"))
|
||||
errorValidationPageGreaterZero = newServiceError(IllegalArgument, errors.New("assert: page has to be greater 0"))
|
||||
errorValidationPageSizeGreaterZero = newServiceError(IllegalArgument, errors.New("assert: pageSize has to be greater 0"))
|
||||
errorValidationLimitGreaterZero = newServiceError(IllegalArgument, errors.New("assert: limit has to be greater 0"))
|
||||
errorValidationSizeGreaterZero = newServiceError(IllegalArgument, errors.New("assert: size has to be greater 0"))
|
||||
errorValidationMaxRetriesGreaterZero = newServiceError(IllegalArgument, errors.New("assert: max retries has to be greater 0"))
|
||||
errorValidationNotEmpty = newServiceError(illegalArgument, errors.New("assert: empty values are not allowed"))
|
||||
errorValidationNotBlank = newServiceError(illegalArgument, errors.New("assert: blank values are not allowed"))
|
||||
errorValidationPageGreaterZero = newServiceError(illegalArgument, errors.New("assert: page has to be greater 0"))
|
||||
errorValidationPageSizeGreaterZero = newServiceError(illegalArgument, errors.New("assert: pageSize has to be greater 0"))
|
||||
errorValidationLimitGreaterZero = newServiceError(illegalArgument, errors.New("assert: limit has to be greater 0"))
|
||||
errorValidationSizeGreaterZero = newServiceError(illegalArgument, errors.New("assert: size has to be greater 0"))
|
||||
errorValidationMaxRetriesGreaterZero = newServiceError(illegalArgument, errors.New("assert: max retries has to be greater 0"))
|
||||
|
||||
errorResourceNotFound = newServiceError(NotFound, errors.New("resource not found"))
|
||||
errorResourceAccessDenied = newServiceError(Forbidden, errors.New("resource access denied"))
|
||||
errorResourceNotFound = newServiceError(notFound, errors.New("resource not found"))
|
||||
errorResourceAccessDenied = newServiceError(forbidden, errors.New("resource access denied"))
|
||||
|
||||
errorDatabaseRowsExpected = newServiceDatabaseError(errors.New("action failed, expected affected rows, but got none"))
|
||||
)
|
||||
|
||||
type ErrorCode string
|
||||
type errorCode string
|
||||
|
||||
const (
|
||||
IllegalArgument ErrorCode = "IllegalArgument"
|
||||
Unauthorized ErrorCode = "Unauthorized"
|
||||
Forbidden ErrorCode = "Forbidden"
|
||||
NotFound ErrorCode = "NotFound"
|
||||
Conflict ErrorCode = "Conflict"
|
||||
General ErrorCode = "General"
|
||||
illegalArgument errorCode = "IllegalArgument"
|
||||
unauthorized errorCode = "Unauthorized"
|
||||
forbidden errorCode = "Forbidden"
|
||||
notFound errorCode = "NotFound"
|
||||
methodNotAllowed errorCode = "MethodNotAllowed"
|
||||
conflict errorCode = "Conflict"
|
||||
general errorCode = "General"
|
||||
)
|
||||
|
||||
// newServiceError returns an error that formats as the given text and aligns with builtin error
|
||||
func newServiceError(status ErrorCode, err error) error {
|
||||
func newServiceError(status errorCode, err error) error {
|
||||
return &serviceError{status, fmt.Errorf("service error (%v): %w", status, err)}
|
||||
}
|
||||
|
||||
// newServiceDatabaseError returns an error that formats as the given text and aligns with builtin error
|
||||
func newServiceDatabaseError(error error) error {
|
||||
return newServiceError(General, fmt.Errorf("database error: %w", error))
|
||||
return newServiceError(general, fmt.Errorf("database error: %w", error))
|
||||
}
|
||||
|
||||
type serviceError struct {
|
||||
Status ErrorCode
|
||||
Status errorCode
|
||||
Cause error
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type WebhookRepository interface {
|
||||
type webhookRepository interface {
|
||||
paginate(page int, pageSize int, orderBy string, order string) ([]*Webhook, error)
|
||||
count() (int64, error)
|
||||
find(id string) (*Webhook, error)
|
||||
|
|
|
@ -39,7 +39,7 @@ func (s *actionService) create(label string, t api.ActionType, matchEvent *strin
|
|||
}
|
||||
|
||||
if isValid, validationErr := s.isValidPayload(t, payload); !isValid {
|
||||
return nil, newServiceError(IllegalArgument, validationErr)
|
||||
return nil, newServiceError(illegalArgument, validationErr)
|
||||
}
|
||||
|
||||
var err error
|
||||
|
@ -197,7 +197,7 @@ func (s *actionService) updateTypeAndPayload(id string, t api.ActionType, payloa
|
|||
}
|
||||
|
||||
if isValid, validationErr := s.isValidPayload(t, payload); !isValid {
|
||||
return nil, newServiceError(IllegalArgument, validationErr)
|
||||
return nil, newServiceError(illegalArgument, validationErr)
|
||||
}
|
||||
|
||||
if e, err = s.repo.updateTypeAndPayload(id, t, payload); err != nil {
|
||||
|
|
|
@ -28,7 +28,7 @@ func newActionInvocationService(r ActionInvocationRepository, a *actionService,
|
|||
|
||||
func (s *actionInvocationService) enqueue(batchSize int) error {
|
||||
if batchSize <= 0 {
|
||||
return newServiceError(General, errors.New("cannot enqueue actions from events with invalid configured batch size"))
|
||||
return newServiceError(general, errors.New("cannot enqueue actions from events with invalid configured batch size"))
|
||||
}
|
||||
|
||||
var events []*Event
|
||||
|
@ -54,7 +54,7 @@ func (s *actionInvocationService) enqueue(batchSize int) error {
|
|||
|
||||
func (s *actionInvocationService) enqueueFromEvent(event *Event, actions []*Action) error {
|
||||
if event == nil || actions == nil {
|
||||
return newServiceError(IllegalArgument, errorValidationNotEmpty)
|
||||
return newServiceError(illegalArgument, errorValidationNotEmpty)
|
||||
}
|
||||
|
||||
var err error
|
||||
|
@ -99,10 +99,10 @@ func (s *actionInvocationService) enqueueFromEvent(event *Event, actions []*Acti
|
|||
|
||||
func (s *actionInvocationService) invoke(batchSize int, maxRetries int) error {
|
||||
if batchSize <= 0 {
|
||||
return newServiceError(General, errors.New("cannot invoke actions with invalid configured batch size"))
|
||||
return newServiceError(general, errors.New("cannot invoke actions with invalid configured batch size"))
|
||||
}
|
||||
if maxRetries <= 0 {
|
||||
return newServiceError(General, errors.New("cannot invoke actions with invalid configured max retries"))
|
||||
return newServiceError(general, errors.New("cannot invoke actions with invalid configured max retries"))
|
||||
}
|
||||
|
||||
var err error
|
||||
|
@ -198,14 +198,14 @@ func (s *actionInvocationService) execute(action *Action, eventPayloadInfo *even
|
|||
var bytes []byte
|
||||
|
||||
if bytes, err = action.Payload.MarshalJSON(); err != nil {
|
||||
return newServiceError(General, err)
|
||||
return newServiceError(general, err)
|
||||
}
|
||||
|
||||
switch action.Type {
|
||||
case api.ActionTypeShoutrrr.Value():
|
||||
var payload actionPayloadShoutrrrDto
|
||||
if payload, err = util.UnmarshalGenericJSON[actionPayloadShoutrrrDto](bytes); err != nil {
|
||||
return newServiceError(General, err)
|
||||
return newServiceError(general, err)
|
||||
}
|
||||
|
||||
body := s.replaceVars(payload.Body, eventPayloadInfo)
|
||||
|
@ -220,7 +220,7 @@ func (s *actionInvocationService) execute(action *Action, eventPayloadInfo *even
|
|||
}
|
||||
break
|
||||
default:
|
||||
return newServiceError(General, errors.New("no matching action type found for invocation"))
|
||||
return newServiceError(general, errors.New("no matching action type found for invocation"))
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -194,41 +194,41 @@ func (s *eventService) extractPayloadInfo(event *Event) (*eventPayloadInformatio
|
|||
var bytes []byte
|
||||
|
||||
if bytes, err = event.Payload.MarshalJSON(); err != nil {
|
||||
return nil, newServiceError(General, err)
|
||||
return nil, newServiceError(general, err)
|
||||
}
|
||||
|
||||
switch event.Name {
|
||||
case api.EventNameUpdateCreated.Value():
|
||||
var p api.EventPayloadUpdateCreatedDto
|
||||
if p, err = util.UnmarshalGenericJSON[api.EventPayloadUpdateCreatedDto](bytes); err != nil {
|
||||
return nil, newServiceError(General, err)
|
||||
return nil, newServiceError(general, err)
|
||||
}
|
||||
return &eventPayloadInformationDto{Host: p.Host, Application: p.Application, Provider: p.Provider, Version: p.Version, State: p.State}, nil
|
||||
case api.EventNameUpdateDeleted.Value():
|
||||
var p api.EventPayloadUpdateDeletedDto
|
||||
if p, err = util.UnmarshalGenericJSON[api.EventPayloadUpdateDeletedDto](bytes); err != nil {
|
||||
return nil, newServiceError(General, err)
|
||||
return nil, newServiceError(general, err)
|
||||
}
|
||||
return &eventPayloadInformationDto{Host: p.Host, Application: p.Application, Provider: p.Provider, Version: p.Version, State: p.State}, nil
|
||||
case api.EventNameUpdateUpdatedState.Value():
|
||||
var p api.EventPayloadUpdateUpdatedDto
|
||||
if p, err = util.UnmarshalGenericJSON[api.EventPayloadUpdateUpdatedDto](bytes); err != nil {
|
||||
return nil, newServiceError(General, err)
|
||||
return nil, newServiceError(general, err)
|
||||
}
|
||||
return &eventPayloadInformationDto{Host: p.Host, Application: p.Application, Provider: p.Provider, Version: p.Version, State: p.State}, nil
|
||||
case api.EventNameUpdateUpdatedVersion.Value():
|
||||
var p api.EventPayloadUpdateUpdatedDto
|
||||
if p, err = util.UnmarshalGenericJSON[api.EventPayloadUpdateUpdatedDto](bytes); err != nil {
|
||||
return nil, newServiceError(General, err)
|
||||
return nil, newServiceError(general, err)
|
||||
}
|
||||
return &eventPayloadInformationDto{Host: p.Host, Application: p.Application, Provider: p.Provider, Version: p.Version, State: p.State}, nil
|
||||
case api.EventNameUpdateUpdated.Value():
|
||||
var p api.EventPayloadUpdateUpdatedDto
|
||||
if p, err = util.UnmarshalGenericJSON[api.EventPayloadUpdateUpdatedDto](bytes); err != nil {
|
||||
return nil, newServiceError(General, err)
|
||||
return nil, newServiceError(general, err)
|
||||
}
|
||||
return &eventPayloadInformationDto{Host: p.Host, Application: p.Application, Provider: p.Provider, Version: p.Version, State: p.State}, nil
|
||||
}
|
||||
|
||||
return nil, newServiceError(General, errors.New("no matching event found"))
|
||||
return nil, newServiceError(general, errors.New("no matching event found"))
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ type lockMemService struct {
|
|||
}
|
||||
|
||||
var (
|
||||
errLockMemNotReleased = newServiceError(Conflict, errors.New("lock service: could not release lock"))
|
||||
errLockMemNotReleased = newServiceError(conflict, errors.New("lock service: could not release lock"))
|
||||
)
|
||||
|
||||
func newLockMemService() lockService {
|
||||
|
|
|
@ -15,8 +15,8 @@ type lockRedisService struct {
|
|||
}
|
||||
|
||||
var (
|
||||
errLockRedisNotObtained = newServiceError(Conflict, errors.New("lock service: could not obtain lock"))
|
||||
errLockRedisNotReleased = newServiceError(Conflict, errors.New("lock service: could not release lock"))
|
||||
errLockRedisNotObtained = newServiceError(conflict, errors.New("lock service: could not obtain lock"))
|
||||
errLockRedisNotReleased = newServiceError(conflict, errors.New("lock service: could not release lock"))
|
||||
)
|
||||
|
||||
func newLockRedisService(lc *lockConfig) (lockService, error) {
|
||||
|
|
|
@ -18,7 +18,7 @@ func newPrometheusService(r *gin.Engine, c *prometheusConfig) *prometheusService
|
|||
if c.secureTokenEnabled {
|
||||
p = ginprom.New(
|
||||
ginprom.Engine(r),
|
||||
ginprom.Namespace(Name),
|
||||
ginprom.Namespace(name),
|
||||
ginprom.Subsystem(""),
|
||||
ginprom.Path(c.path),
|
||||
ginprom.Ignore(c.path),
|
||||
|
@ -27,7 +27,7 @@ func newPrometheusService(r *gin.Engine, c *prometheusConfig) *prometheusService
|
|||
} else {
|
||||
p = ginprom.New(
|
||||
ginprom.Engine(r),
|
||||
ginprom.Namespace(Name),
|
||||
ginprom.Namespace(name),
|
||||
ginprom.Subsystem(""),
|
||||
ginprom.Ignore(c.path),
|
||||
ginprom.Path(c.path),
|
||||
|
|
|
@ -8,11 +8,11 @@ import (
|
|||
)
|
||||
|
||||
type webhookService struct {
|
||||
repo WebhookRepository
|
||||
repo webhookRepository
|
||||
webhookConfig *webhookConfig
|
||||
}
|
||||
|
||||
func newWebhookService(r WebhookRepository, c *webhookConfig) *webhookService {
|
||||
func newWebhookService(r webhookRepository, c *webhookConfig) *webhookService {
|
||||
return &webhookService{
|
||||
repo: r,
|
||||
webhookConfig: c,
|
||||
|
@ -42,7 +42,7 @@ func (s *webhookService) create(label string, t api.WebhookType, ignoreHost bool
|
|||
var token string
|
||||
|
||||
if token, err = util.GenerateSecureRandomString(s.webhookConfig.tokenLength); err != nil {
|
||||
return nil, newServiceError(General, fmt.Errorf("token generation failed: %w", err))
|
||||
return nil, newServiceError(general, fmt.Errorf("token generation failed: %w", err))
|
||||
}
|
||||
|
||||
var e *Webhook
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"git.myservermanager.com/varakh/upda/api"
|
||||
"git.myservermanager.com/varakh/upda/server"
|
||||
"git.myservermanager.com/varakh/upda/util"
|
||||
"github.com/go-resty/resty/v2"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
@ -17,7 +16,7 @@ import (
|
|||
const (
|
||||
name = "upda-cli"
|
||||
desc = "a commandline helper for upda"
|
||||
version = server.Version
|
||||
version = "3.0.0"
|
||||
|
||||
envServerUrl = "UPDA_SERVER_URL"
|
||||
envUser = "UPDA_USER"
|
||||
|
@ -264,7 +263,7 @@ func webhookSend(cCtx *cli.Context) error {
|
|||
client.SetDisableWarn(true)
|
||||
res, err := client.R().
|
||||
SetHeader("Content-Type", "application/json").
|
||||
SetHeader(server.HeaderWebhookToken, cCtx.String(flagWebhookToken)).
|
||||
SetHeader("X-Webhook-Token", cCtx.String(flagWebhookToken)).
|
||||
SetBody(payloadArg).
|
||||
SetError(&errorRes).
|
||||
Post(url)
|
||||
|
|
Loading…
Reference in a new issue