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

- 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:
Varakh 2024-06-10 20:03:25 +02:00
parent 1d79258670
commit 1fc3818d3c
24 changed files with 151 additions and 101 deletions

View file

@ -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

View file

@ -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`

View file

@ -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

View file

@ -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
View file

@ -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=

View file

@ -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) {

View file

@ -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,
}})
}

View file

@ -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
}

View file

@ -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()

View file

@ -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")

View file

@ -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"

View file

@ -1,6 +1,6 @@
package server
const (
Name = "upda"
Version = "2.0.2"
name = "upda"
version = "3.0.0"
)

View file

@ -35,12 +35,16 @@ const (
serverTlsEnabledDefault = "false"
serverTimeoutDefault = "1s"
envCorsAllowOrigin = "CORS_ALLOW_ORIGIN"
envCorsAllowMethods = "CORS_ALLOW_METHODS"
envCorsAllowHeaders = "CORS_ALLOW_HEADERS"
corsAllowOriginDefault = "*"
corsAllowMethodsDefault = "HEAD, GET, POST, PUT, PATCH, DELETE, OPTIONS"
corsAllowHeadersDefault = "Authorization, Content-Type"
envCorsAllowOrigins = "CORS_ALLOW_ORIGINS"
envCorsAllowMethods = "CORS_ALLOW_METHODS"
envCorsAllowHeaders = "CORS_ALLOW_HEADERS"
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"

View file

@ -27,15 +27,17 @@ type appConfig struct {
}
type serverConfig struct {
port int
listen string
tlsEnabled bool
tlsCertPath string
tlsKeyPath string
timeout time.Duration
corsAllowOrigin []string
corsAllowMethods []string
corsAllowHeaders []string
port int
listen string
tlsEnabled bool
tlsCertPath string
tlsKeyPath string
timeout time.Duration
corsAllowCredentials bool
corsAllowOrigins []string
corsAllowMethods []string
corsAllowHeaders []string
corsExposeHeaders []string
}
type authConfig struct {
@ -203,15 +205,17 @@ func bootstrapEnvironment() *Environment {
}
sc = &serverConfig{
port: serverPort,
timeout: serverTimeout,
listen: os.Getenv(envServerListen),
tlsEnabled: serverTlsEnabled,
tlsCertPath: os.Getenv(envServerTlsCertPath),
tlsKeyPath: os.Getenv(envServerTlsKeyPath),
corsAllowOrigin: []string{os.Getenv(envCorsAllowOrigin)},
corsAllowMethods: []string{os.Getenv(envCorsAllowMethods)},
corsAllowHeaders: []string{os.Getenv(envCorsAllowHeaders)},
port: serverPort,
timeout: serverTimeout,
listen: os.Getenv(envServerListen),
tlsEnabled: serverTlsEnabled,
tlsCertPath: os.Getenv(envServerTlsCertPath),
tlsKeyPath: os.Getenv(envServerTlsKeyPath),
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)},
}
authMode := os.Getenv(envAuthMode)
@ -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)
}

View file

@ -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
}

View file

@ -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)

View file

@ -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 {

View file

@ -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

View file

@ -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"))
}

View file

@ -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 {

View file

@ -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) {

View file

@ -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),

View file

@ -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

View file

@ -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)