Compare commits
19 Commits
change_mod
...
e01728b9a0
| Author | SHA1 | Date | |
|---|---|---|---|
| e01728b9a0 | |||
|
465eb99bae
|
|||
|
2a411136b7
|
|||
|
fc8b723114
|
|||
|
180a5c2a90
|
|||
|
8ca762cb1f
|
|||
|
5a8b53b49d
|
|||
|
3fc545f067
|
|||
|
7be0c7c6d3
|
|||
|
7bc4ce8c96
|
|||
|
7e9653606e
|
|||
|
e7592e8737
|
|||
|
334c0c1480
|
|||
|
abc87abe88
|
|||
|
1367783e8a
|
|||
|
|
51e48dd842 | ||
|
3a3580b6ed
|
|||
|
f5d780fb1b
|
|||
|
a4050c28dc
|
4
.env
4
.env
@@ -20,6 +20,6 @@ RABBIT_PASSWORD=user
|
|||||||
RABBIT_HOST=localhost
|
RABBIT_HOST=localhost
|
||||||
RABBIT_PORT=5672
|
RABBIT_PORT=5672
|
||||||
|
|
||||||
JWT_SIGN_PUBLIC_KEY_PATH=_example/keys/jwt_public_key.pem
|
JWT_SIGN_PUBLIC_KEY_PATH=_example/keys/jwt_public.pem
|
||||||
JWT_SIGN_PRIVATE_KEY_PATH=_example/keys/jwt_private_key.pem
|
JWT_SIGN_PRIVATE_KEY_PATH=_example/keys/jwt_private.pem
|
||||||
JWT_TRUSTED_HOSTS=
|
JWT_TRUSTED_HOSTS=
|
||||||
26
.github/workflows/golang-lint.yml
vendored
Normal file
26
.github/workflows/golang-lint.yml
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
name: Lint Golang
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- dev
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
pull-requests: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
golangci:
|
||||||
|
name: lint
|
||||||
|
runs-on: self-hosted
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v5
|
||||||
|
- uses: actions/setup-go@v6
|
||||||
|
with:
|
||||||
|
go-version: 1.25.0
|
||||||
|
- name: golangci-lint
|
||||||
|
uses: golangci/golangci-lint-action@v8
|
||||||
|
with:
|
||||||
|
version: v2.5.0
|
||||||
|
args: '--config=${{ github.workspace }}/.golangci.yml'
|
||||||
9
.github/workflows/release.yml
vendored
9
.github/workflows/release.yml
vendored
@@ -3,14 +3,13 @@ name: Release
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- dev
|
|
||||||
- master
|
- master
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
goreleaser:
|
release:
|
||||||
runs-on: self-hosted
|
runs-on: self-hosted
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
@@ -21,10 +20,8 @@ jobs:
|
|||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: '^1.25'
|
go-version: '^1.25'
|
||||||
- name: Set up Node
|
- name: Install go release
|
||||||
uses: actions/setup-node@v6
|
run: go install github.com/goreleaser/goreleaser/v2@latest
|
||||||
with:
|
|
||||||
node-version: 22.18
|
|
||||||
- name: Release
|
- name: Release
|
||||||
run: |
|
run: |
|
||||||
yarn install
|
yarn install
|
||||||
|
|||||||
27
.golangci.yml
Normal file
27
.golangci.yml
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
version: "2"
|
||||||
|
|
||||||
|
run:
|
||||||
|
relative-path-mode: gomod
|
||||||
|
timeout: 5m
|
||||||
|
|
||||||
|
linters:
|
||||||
|
settings:
|
||||||
|
dupl:
|
||||||
|
threshold: 100
|
||||||
|
enable:
|
||||||
|
- errcheck
|
||||||
|
- govet
|
||||||
|
- ineffassign
|
||||||
|
- staticcheck
|
||||||
|
- unused
|
||||||
|
- errname
|
||||||
|
- dupl
|
||||||
|
- decorder
|
||||||
|
- cyclop
|
||||||
|
- funlen
|
||||||
|
- lll
|
||||||
|
- nestif
|
||||||
|
- nlreturn
|
||||||
|
- prealloc
|
||||||
|
- tagalign
|
||||||
|
- whitespace
|
||||||
13
CHANGELOG.md
Normal file
13
CHANGELOG.md
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# [1.2.0](https://git.ostiwe.com/ostiwe-com/status/compare/v1.1.1...v1.2.0) (2025-10-28)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* Recreate closeNotify channel on recreate rabbit connection ([f5d780f](https://git.ostiwe.com/ostiwe-com/status/commit/f5d780fb1b682aa1f6f29b9297ed1e3e22ad15e1))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* Added ID field to PublicService DTO, update fields in Service model, fix CalculateUptimePercent method, transform services to Public services in goroutines ([a4050c2](https://git.ostiwe.com/ostiwe-com/status/commit/a4050c28dc9cfb2edcc3716b91af4a8ba146637b))
|
||||||
|
* **ci:** Update release config ([dc5c363](https://git.ostiwe.com/ostiwe-com/status/commit/dc5c3635831dffd5e0e9da25e8e69b9ebf29663c))
|
||||||
|
* **ci:** Update release config ([64121d5](https://git.ostiwe.com/ostiwe-com/status/commit/64121d56c7def468b880a30cd0c1f86a25fd3398))
|
||||||
28
_example/keys/jwt_private.pem
Normal file
28
_example/keys/jwt_private.pem
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC5Pp5QB2glt2gs
|
||||||
|
l2A7I9h2ManWeoe/83TOethZGyC9ujZTgA3kO8M3bs7reEYuwEQvMijx3Qvf/ORp
|
||||||
|
cMag+VmNPKBWCpdzY3PANdQP546JqUjIVCNyPr2+z6N+ColSqAiuB159F7g6Lfei
|
||||||
|
5TR25Eu2tadvBX+oMCLrziIPwOuac4ZybyvEs5uPGN/uyQbN3d2bxa/07YkdMqDh
|
||||||
|
alVQZJ95r9vJj6wycxn1cslbGDXYDyXx7aC1x/8dLcewYb79WoBdTFHaa+2Kpv2q
|
||||||
|
e2LRgrAIk1JuHKNar5PjMoegsQ10WUeKl92afEL1MxSFliQbNyND91yNMTGkM+e2
|
||||||
|
ERUyZHZpAgMBAAECggEAAgUaZ5O/GVsvv/26E0cDqR1HRXMSWB/c3BQHmCglMiBt
|
||||||
|
z3kH3b9flHMJP1TRShj3XV7iBqojAyMgL/ymc9KoPPOmaW3F40CYPmYv3OkI2zws
|
||||||
|
8p9FQC2KNuKPfTQ69Vtm9dPXfkx0CjFeYAi5CttYLoK6U8n274Pv24ukwDB5uTZI
|
||||||
|
wXcAsWeiB7UD4gdIU5JwFr1Awx7oWgxT979XC+X/jIKDHfpRSmF+VDz8Mkoi4gLK
|
||||||
|
YIqq3hXeMm9DKHuqxjH193G3oh06/yYZlS2durVWaQsu98WbkhZKIlV9Mgl+aPm/
|
||||||
|
NgjG3QmcbTaPTrf+wrepiAr31NSTkOn5G07mFCMeMQKBgQDvxkRmuQ25F+8QfsFg
|
||||||
|
C0hIW7UF8V7y5bsIguzD+RymsfO8LaIcXPbZA+XRLvmzAxJuG4TTBd9Hk9VueEQF
|
||||||
|
dTXVjpjSSx2zWb1UkGA2TE2aQO+yhJ6gbhZ/OOJb3Kxp5imXRq/EgT6f5APnY31E
|
||||||
|
ysnALFSx+9BuAOo4gwvao+/30QKBgQDFx7P1wMuoCrFpr0mplqa4bXuM6H6cUonn
|
||||||
|
a9vPrVRwbRSx8xc+iMRoFjOR2BWsMxhAm2t6WleT1DrOXKxjHQmyf6VGknGydxdX
|
||||||
|
al4yLjkeD8nzfDR/EhVDMN+4ld990WNAZZWm+rX4Y4mISt8o8Z0Tq8N9R3s4g4aT
|
||||||
|
eFYBXHTTGQKBgCyVdz6Khky2cJNmnlpXfrdFpiFWwkr0AJUSkyfVeEheqm2BJrWT
|
||||||
|
a6rqmJ8O1ws8NP8YSthaLSxIBtWlszA4nSv6edwQb5NbymKg/eLayUs3a9qL4lr+
|
||||||
|
XVyGnUBrhfui+nTQhfpJ9fURFtC9pRtXgbAkDhOSOS1bKjIb2+ZpuUMhAoGBALGZ
|
||||||
|
jK4nvDlfsMR4VStmTrvaBFIaDGePbqpTHoW03dg++5B3++15nvTgytoyMfP5xdNu
|
||||||
|
POsX6QCkWVIpwdsWnjidiup+Yn6hlmI27/Mbssqd3vk4FWPt9w3o+1yjqJcwyXFw
|
||||||
|
Rxw0kedEaqHqqc34eNbLLLZ409uBr/0I2CJMxdMxAoGAYVED4ltIlK8Z9fKaoNuG
|
||||||
|
eC6FBEDsN2RnXZg2qyE2yEw9DwWun6e42CO/mDXfRB2jOFxSVXP27w+6G9dsN+QG
|
||||||
|
U9Gv+AZY1Kr29qvHHheA6RhyeGMSrsfBj7U2TmUzj2xwvjoENsxBj1rDoCgIK8hB
|
||||||
|
o/nsWmEy9tf6xs8KTjztHZw=
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
-----BEGIN PRIVATE KEY-----
|
|
||||||
MC4CAQAwBQYDK2VwBCIEIErwGenQ53CBtItiMuRBUgrn5/l1uYW6RiAoE+9IFqtj
|
|
||||||
-----END PRIVATE KEY-----
|
|
||||||
9
_example/keys/jwt_public.pem
Normal file
9
_example/keys/jwt_public.pem
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
-----BEGIN PUBLIC KEY-----
|
||||||
|
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuT6eUAdoJbdoLJdgOyPY
|
||||||
|
djGp1nqHv/N0znrYWRsgvbo2U4AN5DvDN27O63hGLsBELzIo8d0L3/zkaXDGoPlZ
|
||||||
|
jTygVgqXc2NzwDXUD+eOialIyFQjcj69vs+jfgqJUqgIrgdefRe4Oi33ouU0duRL
|
||||||
|
trWnbwV/qDAi684iD8DrmnOGcm8rxLObjxjf7skGzd3dm8Wv9O2JHTKg4WpVUGSf
|
||||||
|
ea/byY+sMnMZ9XLJWxg12A8l8e2gtcf/HS3HsGG+/VqAXUxR2mvtiqb9qnti0YKw
|
||||||
|
CJNSbhyjWq+T4zKHoLENdFlHipfdmnxC9TMUhZYkGzcjQ/dcjTExpDPnthEVMmR2
|
||||||
|
aQIDAQAB
|
||||||
|
-----END PUBLIC KEY-----
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
-----BEGIN PUBLIC KEY-----
|
|
||||||
MCowBQYDK2VwAyEANttz9RhiE7FXL4A/PX3GfgxhWxSwKy5zhxrNHXifszs=
|
|
||||||
-----END PUBLIC KEY-----
|
|
||||||
@@ -12,14 +12,6 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- "5444:5432"
|
- "5444:5432"
|
||||||
|
|
||||||
rabbitmq:
|
|
||||||
image: rabbitmq:4.1.2-management
|
|
||||||
environment:
|
|
||||||
RABBITMQ_DEFAULT_USER: user
|
|
||||||
RABBITMQ_DEFAULT_PASS: user
|
|
||||||
ports:
|
|
||||||
- "5672:5672"
|
|
||||||
- "15672:15672"
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
database_postgres:
|
database_postgres:
|
||||||
@@ -3,8 +3,9 @@ package dto
|
|||||||
import "git.ostiwe.com/ostiwe-com/status/model"
|
import "git.ostiwe.com/ostiwe-com/status/model"
|
||||||
|
|
||||||
type PublicService struct {
|
type PublicService struct {
|
||||||
|
ID int `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Description string `json:"description"`
|
Description *string `json:"description"`
|
||||||
Statuses []model.Status `json:"statuses"`
|
Statuses []model.Status `json:"statuses"`
|
||||||
Uptime float64 `json:"uptime"`
|
Uptime float64 `json:"uptime"`
|
||||||
}
|
}
|
||||||
|
|||||||
65
go.mod
65
go.mod
@@ -4,32 +4,39 @@ go 1.25.0
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/alexflint/go-arg v1.6.0
|
github.com/alexflint/go-arg v1.6.0
|
||||||
github.com/go-andiamo/chioas v1.16.4
|
github.com/appleboy/gin-jwt/v3 v3.2.0
|
||||||
github.com/go-chi/chi/v5 v5.2.2
|
github.com/gin-gonic/gin v1.11.0
|
||||||
github.com/go-chi/jwtauth/v5 v5.3.3
|
github.com/go-andiamo/chioas v1.19.0
|
||||||
github.com/go-chi/render v1.0.3
|
|
||||||
github.com/go-co-op/gocron/v2 v2.17.0
|
github.com/go-co-op/gocron/v2 v2.17.0
|
||||||
github.com/golang-jwt/jwt/v5 v5.3.0
|
github.com/golang-jwt/jwt/v5 v5.3.0
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/joho/godotenv v1.5.1
|
github.com/joho/godotenv v1.5.1
|
||||||
github.com/lestrrat-go/jwx/v2 v2.1.6
|
github.com/pressly/goose/v3 v3.26.0
|
||||||
github.com/pressly/goose/v3 v3.24.3
|
|
||||||
github.com/rabbitmq/amqp091-go v1.10.0
|
github.com/rabbitmq/amqp091-go v1.10.0
|
||||||
github.com/samber/lo v1.52.0
|
github.com/samber/lo v1.52.0
|
||||||
github.com/sirupsen/logrus v1.9.3
|
github.com/sirupsen/logrus v1.9.3
|
||||||
go.uber.org/mock v0.6.0
|
go.uber.org/mock v0.6.0
|
||||||
golang.org/x/crypto v0.41.0
|
golang.org/x/crypto v0.43.0
|
||||||
gorm.io/driver/postgres v1.6.0
|
gorm.io/driver/postgres v1.6.0
|
||||||
gorm.io/gorm v1.30.1
|
gorm.io/gorm v1.31.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/ajg/form v1.5.1 // indirect
|
|
||||||
github.com/alexflint/go-scalar v1.2.0 // indirect
|
github.com/alexflint/go-scalar v1.2.0 // indirect
|
||||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect
|
github.com/bytedance/gopkg v0.1.3 // indirect
|
||||||
|
github.com/bytedance/sonic v1.14.1 // indirect
|
||||||
|
github.com/bytedance/sonic/loader v0.3.0 // indirect
|
||||||
|
github.com/cloudwego/base64x v0.1.6 // indirect
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.10 // indirect
|
||||||
|
github.com/gin-contrib/sse v1.1.0 // indirect
|
||||||
github.com/go-andiamo/splitter v1.2.5 // indirect
|
github.com/go-andiamo/splitter v1.2.5 // indirect
|
||||||
github.com/go-andiamo/urit v1.2.1 // indirect
|
github.com/go-andiamo/urit v1.2.1 // indirect
|
||||||
|
github.com/go-chi/chi/v5 v5.2.3 // indirect
|
||||||
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
|
github.com/go-playground/validator/v10 v10.28.0 // indirect
|
||||||
github.com/goccy/go-json v0.10.5 // indirect
|
github.com/goccy/go-json v0.10.5 // indirect
|
||||||
|
github.com/goccy/go-yaml v1.18.0 // indirect
|
||||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
||||||
github.com/jackc/pgx/v5 v5.7.5 // indirect
|
github.com/jackc/pgx/v5 v5.7.5 // indirect
|
||||||
@@ -37,20 +44,38 @@ require (
|
|||||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
github.com/jinzhu/now v1.1.5 // indirect
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
github.com/jonboulle/clockwork v0.5.0 // indirect
|
github.com/jonboulle/clockwork v0.5.0 // indirect
|
||||||
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
|
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||||
github.com/kr/pretty v0.3.1 // indirect
|
github.com/kr/pretty v0.3.1 // indirect
|
||||||
github.com/lestrrat-go/blackmagic v1.0.4 // indirect
|
github.com/leodido/go-urn v1.4.0 // indirect
|
||||||
github.com/lestrrat-go/httpcc v1.0.1 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/lestrrat-go/httprc v1.0.6 // indirect
|
|
||||||
github.com/lestrrat-go/iter v1.0.2 // indirect
|
|
||||||
github.com/lestrrat-go/option v1.0.1 // indirect
|
|
||||||
github.com/mfridman/interpolate v0.0.2 // indirect
|
github.com/mfridman/interpolate v0.0.2 // indirect
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
|
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||||
|
github.com/quic-go/qpack v0.5.1 // indirect
|
||||||
|
github.com/quic-go/quic-go v0.55.0 // indirect
|
||||||
|
github.com/redis/rueidis v1.0.66 // indirect
|
||||||
github.com/robfig/cron/v3 v3.0.1 // indirect
|
github.com/robfig/cron/v3 v3.0.1 // indirect
|
||||||
github.com/segmentio/asm v1.2.0 // indirect
|
|
||||||
github.com/sethvargo/go-retry v0.3.0 // indirect
|
github.com/sethvargo/go-retry v0.3.0 // indirect
|
||||||
|
github.com/swaggest/jsonschema-go v0.3.74 // indirect
|
||||||
|
github.com/swaggest/openapi-go v0.2.60 // indirect
|
||||||
|
github.com/swaggest/refl v1.3.1 // indirect
|
||||||
|
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
|
github.com/ugorji/go/codec v1.3.0 // indirect
|
||||||
|
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b // indirect
|
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||||
golang.org/x/sync v0.16.0 // indirect
|
golang.org/x/arch v0.22.0 // indirect
|
||||||
golang.org/x/sys v0.35.0 // indirect
|
golang.org/x/exp v0.0.0-20251009144603-d2f985daa21b // indirect
|
||||||
golang.org/x/text v0.28.0 // indirect
|
golang.org/x/mod v0.29.0 // indirect
|
||||||
|
golang.org/x/net v0.46.0 // indirect
|
||||||
|
golang.org/x/sync v0.17.0 // indirect
|
||||||
|
golang.org/x/sys v0.37.0 // indirect
|
||||||
|
golang.org/x/text v0.30.0 // indirect
|
||||||
|
golang.org/x/tools v0.38.0 // indirect
|
||||||
|
google.golang.org/protobuf v1.36.10 // indirect
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
sigs.k8s.io/yaml v1.6.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
237
go.sum
237
go.sum
@@ -1,35 +1,102 @@
|
|||||||
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
|
dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
|
||||||
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
|
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
|
||||||
|
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
|
||||||
|
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||||
|
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||||
|
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||||
github.com/alexflint/go-arg v1.6.0 h1:wPP9TwTPO54fUVQl4nZoxbFfKCcy5E6HBCumj1XVRSo=
|
github.com/alexflint/go-arg v1.6.0 h1:wPP9TwTPO54fUVQl4nZoxbFfKCcy5E6HBCumj1XVRSo=
|
||||||
github.com/alexflint/go-arg v1.6.0/go.mod h1:A7vTJzvjoaSTypg4biM5uYNTkJ27SkNTArtYXnlqVO8=
|
github.com/alexflint/go-arg v1.6.0/go.mod h1:A7vTJzvjoaSTypg4biM5uYNTkJ27SkNTArtYXnlqVO8=
|
||||||
github.com/alexflint/go-scalar v1.2.0 h1:WR7JPKkeNpnYIOfHRa7ivM21aWAdHD0gEWHCx+WQBRw=
|
github.com/alexflint/go-scalar v1.2.0 h1:WR7JPKkeNpnYIOfHRa7ivM21aWAdHD0gEWHCx+WQBRw=
|
||||||
github.com/alexflint/go-scalar v1.2.0/go.mod h1:LoFvNMqS1CPrMVltza4LvnGKhaSpc3oyLEBUZVhhS2o=
|
github.com/alexflint/go-scalar v1.2.0/go.mod h1:LoFvNMqS1CPrMVltza4LvnGKhaSpc3oyLEBUZVhhS2o=
|
||||||
|
github.com/appleboy/gin-jwt/v3 v3.1.0 h1:Q2DQ2MksmojwrYLsvIBTZ17zpWfeR8aHo8W9yu+hLtA=
|
||||||
|
github.com/appleboy/gin-jwt/v3 v3.1.0/go.mod h1:ANNEPdDkdOp6jXAbicMFX7N4mIIx70m9A3asDmXdbYo=
|
||||||
|
github.com/appleboy/gin-jwt/v3 v3.2.0 h1:Ifa8Zsm2cZ93u/HIAhcTmftTK8rIaaoAoH77lcajWD0=
|
||||||
|
github.com/appleboy/gin-jwt/v3 v3.2.0/go.mod h1:ANNEPdDkdOp6jXAbicMFX7N4mIIx70m9A3asDmXdbYo=
|
||||||
|
github.com/appleboy/gofight/v2 v2.1.2 h1:VOy3jow4vIK8BRQJoC/I9muxyYlJ2yb9ht2hZoS3rf4=
|
||||||
|
github.com/appleboy/gofight/v2 v2.1.2/go.mod h1:frW+U1QZEdDgixycTj4CygQ48yLTUhplt43+Wczp3rw=
|
||||||
|
github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M=
|
||||||
|
github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM=
|
||||||
|
github.com/bytedance/sonic v1.14.1 h1:FBMC0zVz5XUmE4z9wF4Jey0An5FueFvOsTKKKtwIl7w=
|
||||||
|
github.com/bytedance/sonic v1.14.1/go.mod h1:gi6uhQLMbTdeP0muCnrjHLeCUPyb70ujhnNlhOylAFc=
|
||||||
|
github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA=
|
||||||
|
github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
|
||||||
|
github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
|
||||||
|
github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||||
|
github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M=
|
||||||
|
github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU=
|
||||||
|
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
|
||||||
|
github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
|
||||||
|
github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
|
||||||
|
github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
|
||||||
|
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
|
||||||
|
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
|
||||||
|
github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A=
|
||||||
|
github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw=
|
||||||
|
github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA=
|
||||||
|
github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc=
|
||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc=
|
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
||||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40=
|
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||||
|
github.com/docker/docker v28.3.3+incompatible h1:Dypm25kh4rmk49v1eiVbsAtpAsYURjYkaKubwuBdxEI=
|
||||||
|
github.com/docker/docker v28.3.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
|
github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94=
|
||||||
|
github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE=
|
||||||
|
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||||
|
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||||
|
github.com/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0omw=
|
||||||
|
github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
|
||||||
|
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||||
|
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.10 h1:zyueNbySn/z8mJZHLt6IPw0KoZsiQNszIpU+bX4+ZK0=
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.10/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
|
||||||
|
github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w=
|
||||||
|
github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM=
|
||||||
|
github.com/gin-gonic/gin v1.11.0 h1:OW/6PLjyusp2PPXtyxKHU0RbX6I/l28FTdDlae5ueWk=
|
||||||
|
github.com/gin-gonic/gin v1.11.0/go.mod h1:+iq/FyxlGzII0KHiBGjuNn4UNENUlKbGlNmc+W50Dls=
|
||||||
github.com/go-andiamo/chioas v1.16.4 h1:aHtA3KLmfQfHRsGxjYPNjrD8cMR2uTncbjvcxY64B3Q=
|
github.com/go-andiamo/chioas v1.16.4 h1:aHtA3KLmfQfHRsGxjYPNjrD8cMR2uTncbjvcxY64B3Q=
|
||||||
github.com/go-andiamo/chioas v1.16.4/go.mod h1:5ZZYYuGwlF/amxErKFUu3eXz6hZ5GEYu5vCk+Guw+uc=
|
github.com/go-andiamo/chioas v1.16.4/go.mod h1:5ZZYYuGwlF/amxErKFUu3eXz6hZ5GEYu5vCk+Guw+uc=
|
||||||
|
github.com/go-andiamo/chioas v1.19.0 h1:LEMU0Wv86uB1Y2RSiCKkdswCFp0FSHyYi49E+DMC6z8=
|
||||||
|
github.com/go-andiamo/chioas v1.19.0/go.mod h1:J7ffP8Qm9rvODPy3ghAsdCNIQbyIH4AFuuMdceeT6YU=
|
||||||
github.com/go-andiamo/splitter v1.2.5 h1:P3NovWMY2V14TJJSolXBvlOmGSZo3Uz+LtTl2bsV/eY=
|
github.com/go-andiamo/splitter v1.2.5 h1:P3NovWMY2V14TJJSolXBvlOmGSZo3Uz+LtTl2bsV/eY=
|
||||||
github.com/go-andiamo/splitter v1.2.5/go.mod h1:8WHU24t9hcMKU5FXDQb1hysSEC/GPuivIp0uKY1J8gw=
|
github.com/go-andiamo/splitter v1.2.5/go.mod h1:8WHU24t9hcMKU5FXDQb1hysSEC/GPuivIp0uKY1J8gw=
|
||||||
github.com/go-andiamo/urit v1.2.1 h1:5JHJb+TuzuGvXw9Y/LK/lQltCL2gpgHkCznI2vv9ZeY=
|
github.com/go-andiamo/urit v1.2.1 h1:5JHJb+TuzuGvXw9Y/LK/lQltCL2gpgHkCznI2vv9ZeY=
|
||||||
github.com/go-andiamo/urit v1.2.1/go.mod h1:9kgXBxUPHFZvXwlOPN1GimDuHl+JCfQuetN5nxBNlpQ=
|
github.com/go-andiamo/urit v1.2.1/go.mod h1:9kgXBxUPHFZvXwlOPN1GimDuHl+JCfQuetN5nxBNlpQ=
|
||||||
github.com/go-chi/chi/v5 v5.2.2 h1:CMwsvRVTbXVytCk1Wd72Zy1LAsAh9GxMmSNWLHCG618=
|
github.com/go-chi/chi/v5 v5.2.2 h1:CMwsvRVTbXVytCk1Wd72Zy1LAsAh9GxMmSNWLHCG618=
|
||||||
github.com/go-chi/chi/v5 v5.2.2/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
|
github.com/go-chi/chi/v5 v5.2.2/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
|
||||||
github.com/go-chi/jwtauth/v5 v5.3.3 h1:50Uzmacu35/ZP9ER2Ht6SazwPsnLQ9LRJy6zTZJpHEo=
|
github.com/go-chi/chi/v5 v5.2.3 h1:WQIt9uxdsAbgIYgid+BpYc+liqQZGMHRaUwp0JUcvdE=
|
||||||
github.com/go-chi/jwtauth/v5 v5.3.3/go.mod h1:O4QvPRuZLZghl9WvfVaON+ARfGzpD2PBX/QY5vUz7aQ=
|
github.com/go-chi/chi/v5 v5.2.3/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
|
||||||
github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4=
|
|
||||||
github.com/go-chi/render v1.0.3/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0=
|
|
||||||
github.com/go-co-op/gocron/v2 v2.17.0 h1:e/oj6fcAM8vOOKZxv2Cgfmjo+s8AXC46po5ZPtaSea4=
|
github.com/go-co-op/gocron/v2 v2.17.0 h1:e/oj6fcAM8vOOKZxv2Cgfmjo+s8AXC46po5ZPtaSea4=
|
||||||
github.com/go-co-op/gocron/v2 v2.17.0/go.mod h1:Zii6he+Zfgy5W9B+JKk/KwejFOW0kZTFvHtwIpR4aBI=
|
github.com/go-co-op/gocron/v2 v2.17.0/go.mod h1:Zii6he+Zfgy5W9B+JKk/KwejFOW0kZTFvHtwIpR4aBI=
|
||||||
|
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||||
|
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
|
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
|
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||||
|
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||||
|
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||||
|
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||||
|
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||||
|
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||||
|
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||||
|
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||||
|
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||||
|
github.com/go-playground/validator/v10 v10.28.0 h1:Q7ibns33JjyW48gHkuFT91qX48KG0ktULL6FgHdG688=
|
||||||
|
github.com/go-playground/validator/v10 v10.28.0/go.mod h1:GoI6I1SjPBh9p7ykNE/yj3fFYbyDOpwMn5KXd+m2hUU=
|
||||||
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
|
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
|
||||||
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||||
|
github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw=
|
||||||
|
github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||||
|
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||||
|
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||||
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
|
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
|
||||||
github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
|
github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
|
||||||
|
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||||
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||||
@@ -48,35 +115,78 @@ github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
|||||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||||
github.com/jonboulle/clockwork v0.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I=
|
github.com/jonboulle/clockwork v0.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I=
|
||||||
github.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60=
|
github.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60=
|
||||||
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
|
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||||
|
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||||
|
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
||||||
|
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/lestrrat-go/blackmagic v1.0.4 h1:IwQibdnf8l2KoO+qC3uT4OaTWsW7tuRQXy9TRN9QanA=
|
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||||
github.com/lestrrat-go/blackmagic v1.0.4/go.mod h1:6AWFyKNNj0zEXQYfTMPfZrAXUWUfTIZ5ECEUEJaijtw=
|
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||||
github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE=
|
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
|
||||||
github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E=
|
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||||
github.com/lestrrat-go/httprc v1.0.6 h1:qgmgIRhpvBqexMJjA/PmwSvhNk679oqD1RbovdCGW8k=
|
github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE=
|
||||||
github.com/lestrrat-go/httprc v1.0.6/go.mod h1:mwwz3JMTPBjHUkkDv/IGJ39aALInZLrhBp0X7KGUZlo=
|
github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||||
github.com/lestrrat-go/iter v1.0.2 h1:gMXo1q4c2pHmC3dn8LzRhJfP1ceCbgSiT9lUydIzltI=
|
|
||||||
github.com/lestrrat-go/iter v1.0.2/go.mod h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4=
|
|
||||||
github.com/lestrrat-go/jwx/v2 v2.1.6 h1:hxM1gfDILk/l5ylers6BX/Eq1m/pnxe9NBwW6lVfecA=
|
|
||||||
github.com/lestrrat-go/jwx/v2 v2.1.6/go.mod h1:Y722kU5r/8mV7fYDifjug0r8FK8mZdw0K0GpJw/l8pU=
|
|
||||||
github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU=
|
|
||||||
github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
|
|
||||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
github.com/mdelapenya/tlscert v0.2.0 h1:7H81W6Z/4weDvZBNOfQte5GpIMo0lGYEeWbkGp5LJHI=
|
||||||
|
github.com/mdelapenya/tlscert v0.2.0/go.mod h1:O4njj3ELLnJjGdkN7M/vIVCpZ+Cf0L6muqOG4tLSl8o=
|
||||||
github.com/mfridman/interpolate v0.0.2 h1:pnuTK7MQIxxFz1Gr+rjSIx9u7qVjf5VOoM/u6BbAxPY=
|
github.com/mfridman/interpolate v0.0.2 h1:pnuTK7MQIxxFz1Gr+rjSIx9u7qVjf5VOoM/u6BbAxPY=
|
||||||
github.com/mfridman/interpolate v0.0.2/go.mod h1:p+7uk6oE07mpE/Ik1b8EckO0O4ZXiGAfshKBWLUM9Xg=
|
github.com/mfridman/interpolate v0.0.2/go.mod h1:p+7uk6oE07mpE/Ik1b8EckO0O4ZXiGAfshKBWLUM9Xg=
|
||||||
|
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
||||||
|
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
||||||
|
github.com/moby/go-archive v0.1.0 h1:Kk/5rdW/g+H8NHdJW2gsXyZ7UnzvJNOy6VKJqueWdcQ=
|
||||||
|
github.com/moby/go-archive v0.1.0/go.mod h1:G9B+YoujNohJmrIYFBpSd54GTUB4lt9S+xVQvsJyFuo=
|
||||||
|
github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
|
||||||
|
github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
|
||||||
|
github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU=
|
||||||
|
github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko=
|
||||||
|
github.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs=
|
||||||
|
github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=
|
||||||
|
github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=
|
||||||
|
github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
|
||||||
|
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
|
||||||
|
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||||
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
|
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
||||||
|
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||||
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
|
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
|
||||||
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
|
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
|
||||||
|
github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8=
|
||||||
|
github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY=
|
||||||
|
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||||
|
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||||
|
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
|
||||||
|
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
|
||||||
|
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
|
||||||
|
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
||||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||||
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
|
||||||
|
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||||
github.com/pressly/goose/v3 v3.24.3 h1:DSWWNwwggVUsYZ0X2VitiAa9sKuqtBfe+Jr9zFGwWlM=
|
github.com/pressly/goose/v3 v3.24.3 h1:DSWWNwwggVUsYZ0X2VitiAa9sKuqtBfe+Jr9zFGwWlM=
|
||||||
github.com/pressly/goose/v3 v3.24.3/go.mod h1:v9zYL4xdViLHCUUJh/mhjnm6JrK7Eul8AS93IxiZM4E=
|
github.com/pressly/goose/v3 v3.24.3/go.mod h1:v9zYL4xdViLHCUUJh/mhjnm6JrK7Eul8AS93IxiZM4E=
|
||||||
|
github.com/pressly/goose/v3 v3.26.0 h1:KJakav68jdH0WDvoAcj8+n61WqOIaPGgH0bJWS6jpmM=
|
||||||
|
github.com/pressly/goose/v3 v3.26.0/go.mod h1:4hC1KrritdCxtuFsqgs1R4AU5bWtTAf+cnWvfhf2DNY=
|
||||||
|
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
|
||||||
|
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
||||||
|
github.com/quic-go/quic-go v0.55.0 h1:zccPQIqYCXDt5NmcEabyYvOnomjs8Tlwl7tISjJh9Mk=
|
||||||
|
github.com/quic-go/quic-go v0.55.0/go.mod h1:DR51ilwU1uE164KuWXhinFcKWGlEjzys2l8zUl5Ss1U=
|
||||||
github.com/rabbitmq/amqp091-go v1.10.0 h1:STpn5XsHlHGcecLmMFCtg7mqq0RnD+zFr4uzukfVhBw=
|
github.com/rabbitmq/amqp091-go v1.10.0 h1:STpn5XsHlHGcecLmMFCtg7mqq0RnD+zFr4uzukfVhBw=
|
||||||
github.com/rabbitmq/amqp091-go v1.10.0/go.mod h1:Hy4jKW5kQART1u+JkDTF9YYOQUHXqMuhrgxOEeS7G4o=
|
github.com/rabbitmq/amqp091-go v1.10.0/go.mod h1:Hy4jKW5kQART1u+JkDTF9YYOQUHXqMuhrgxOEeS7G4o=
|
||||||
|
github.com/redis/rueidis v1.0.66 h1:7rvyrl0vL/cAEkE97+L5v3MJ3Vg8IKz+KIxUTfT+yJk=
|
||||||
|
github.com/redis/rueidis v1.0.66/go.mod h1:Lkhr2QTgcoYBhxARU7kJRO8SyVlgUuEkcJO1Y8MCluA=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||||
@@ -86,40 +196,98 @@ github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0t
|
|||||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||||
github.com/samber/lo v1.52.0 h1:Rvi+3BFHES3A8meP33VPAxiBZX/Aws5RxrschYGjomw=
|
github.com/samber/lo v1.52.0 h1:Rvi+3BFHES3A8meP33VPAxiBZX/Aws5RxrschYGjomw=
|
||||||
github.com/samber/lo v1.52.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0=
|
github.com/samber/lo v1.52.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0=
|
||||||
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
|
|
||||||
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
|
|
||||||
github.com/sethvargo/go-retry v0.3.0 h1:EEt31A35QhrcRZtrYFDTBg91cqZVnFL2navjDrah2SE=
|
github.com/sethvargo/go-retry v0.3.0 h1:EEt31A35QhrcRZtrYFDTBg91cqZVnFL2navjDrah2SE=
|
||||||
github.com/sethvargo/go-retry v0.3.0/go.mod h1:mNX17F0C/HguQMyMyJxcnU471gOZGxCLyYaFyAZraas=
|
github.com/sethvargo/go-retry v0.3.0/go.mod h1:mNX17F0C/HguQMyMyJxcnU471gOZGxCLyYaFyAZraas=
|
||||||
|
github.com/shirou/gopsutil/v4 v4.25.6 h1:kLysI2JsKorfaFPcYmcJqbzROzsBWEOAtw6A7dIfqXs=
|
||||||
|
github.com/shirou/gopsutil/v4 v4.25.6/go.mod h1:PfybzyydfZcN+JMMjkF6Zb8Mq1A/VcogFFg7hj50W9c=
|
||||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||||
|
github.com/swaggest/jsonschema-go v0.3.74 h1:hkAZBK3RxNWU013kPqj0Q/GHGzYCCm9WcUTnfg2yPp0=
|
||||||
|
github.com/swaggest/jsonschema-go v0.3.74/go.mod h1:qp+Ym2DIXHlHzch3HKz50gPf2wJhKOrAB/VYqLS2oJU=
|
||||||
|
github.com/swaggest/openapi-go v0.2.60 h1:kglHH/WIfqAglfuWL4tu0LPakqNYySzklUWx06SjSKo=
|
||||||
|
github.com/swaggest/openapi-go v0.2.60/go.mod h1:jmFOuYdsWGtHU0BOuILlHZQJxLqHiAE6en+baE+QQUk=
|
||||||
|
github.com/swaggest/refl v1.3.1 h1:XGplEkYftR7p9cz1lsiwXMM2yzmOymTE9vneVVpaOh4=
|
||||||
|
github.com/swaggest/refl v1.3.1/go.mod h1:4uUVFVfPJ0NSX9FPwMPspeHos9wPFlCMGoPRllUbpvA=
|
||||||
|
github.com/testcontainers/testcontainers-go v0.39.0 h1:uCUJ5tA+fcxbFAB0uP3pIK3EJ2IjjDUHFSZ1H1UxAts=
|
||||||
|
github.com/testcontainers/testcontainers-go v0.39.0/go.mod h1:qmHpkG7H5uPf/EvOORKvS6EuDkBUPE3zpVGaH9NL7f8=
|
||||||
|
github.com/testcontainers/testcontainers-go/modules/redis v0.39.0 h1:p54qELdCx4Gftkxzf44k9RJRRhaO/S5ehP9zo8SUTLM=
|
||||||
|
github.com/testcontainers/testcontainers-go/modules/redis v0.39.0/go.mod h1:P1mTbHruHqAU2I26y0RADz1BitF59FLbQr7ceqN9bt4=
|
||||||
|
github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U=
|
||||||
|
github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||||
|
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||||
|
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||||
|
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
||||||
|
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||||
|
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
|
||||||
|
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
|
||||||
|
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
|
||||||
|
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
|
||||||
|
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||||
|
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||||
|
github.com/ugorji/go/codec v1.3.0 h1:Qd2W2sQawAfG8XSvzwhBeoGq71zXOC/Q1E9y/wUcsUA=
|
||||||
|
github.com/ugorji/go/codec v1.3.0/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
|
||||||
|
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM=
|
||||||
|
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI=
|
||||||
|
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
||||||
|
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||||
|
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||||
|
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||||
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk=
|
||||||
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw=
|
||||||
|
go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=
|
||||||
|
go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I=
|
||||||
|
go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE=
|
||||||
|
go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E=
|
||||||
|
go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
|
||||||
|
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
|
||||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||||
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
|
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
|
||||||
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
|
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
|
||||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||||
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
|
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
|
||||||
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
|
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
||||||
|
golang.org/x/arch v0.22.0 h1:c/Zle32i5ttqRXjdLyyHZESLD/bB90DCU1g9l/0YBDI=
|
||||||
|
golang.org/x/arch v0.22.0/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A=
|
||||||
|
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
|
||||||
|
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
|
||||||
golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b h1:DXr+pvt3nC887026GRP39Ej11UATqWDmWuS99x26cD0=
|
golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b h1:DXr+pvt3nC887026GRP39Ej11UATqWDmWuS99x26cD0=
|
||||||
golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b/go.mod h1:4QTo5u+SEIbbKW1RacMZq1YEfOBqeXa19JeshGi+zc4=
|
golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b/go.mod h1:4QTo5u+SEIbbKW1RacMZq1YEfOBqeXa19JeshGi+zc4=
|
||||||
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
golang.org/x/exp v0.0.0-20251009144603-d2f985daa21b h1:18qgiDvlvH7kk8Ioa8Ov+K6xCi0GMvmGfGW0sgd/SYA=
|
||||||
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
golang.org/x/exp v0.0.0-20251009144603-d2f985daa21b/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70=
|
||||||
|
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
|
||||||
|
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
|
||||||
|
golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4=
|
||||||
|
golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
|
||||||
|
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
|
||||||
|
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
|
||||||
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
|
||||||
|
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
|
||||||
|
golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
|
||||||
|
golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
|
||||||
|
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
|
||||||
|
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
@@ -127,11 +295,18 @@ gorm.io/driver/postgres v1.6.0 h1:2dxzU8xJ+ivvqTRph34QX+WrRaJlmfyPqXmoGVjMBa4=
|
|||||||
gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo=
|
gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo=
|
||||||
gorm.io/gorm v1.30.1 h1:lSHg33jJTBxs2mgJRfRZeLDG+WZaHYCk3Wtfl6Ngzo4=
|
gorm.io/gorm v1.30.1 h1:lSHg33jJTBxs2mgJRfRZeLDG+WZaHYCk3Wtfl6Ngzo4=
|
||||||
gorm.io/gorm v1.30.1/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=
|
gorm.io/gorm v1.30.1/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=
|
||||||
|
gorm.io/gorm v1.31.1 h1:7CA8FTFz/gRfgqgpeKIBcervUn3xSyPUmr6B2WXJ7kg=
|
||||||
|
gorm.io/gorm v1.31.1/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs=
|
||||||
modernc.org/libc v1.65.0 h1:e183gLDnAp9VJh6gWKdTy0CThL9Pt7MfcR/0bgb7Y1Y=
|
modernc.org/libc v1.65.0 h1:e183gLDnAp9VJh6gWKdTy0CThL9Pt7MfcR/0bgb7Y1Y=
|
||||||
modernc.org/libc v1.65.0/go.mod h1:7m9VzGq7APssBTydds2zBcxGREwvIGpuUBaKTXdm2Qs=
|
modernc.org/libc v1.65.0/go.mod h1:7m9VzGq7APssBTydds2zBcxGREwvIGpuUBaKTXdm2Qs=
|
||||||
|
modernc.org/libc v1.66.3 h1:cfCbjTUcdsKyyZZfEUKfoHcP3S0Wkvz3jgSzByEWVCQ=
|
||||||
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
|
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
|
||||||
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
|
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
|
||||||
modernc.org/memory v1.10.0 h1:fzumd51yQ1DxcOxSO+S6X7+QTuVU+n8/Aj7swYjFfC4=
|
modernc.org/memory v1.10.0 h1:fzumd51yQ1DxcOxSO+S6X7+QTuVU+n8/Aj7swYjFfC4=
|
||||||
modernc.org/memory v1.10.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
|
modernc.org/memory v1.10.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
|
||||||
|
modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
|
||||||
modernc.org/sqlite v1.37.0 h1:s1TMe7T3Q3ovQiK2Ouz4Jwh7dw4ZDqbebSDTlSJdfjI=
|
modernc.org/sqlite v1.37.0 h1:s1TMe7T3Q3ovQiK2Ouz4Jwh7dw4ZDqbebSDTlSJdfjI=
|
||||||
modernc.org/sqlite v1.37.0/go.mod h1:5YiWv+YviqGMuGw4V+PNplcyaJ5v+vQd7TQOgkACoJM=
|
modernc.org/sqlite v1.37.0/go.mod h1:5YiWv+YviqGMuGw4V+PNplcyaJ5v+vQd7TQOgkACoJM=
|
||||||
|
modernc.org/sqlite v1.38.2 h1:Aclu7+tgjgcQVShZqim41Bbw9Cho0y/7WzYptXqkEek=
|
||||||
|
sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
|
||||||
|
sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=
|
||||||
|
|||||||
24
html/redoc.html
Normal file
24
html/redoc.html
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>Documentation of OstiweStatus API</title>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script src="https://cdn.redoc.ly/redoc/latest/bundles/redoc.standalone.js"> </script>
|
||||||
|
<div id="redoc-container"></div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
Redoc.init('/static-doc', {
|
||||||
|
"showExtensions": true
|
||||||
|
}, document.getElementById('redoc-container'))
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
163
main.go
163
main.go
@@ -1,62 +1,163 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"embed"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
|
|
||||||
"git.ostiwe.com/ostiwe-com/status/migration"
|
"git.ostiwe.com/ostiwe-com/status/migration"
|
||||||
appLog "git.ostiwe.com/ostiwe-com/status/modules/log"
|
appLog "git.ostiwe.com/ostiwe-com/status/modules/log"
|
||||||
"git.ostiwe.com/ostiwe-com/status/pkg/args"
|
"git.ostiwe.com/ostiwe-com/status/pkg/args"
|
||||||
"git.ostiwe.com/ostiwe-com/status/router"
|
"git.ostiwe.com/ostiwe-com/status/router"
|
||||||
"git.ostiwe.com/ostiwe-com/status/server"
|
"git.ostiwe.com/ostiwe-com/status/server"
|
||||||
_ "git.ostiwe.com/ostiwe-com/status/settings"
|
"git.ostiwe.com/ostiwe-com/status/settings"
|
||||||
"github.com/alexflint/go-arg"
|
"github.com/alexflint/go-arg"
|
||||||
"github.com/go-chi/chi/v5"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//go:embed html
|
||||||
|
var htmlFolder embed.FS
|
||||||
|
|
||||||
var appArgs args.AppArgs
|
var appArgs args.AppArgs
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
arg.MustParse(&appArgs)
|
arg.MustParse(&appArgs)
|
||||||
|
defer appLog.Global.Get(appLog.SYSTEM).Debug("Exit from application")
|
||||||
|
|
||||||
if appArgs.Migration != nil && appArgs.Migration.Create != nil {
|
if appArgs.Migration != nil && appArgs.Migration.Create != nil {
|
||||||
if err := migration.CreateMigration(appArgs.Migration.Create.Name); err != nil {
|
runMigrationCreateCommand()
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if appArgs.Server != nil {
|
if appArgs.Server != nil {
|
||||||
migration.RunMigration()
|
runServerCommand()
|
||||||
|
|
||||||
server.Run(appArgs.Server)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if appArgs.ServerDocumentation != nil {
|
|
||||||
appLog.Global.Get(appLog.SYSTEM).Info("Collect documentation")
|
|
||||||
|
|
||||||
docs := router.Documentate()
|
|
||||||
if !appArgs.ServerDocumentation.Plain {
|
|
||||||
chiRouter := chi.NewRouter()
|
|
||||||
|
|
||||||
err := docs.SetupRoutes(chiRouter, docs)
|
|
||||||
if err != nil {
|
|
||||||
appLog.Global.Get(appLog.SYSTEM).Error(fmt.Sprintf("Setup docs routes error: %v", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
appLog.Global.Get(appLog.SYSTEM).Info(fmt.Sprintf("Start documentation server on port: %s", appArgs.ServerDocumentation.Port))
|
|
||||||
err = http.ListenAndServe(fmt.Sprintf(":%s", appArgs.ServerDocumentation.Port), chiRouter)
|
|
||||||
if err != nil {
|
|
||||||
appLog.Global.Get(appLog.SYSTEM).Error(fmt.Sprintf("Startup server error: %v", err))
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
if appArgs.Docs != nil {
|
||||||
|
runDocumentationCommand()
|
||||||
|
|
||||||
appLog.Global.Get(appLog.SYSTEM).Info("Exit from application")
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func runMigrationCreateCommand() {
|
||||||
|
settings.Init()
|
||||||
|
if err := migration.CreateMigration(appArgs.Migration.Create.Name); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func runServerCommand() {
|
||||||
|
settings.Init()
|
||||||
|
migration.RunMigration()
|
||||||
|
server.Run(appArgs.Server)
|
||||||
|
}
|
||||||
|
|
||||||
|
func runDocumentationCommand() {
|
||||||
|
if appArgs.Docs.Generate != nil {
|
||||||
|
runDocsGenerationCommand()
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if appArgs.Docs.Serve != nil {
|
||||||
|
runDocsServingCommand()
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func runDocsGenerationCommand() {
|
||||||
|
documentate, err := router.Documentate()
|
||||||
|
if err != nil {
|
||||||
|
appLog.Global.Get(appLog.SYSTEM).Error(err)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var file []byte
|
||||||
|
switch appArgs.Docs.Generate.Format {
|
||||||
|
case "json":
|
||||||
|
file, err = documentate.MarshalJSON()
|
||||||
|
case "yaml":
|
||||||
|
file, err = documentate.MarshalYAML()
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
appLog.Global.Get(appLog.SYSTEM).Error(err)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if appArgs.Docs.Generate.Out == "stdout" {
|
||||||
|
_, err = os.Stdout.Write(file)
|
||||||
|
if err != nil {
|
||||||
|
appLog.Global.Get(appLog.SYSTEM).Error(err)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.WriteFile(appArgs.Docs.Generate.Out, file, os.ModeAppend)
|
||||||
|
if err != nil {
|
||||||
|
appLog.Global.Get(appLog.SYSTEM).Error(err)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func runDocsServingCommand() {
|
||||||
|
documentate, err := router.Documentate()
|
||||||
|
if err != nil {
|
||||||
|
appLog.Global.Get(appLog.SYSTEM).Error(err)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
docsJson, err := documentate.MarshalJSON()
|
||||||
|
if err != nil {
|
||||||
|
appLog.Global.Get(appLog.SYSTEM).Error(err)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
html, err := htmlFolder.ReadFile("html/redoc.html")
|
||||||
|
if err != nil {
|
||||||
|
appLog.Global.Get(appLog.SYSTEM).Error(err)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
g := gin.New()
|
||||||
|
g.Handle("GET", "/static-doc", func(c *gin.Context) {
|
||||||
|
c.Writer.Header().Add("Content-type", "application/json")
|
||||||
|
_, err = c.Writer.Write(docsJson)
|
||||||
|
if err != nil {
|
||||||
|
c.Writer.WriteHeader(http.StatusInternalServerError)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
g.Handle("GET", "/docs/index.html", func(c *gin.Context) {
|
||||||
|
c.Writer.Header().Add("Content-Type", "text/html")
|
||||||
|
_, err = c.Writer.Write(html)
|
||||||
|
if err != nil {
|
||||||
|
c.Writer.WriteHeader(http.StatusInternalServerError)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if err = g.Run(fmt.Sprintf(":%s", appArgs.Docs.Serve.Port)); err != nil {
|
||||||
|
appLog.Global.Get(appLog.SYSTEM).Error(err)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,32 +7,33 @@ type HTTPConfig struct {
|
|||||||
Headers map[string]string `json:"headers"`
|
Headers map[string]string `json:"headers"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ServiceTypeCheckConfig
|
||||||
|
// MaxFails - max "ping" fails, after with the service marked as unavailable
|
||||||
|
// Interval - interval between "ping" in seconds
|
||||||
|
// Timeout - interval after which the task will be canceled
|
||||||
type ServiceTypeCheckConfig struct {
|
type ServiceTypeCheckConfig struct {
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
HTTPConfig *HTTPConfig `json:"httpConfig"`
|
HTTPConfig *HTTPConfig `json:"httpConfig"`
|
||||||
// MaxFails - max "ping" fails, after with the service marked as unavailable
|
|
||||||
MaxFails uint8 `json:"maxFails"`
|
MaxFails uint8 `json:"maxFails"`
|
||||||
// Interval - interval between "ping" in seconds
|
|
||||||
Interval uint64 `json:"interval"`
|
Interval uint64 `json:"interval"`
|
||||||
// Timeout - interval after which the task will be canceled
|
|
||||||
Timeout uint64 `json:"timeout"`
|
Timeout uint64 `json:"timeout"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Service
|
||||||
|
// ID Unique ID for entity
|
||||||
|
// Name Human-readable service name
|
||||||
|
// Description Human-readable service description
|
||||||
|
// Host to check, for example 192.168.1.44 or https://google.com
|
||||||
|
// Type for check, for now is TCP or HTTP or something else
|
||||||
type Service struct {
|
type Service struct {
|
||||||
// Unique ID for entity
|
|
||||||
ID uint64 `gorm:"primary_key;auto_increment" json:"id"`
|
ID uint64 `gorm:"primary_key;auto_increment" json:"id"`
|
||||||
// Human-readable service name
|
|
||||||
Name string `gorm:"size:255;not null" json:"name"`
|
Name string `gorm:"size:255;not null" json:"name"`
|
||||||
// Human-readable service description
|
|
||||||
Description string `gorm:"size:255" json:"description"`
|
Description string `gorm:"size:255" json:"description"`
|
||||||
PublicDescription string `gorm:"size:255" json:"publicDescription"`
|
PublicDescription string `gorm:"size:255" json:"publicDescription"`
|
||||||
Public *bool `gorm:"default:false" json:"public"`
|
Public *bool `gorm:"default:false" json:"public"`
|
||||||
// Host to check, for example 192.168.1.44 or https://google.com
|
|
||||||
Host string `gorm:"size:255;not null" json:"host"`
|
Host string `gorm:"size:255;not null" json:"host"`
|
||||||
// Type for check, for now is TCP or HTTP or something else
|
|
||||||
Type string `gorm:"size:255;not null" json:"type"`
|
Type string `gorm:"size:255;not null" json:"type"`
|
||||||
Config *ServiceTypeCheckConfig `gorm:"serializer:json;column:type_config" json:"typeConfig"`
|
Config *ServiceTypeCheckConfig `gorm:"serializer:json;column:type_config" json:"typeConfig"`
|
||||||
|
|
||||||
Statuses []Status `gorm:"foreignkey:ServiceID" json:"statuses"`
|
Statuses []Status `gorm:"foreignkey:ServiceID" json:"statuses"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ const (
|
|||||||
StatusOK StatusCode = "ok" // Means - response ok, service is alive
|
StatusOK StatusCode = "ok" // Means - response ok, service is alive
|
||||||
StatusFailed StatusCode = "failed" // Means - response failed, all tries failed, service down
|
StatusFailed StatusCode = "failed" // Means - response failed, all tries failed, service down
|
||||||
StatusWarn StatusCode = "warn" // Means - response failed after N tries and still watched
|
StatusWarn StatusCode = "warn" // Means - response failed after N tries and still watched
|
||||||
|
StatusUncheck StatusCode = "uncheck"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Status struct {
|
type Status struct {
|
||||||
|
|||||||
@@ -1,27 +1,26 @@
|
|||||||
package jwt
|
package jwt
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/ed25519"
|
"crypto/rsa"
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.ostiwe.com/ostiwe-com/status/model"
|
"git.ostiwe.com/ostiwe-com/status/model"
|
||||||
"git.ostiwe.com/ostiwe-com/status/settings"
|
"git.ostiwe.com/ostiwe-com/status/settings"
|
||||||
"github.com/go-chi/jwtauth/v5"
|
ginJwt "github.com/appleboy/gin-jwt/v3"
|
||||||
"github.com/golang-jwt/jwt/v5"
|
"github.com/golang-jwt/jwt/v5"
|
||||||
"github.com/lestrrat-go/jwx/v2/jwa"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
signKey *ed25519.PrivateKey
|
signKey *rsa.PrivateKey
|
||||||
publicSignKey *ed25519.PublicKey
|
signMethod jwt.SigningMethod = jwt.SigningMethodRS256
|
||||||
signMethod jwt.SigningMethod
|
|
||||||
|
|
||||||
TokenAuth *jwtauth.JWTAuth
|
AuthMiddleware *ginJwt.GinJWTMiddleware
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func Init() {
|
||||||
jwtPublicKeyPath := os.Getenv("JWT_SIGN_PUBLIC_KEY_PATH")
|
jwtPublicKeyPath := os.Getenv("JWT_SIGN_PUBLIC_KEY_PATH")
|
||||||
if !strings.HasPrefix(jwtPublicKeyPath, "/") {
|
if !strings.HasPrefix(jwtPublicKeyPath, "/") {
|
||||||
jwtPublicKeyPath = settings.WorkingDir + "/" + jwtPublicKeyPath
|
jwtPublicKeyPath = settings.WorkingDir + "/" + jwtPublicKeyPath
|
||||||
@@ -32,6 +31,8 @@ func init() {
|
|||||||
jwtPrivateKeyPath = settings.WorkingDir + "/" + jwtPrivateKeyPath
|
jwtPrivateKeyPath = settings.WorkingDir + "/" + jwtPrivateKeyPath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
|
||||||
publicFile, err := os.ReadFile(jwtPublicKeyPath)
|
publicFile, err := os.ReadFile(jwtPublicKeyPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -42,31 +43,26 @@ func init() {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
privateKey, err := jwt.ParseEdPrivateKeyFromPEM(privateFile)
|
signKey, err = jwt.ParseRSAPrivateKeyFromPEM(privateFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
publicKey, err := jwt.ParseEdPublicKeyFromPEM(publicFile)
|
AuthMiddleware = &ginJwt.GinJWTMiddleware{
|
||||||
if err != nil {
|
SigningAlgorithm: signMethod.Alg(),
|
||||||
|
PrivKeyBytes: privateFile,
|
||||||
|
PubKeyBytes: publicFile,
|
||||||
|
Timeout: time.Hour * 6,
|
||||||
|
MaxRefresh: time.Hour * 24 * 7,
|
||||||
|
SecureCookie: true,
|
||||||
|
CookieHTTPOnly: true,
|
||||||
|
CookieSameSite: http.SameSiteStrictMode,
|
||||||
|
SendCookie: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = AuthMiddleware.MiddlewareInit(); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
pk, ok := privateKey.(ed25519.PrivateKey)
|
|
||||||
if !ok {
|
|
||||||
panic("invalid ed25519 private key")
|
|
||||||
}
|
|
||||||
|
|
||||||
k, ok := publicKey.(ed25519.PublicKey)
|
|
||||||
if !ok {
|
|
||||||
panic("invalid ed25519 public key")
|
|
||||||
}
|
|
||||||
|
|
||||||
signKey = &pk
|
|
||||||
publicSignKey = &k
|
|
||||||
signMethod = jwt.SigningMethodEdDSA
|
|
||||||
|
|
||||||
TokenAuth = jwtauth.New(string(jwa.EdDSA), signKey, publicSignKey)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateByUser(user *model.User) (string, error) {
|
func CreateByUser(user *model.User) (string, error) {
|
||||||
|
|||||||
@@ -44,7 +44,12 @@ func NewAppScheduler() (AppScheduler, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *appScheduler) NewServiceJob(serviceID uint64, jd gocron.JobDefinition, t gocron.Task, opt ...gocron.JobOption) (gocron.Job, error) {
|
func (s *appScheduler) NewServiceJob(
|
||||||
|
serviceID uint64,
|
||||||
|
jd gocron.JobDefinition,
|
||||||
|
t gocron.Task,
|
||||||
|
opt ...gocron.JobOption,
|
||||||
|
) (gocron.Job, error) {
|
||||||
job, err := s.scheduler.NewJob(jd, t, opt...)
|
job, err := s.scheduler.NewJob(jd, t, opt...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package args
|
|||||||
import "git.ostiwe.com/ostiwe-com/status/version"
|
import "git.ostiwe.com/ostiwe-com/status/version"
|
||||||
|
|
||||||
type ServerCmd struct {
|
type ServerCmd struct {
|
||||||
Port string `arg:"-p,--port" help:"Port to listen on" default:"8080"`
|
Port string `arg:"-p,--port,env:APP_PORT" default:"8080" help:"Port to listen on"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type MigrationCreate struct {
|
type MigrationCreate struct {
|
||||||
@@ -15,14 +15,22 @@ type Migration struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ServerDocumentationCmd struct {
|
type ServerDocumentationCmd struct {
|
||||||
Port string `arg:"-p,--port" help:"Port to listen on" default:"8081"`
|
Port string `arg:"-p,--port,env:APP_PORT_DOCS" default:"8081" help:"Port to listen on"`
|
||||||
Plain bool `arg:"--plain" help:"Enable plain text output" default:"true"`
|
}
|
||||||
PlainFormat string `arg:"--plain-format" help:"Set format for output (json, yaml)" default:"yaml"`
|
|
||||||
|
type GenerateDocumentationCmd struct {
|
||||||
|
Format string `arg:"--format,-f" default:"yaml" help:"Set output format (json, yaml)"`
|
||||||
|
Out string `arg:"--out,-o" default:"stdout" help:"Output file name (or stdout)"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DocsCmd struct {
|
||||||
|
Serve *ServerDocumentationCmd `arg:"subcommand:serve" help:"Generate and serve the documentation server"`
|
||||||
|
Generate *GenerateDocumentationCmd `arg:"subcommand:generate" help:"Generate documentation to file"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AppArgs struct {
|
type AppArgs struct {
|
||||||
Server *ServerCmd `arg:"subcommand:server" help:"Start the api server"`
|
Server *ServerCmd `arg:"subcommand:server" help:"Start the api server"`
|
||||||
ServerDocumentation *ServerDocumentationCmd `arg:"subcommand:server-docs" help:"Generate documentation for api server and start documentation server"`
|
Docs *DocsCmd `arg:"subcommand:docs" help:"Generate documentation to file or run documentation server"`
|
||||||
Migration *Migration `arg:"subcommand:migration" help:"Migration utils"`
|
Migration *Migration `arg:"subcommand:migration" help:"Migration utils"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/go-chi/chi/v5/middleware"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ResponseErr struct {
|
type ResponseErr struct {
|
||||||
@@ -23,7 +23,7 @@ type ResponseErrBuilder interface {
|
|||||||
WithStatusCode(int) ResponseErrBuilder
|
WithStatusCode(int) ResponseErrBuilder
|
||||||
WithTrace(string) ResponseErrBuilder
|
WithTrace(string) ResponseErrBuilder
|
||||||
Ready() ResponseErrReadyToSend
|
Ready() ResponseErrReadyToSend
|
||||||
Send(http.ResponseWriter, *http.Request) error
|
Send(ctx *gin.Context) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type responseErrBuilder struct {
|
type responseErrBuilder struct {
|
||||||
@@ -58,11 +58,13 @@ func (r readyResponseErr) Send(response http.ResponseWriter) error {
|
|||||||
|
|
||||||
func (r responseErrBuilder) WithTrace(s string) ResponseErrBuilder {
|
func (r responseErrBuilder) WithTrace(s string) ResponseErrBuilder {
|
||||||
r.trace = s
|
r.trace = s
|
||||||
|
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r responseErrBuilder) WithStatusCode(i int) ResponseErrBuilder {
|
func (r responseErrBuilder) WithStatusCode(i int) ResponseErrBuilder {
|
||||||
r.status = i
|
r.status = i
|
||||||
|
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,11 +74,13 @@ func NewResponseErrBuilder() ResponseErrBuilder {
|
|||||||
|
|
||||||
func (r responseErrBuilder) WithDetails(m map[string]any) ResponseErrBuilder {
|
func (r responseErrBuilder) WithDetails(m map[string]any) ResponseErrBuilder {
|
||||||
r.details = m
|
r.details = m
|
||||||
|
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r responseErrBuilder) WithMessage(s string) ResponseErrBuilder {
|
func (r responseErrBuilder) WithMessage(s string) ResponseErrBuilder {
|
||||||
r.message = s
|
r.message = s
|
||||||
|
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,11 +96,12 @@ func (r responseErrBuilder) Ready() ResponseErrReadyToSend {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r responseErrBuilder) Send(response http.ResponseWriter, request *http.Request) error {
|
func (r responseErrBuilder) Send(ginCtx *gin.Context) error {
|
||||||
if r.ready == nil {
|
if r.ready == nil {
|
||||||
r.ready = &ResponseErr{
|
r.ready = &ResponseErr{
|
||||||
Message: r.message,
|
Message: r.message,
|
||||||
Trace: middleware.GetReqID(request.Context()),
|
// TODO get traceID from gin context
|
||||||
|
Trace: "",
|
||||||
Details: r.details,
|
Details: r.details,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -110,10 +115,10 @@ func (r responseErrBuilder) Send(response http.ResponseWriter, request *http.Req
|
|||||||
r.status = http.StatusInternalServerError
|
r.status = http.StatusInternalServerError
|
||||||
}
|
}
|
||||||
|
|
||||||
response.Header().Set("Content-Type", "application/json")
|
ginCtx.Writer.Header().Set("Content-Type", "application/json")
|
||||||
response.WriteHeader(r.status)
|
ginCtx.Writer.WriteHeader(r.status)
|
||||||
|
|
||||||
_, err = response.Write(format)
|
_, err = ginCtx.Writer.Write(format)
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,8 +75,7 @@ func (c *Connection) listenCloseNotify() {
|
|||||||
))
|
))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
<-c.closeNotify
|
||||||
case <-c.closeNotify:
|
|
||||||
c.logger.Info("Trying to reconnect to rabbit")
|
c.logger.Info("Trying to reconnect to rabbit")
|
||||||
|
|
||||||
dial, dialErr := amqp.Dial(c.connString)
|
dial, dialErr := amqp.Dial(c.connString)
|
||||||
@@ -87,12 +86,10 @@ func (c *Connection) listenCloseNotify() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
c.conn = dial
|
c.conn = dial
|
||||||
|
c.closeNotify = dial.NotifyClose(make(chan *amqp.Error))
|
||||||
|
|
||||||
c.logger.Info("Rabbit connection stabilized")
|
c.logger.Info("Rabbit connection stabilized")
|
||||||
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
time.Sleep(c.reconnectInterval)
|
time.Sleep(c.reconnectInterval)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,14 +2,16 @@
|
|||||||
* @type {import('semantic-release').GlobalConfig}
|
* @type {import('semantic-release').GlobalConfig}
|
||||||
*/
|
*/
|
||||||
module.exports = {
|
module.exports = {
|
||||||
branches: ['master', { name: 'dev', prerelease: false, channel: 'dev'}],
|
branches: ['main'],
|
||||||
plugins: [
|
plugins: [
|
||||||
[
|
[
|
||||||
'@semantic-release/commit-analyzer',
|
'@semantic-release/commit-analyzer',
|
||||||
{
|
{
|
||||||
"preset": "angular",
|
"preset": "conventionalcommits",
|
||||||
"releaseRules": [
|
"releaseRules": [
|
||||||
{"type": "docs", "scope": "README", "release": "patch"},
|
{"type": "docs", "scope": "README", "release": "patch"},
|
||||||
|
{"type": "feat", scope: "ci", release: "patch"},
|
||||||
|
{"type": "feature", scope: "ci", release: "patch"},
|
||||||
{"type": "refactor", "release": "patch"},
|
{"type": "refactor", "release": "patch"},
|
||||||
{"type": "style", "release": "patch"}
|
{"type": "style", "release": "patch"}
|
||||||
],
|
],
|
||||||
@@ -18,11 +20,39 @@ module.exports = {
|
|||||||
[
|
[
|
||||||
'@semantic-release/release-notes-generator',
|
'@semantic-release/release-notes-generator',
|
||||||
{
|
{
|
||||||
"preset": "angular",
|
"preset": "conventionalcommits",
|
||||||
|
"presetConfig": {
|
||||||
|
types: [
|
||||||
|
{"type": "breaking", "section": "Major version release", "hidden": false},
|
||||||
|
{"type": "BREAKING", "section": "Major version release", "hidden": false},
|
||||||
|
{"type": "BREAKING CHANGE", "section": "Major version release", "hidden": false},
|
||||||
|
{"type": "BREAKING CHANGES", "section": "Major version release", "hidden": false},
|
||||||
|
{"type": "feat", "section": "Features", "hidden": false},
|
||||||
|
{"type": "fix", "section": "Bug Fixes", "hidden": false},
|
||||||
|
{"type": "hotfix", "section": "Bug Fixes", "hidden": false},
|
||||||
|
{"type": "update", "section": "Updates", "hidden": false},
|
||||||
|
{"type": "upgrade", "section": "Upgrades", "hidden": false},
|
||||||
|
{"type": "docs", "section": "Documentation", "hidden": false},
|
||||||
|
{"type": "build", "section": "CI/CD Changes", "hidden": false},
|
||||||
|
{"type": "ci", "section": "CI/CD Changes", "hidden": false},
|
||||||
|
{"type": "refactor", "section": "Refactoring", "hidden": false},
|
||||||
|
{"type": "perf", "section": "Performance Improvements", "hidden": false}
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
'@semantic-release/changelog',
|
[
|
||||||
|
"@semantic-release/exec",
|
||||||
|
{
|
||||||
|
publishCmd: 'echo -e "${nextRelease.notes}\n\n$(cat CHANGELOG.md)" > CHANGELOG.md'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
'@semantic-release/git',
|
'@semantic-release/git',
|
||||||
|
{
|
||||||
|
"assets": ["CHANGELOG.md"]
|
||||||
|
}
|
||||||
|
],
|
||||||
[
|
[
|
||||||
"@semantic-release/exec",
|
"@semantic-release/exec",
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,63 +0,0 @@
|
|||||||
package auth
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"git.ostiwe.com/ostiwe-com/status/dto"
|
|
||||||
"git.ostiwe.com/ostiwe-com/status/modules/auth"
|
|
||||||
httpApp "git.ostiwe.com/ostiwe-com/status/pkg/http"
|
|
||||||
"git.ostiwe.com/ostiwe-com/status/router/controller"
|
|
||||||
"github.com/go-andiamo/chioas"
|
|
||||||
"github.com/go-chi/chi/v5"
|
|
||||||
"github.com/go-chi/render"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Controller struct {
|
|
||||||
authModule auth.Module
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*Controller) New() controller.Controller {
|
|
||||||
return &Controller{
|
|
||||||
authModule: auth.New(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Controller) plainLogin(w http.ResponseWriter, r *http.Request) {
|
|
||||||
var payload dto.LoginRequest
|
|
||||||
|
|
||||||
if err := render.Bind(r, &payload); err != nil {
|
|
||||||
sendErr := httpApp.NewResponseErrBuilder().WithStatusCode(http.StatusBadRequest).WithMessage(err.Error()).Send(w, r)
|
|
||||||
if sendErr != nil {
|
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
jwtString, err := c.authModule.Proceed(r.Context(), payload.Login, payload.Password)
|
|
||||||
if err != nil {
|
|
||||||
sendErr := httpApp.NewResponseErrBuilder().WithStatusCode(http.StatusBadRequest).WithMessage(err.Error()).Send(w, r)
|
|
||||||
if sendErr != nil {
|
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response := dto.LoginResponse{
|
|
||||||
AccessToken: *jwtString,
|
|
||||||
}
|
|
||||||
|
|
||||||
render.JSON(w, r, response)
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Controller) Group(r chi.Router) {
|
|
||||||
r.Post("/auth/plain", c.plainLogin)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Controller) Documentate() (*chioas.Paths, *chioas.Components) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
72
router/controller/auth/plain.go
Normal file
72
router/controller/auth/plain.go
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
package auth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"git.ostiwe.com/ostiwe-com/status/dto"
|
||||||
|
"git.ostiwe.com/ostiwe-com/status/modules/auth"
|
||||||
|
httpApp "git.ostiwe.com/ostiwe-com/status/pkg/http"
|
||||||
|
"git.ostiwe.com/ostiwe-com/status/router/controller"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PlainAuthController struct {
|
||||||
|
authModule auth.Module
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *PlainAuthController) Handler() gin.HandlerFunc {
|
||||||
|
return func(ginCtx *gin.Context) {
|
||||||
|
var payload dto.LoginRequest
|
||||||
|
|
||||||
|
if err := ginCtx.ShouldBindJSON(&payload); err != nil {
|
||||||
|
sendErr := httpApp.
|
||||||
|
NewResponseErrBuilder().
|
||||||
|
WithStatusCode(http.StatusBadRequest).
|
||||||
|
WithMessage(err.Error()).
|
||||||
|
Send(ginCtx)
|
||||||
|
if sendErr != nil {
|
||||||
|
ginCtx.Writer.WriteHeader(http.StatusInternalServerError)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
jwtString, err := c.authModule.Proceed(ginCtx.Request.Context(), payload.Login, payload.Password)
|
||||||
|
if err != nil {
|
||||||
|
sendErr := httpApp.
|
||||||
|
NewResponseErrBuilder().
|
||||||
|
WithStatusCode(http.StatusBadRequest).
|
||||||
|
WithMessage(err.Error()).
|
||||||
|
Send(ginCtx)
|
||||||
|
if sendErr != nil {
|
||||||
|
ginCtx.Writer.WriteHeader(http.StatusInternalServerError)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response := dto.LoginResponse{
|
||||||
|
AccessToken: *jwtString,
|
||||||
|
}
|
||||||
|
|
||||||
|
ginCtx.JSON(http.StatusOK, response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *PlainAuthController) Method() string {
|
||||||
|
return http.MethodPost
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *PlainAuthController) Path() string {
|
||||||
|
return "/api/v1/auth"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*PlainAuthController) New() controller.Controller {
|
||||||
|
return &PlainAuthController{
|
||||||
|
authModule: auth.New(),
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,12 +1,24 @@
|
|||||||
package controller
|
package controller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/go-andiamo/chioas"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/go-chi/chi/v5"
|
"github.com/swaggest/openapi-go"
|
||||||
|
"github.com/swaggest/openapi-go/openapi3"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// SecuredController - means, controller has middlewares
|
||||||
|
// Maybe should rename it later
|
||||||
|
type SecuredController interface {
|
||||||
|
Middlewares() []gin.HandlerFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
type DocumentateController interface {
|
||||||
|
Documentate(r *openapi3.Reflector) openapi.OperationContext
|
||||||
|
}
|
||||||
|
|
||||||
type Controller interface {
|
type Controller interface {
|
||||||
New() Controller
|
New() Controller
|
||||||
Group(r chi.Router)
|
Handler() gin.HandlerFunc
|
||||||
Documentate() (*chioas.Paths, *chioas.Components)
|
Method() string
|
||||||
|
Path() string
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,53 +5,50 @@ import (
|
|||||||
|
|
||||||
"git.ostiwe.com/ostiwe-com/status/modules/log"
|
"git.ostiwe.com/ostiwe-com/status/modules/log"
|
||||||
"git.ostiwe.com/ostiwe-com/status/router/controller"
|
"git.ostiwe.com/ostiwe-com/status/router/controller"
|
||||||
"github.com/go-andiamo/chioas"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/go-chi/chi/v5"
|
"github.com/swaggest/openapi-go"
|
||||||
|
"github.com/swaggest/openapi-go/openapi3"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Controller struct {
|
type Controller struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Controller) Method() string {
|
||||||
|
return http.MethodGet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Controller) Path() string {
|
||||||
|
return "/api/v1/ping"
|
||||||
|
}
|
||||||
|
|
||||||
func (*Controller) New() controller.Controller {
|
func (*Controller) New() controller.Controller {
|
||||||
return &Controller{}
|
return &Controller{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) Group(r chi.Router) {
|
func (c *Controller) Handler() gin.HandlerFunc {
|
||||||
|
return func(ginCtx *gin.Context) {
|
||||||
r.Get("/ping", c.PingHandler)
|
_, err := ginCtx.Writer.Write([]byte("pong"))
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Controller) PingHandler(w http.ResponseWriter, _ *http.Request) {
|
|
||||||
_, err := w.Write([]byte("pong"))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Global.Get(log.SERVER).Error(err)
|
log.Global.Get(log.SERVER).Error(err)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) Documentate() (*chioas.Paths, *chioas.Components) {
|
func (c *Controller) Documentate(r *openapi3.Reflector) openapi.OperationContext {
|
||||||
return &chioas.Paths{
|
op, err := r.NewOperationContext(c.Method(), c.Path())
|
||||||
"/ping": chioas.Path{
|
if err != nil {
|
||||||
Methods: map[string]chioas.Method{
|
return nil
|
||||||
http.MethodGet: {
|
}
|
||||||
Handler: c.PingHandler,
|
|
||||||
Responses: chioas.Responses{
|
|
||||||
http.StatusOK: {
|
|
||||||
ContentType: "plain/text",
|
|
||||||
Schema: chioas.Schema{Type: "string"},
|
|
||||||
Examples: chioas.Examples{
|
|
||||||
{
|
|
||||||
|
|
||||||
Name: "200 OK",
|
op.SetDescription("Route for check service is alive")
|
||||||
Value: "pong",
|
op.SetSummary("Server ping")
|
||||||
},
|
|
||||||
},
|
op.AddRespStructure("pong", func(cu *openapi.ContentUnit) {
|
||||||
},
|
cu.ContentType = "plain/text"
|
||||||
},
|
cu.HTTPStatus = http.StatusOK
|
||||||
},
|
})
|
||||||
},
|
|
||||||
Tag: "service",
|
return op
|
||||||
Comment: "Route for check service is alive",
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
30
router/controller/service/common.go
Normal file
30
router/controller/service/common.go
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"git.ostiwe.com/ostiwe-com/status/modules/log"
|
||||||
|
http2 "git.ostiwe.com/ostiwe-com/status/pkg/http"
|
||||||
|
"git.ostiwe.com/ostiwe-com/status/repository"
|
||||||
|
"git.ostiwe.com/ostiwe-com/status/transform"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func processGetServicesHandler(c *gin.Context, publicOnly bool, serviceRepository repository.Service) {
|
||||||
|
items, err := serviceRepository.All(c.Request.Context(), -1, 0, publicOnly)
|
||||||
|
if err != nil {
|
||||||
|
log.Global.Get(log.SERVER).Error(err)
|
||||||
|
|
||||||
|
writeErr := http2.NewResponseErrBuilder().
|
||||||
|
WithMessage("Fetch service error").
|
||||||
|
WithStatusCode(http.StatusInternalServerError).
|
||||||
|
Send(c)
|
||||||
|
if writeErr != nil {
|
||||||
|
log.Global.Get(log.SERVER).Error(writeErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, transform.PublicServices(items...))
|
||||||
|
}
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"git.ostiwe.com/ostiwe-com/status/modules/jwt"
|
|
||||||
"git.ostiwe.com/ostiwe-com/status/modules/log"
|
|
||||||
http2 "git.ostiwe.com/ostiwe-com/status/pkg/http"
|
|
||||||
"git.ostiwe.com/ostiwe-com/status/repository"
|
|
||||||
"git.ostiwe.com/ostiwe-com/status/router/controller"
|
|
||||||
"git.ostiwe.com/ostiwe-com/status/router/midlleware"
|
|
||||||
"git.ostiwe.com/ostiwe-com/status/transform"
|
|
||||||
"github.com/go-andiamo/chioas"
|
|
||||||
"github.com/go-chi/chi/v5"
|
|
||||||
"github.com/go-chi/jwtauth/v5"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Controller struct {
|
|
||||||
serviceRepository repository.Service
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Controller) New() controller.Controller {
|
|
||||||
return &Controller{
|
|
||||||
serviceRepository: repository.NewServiceRepository(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Controller) Group(r chi.Router) {
|
|
||||||
c.public(r)
|
|
||||||
c.internal(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Controller) public(r chi.Router) {
|
|
||||||
r.Get("/api/public/service", c.GetAllServicesPublic)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Controller) internal(r chi.Router) {
|
|
||||||
r.Group(func(r chi.Router) {
|
|
||||||
r.Use(
|
|
||||||
jwtauth.Verifier(jwt.TokenAuth),
|
|
||||||
jwtauth.Authenticator(jwt.TokenAuth),
|
|
||||||
midlleware.SetUserFromJWT,
|
|
||||||
)
|
|
||||||
|
|
||||||
r.Get("/api/v1/service", c.GetAllServices)
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Controller) GetAllServicesPublic(w http.ResponseWriter, r *http.Request) {
|
|
||||||
items, err := c.serviceRepository.All(r.Context(), -1, 0, true)
|
|
||||||
if err != nil {
|
|
||||||
log.Global.Get(log.SERVER).Error(err)
|
|
||||||
|
|
||||||
writeErr := http2.NewResponseErrBuilder().
|
|
||||||
WithMessage("Fetch service error").
|
|
||||||
WithStatusCode(http.StatusInternalServerError).
|
|
||||||
Send(w, r)
|
|
||||||
if writeErr != nil {
|
|
||||||
log.Global.Get(log.SERVER).Error(writeErr)
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = http2.JSON(w, transform.PublicServices(items...), http.StatusOK)
|
|
||||||
if err != nil {
|
|
||||||
log.Global.Get(log.SERVER).Error(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Controller) GetAllServices(w http.ResponseWriter, r *http.Request) {
|
|
||||||
limit, offset, errReady := http2.ExtractLimitOffset(r)
|
|
||||||
if errReady != nil {
|
|
||||||
err := errReady.Send(w)
|
|
||||||
if err != nil {
|
|
||||||
log.Global.Get(log.SERVER).Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
items, err := c.serviceRepository.All(r.Context(), limit, offset, false)
|
|
||||||
if err != nil {
|
|
||||||
log.Global.Get(log.SERVER).Error(err)
|
|
||||||
|
|
||||||
writeErr := http2.NewResponseErrBuilder().
|
|
||||||
WithMessage("Fetch service error").
|
|
||||||
WithStatusCode(http.StatusInternalServerError).
|
|
||||||
Send(w, r)
|
|
||||||
if writeErr != nil {
|
|
||||||
log.Global.Get(log.SERVER).Error(writeErr)
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = http2.JSON(w, items, http.StatusOK)
|
|
||||||
if err != nil {
|
|
||||||
log.Global.Get(log.SERVER).Error(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Controller) Documentate() (*chioas.Paths, *chioas.Components) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
42
router/controller/service/get.go
Normal file
42
router/controller/service/get.go
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"git.ostiwe.com/ostiwe-com/status/modules/jwt"
|
||||||
|
"git.ostiwe.com/ostiwe-com/status/repository"
|
||||||
|
"git.ostiwe.com/ostiwe-com/status/router/controller"
|
||||||
|
"git.ostiwe.com/ostiwe-com/status/router/midlleware"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetServices struct {
|
||||||
|
serviceRepository repository.Service
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GetServices) New() controller.Controller {
|
||||||
|
return &GetServices{
|
||||||
|
serviceRepository: repository.NewServiceRepository(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GetServices) Handler() gin.HandlerFunc {
|
||||||
|
return func(c *gin.Context) {
|
||||||
|
processGetServicesHandler(c, false, g.serviceRepository)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GetServices) Method() string {
|
||||||
|
return http.MethodGet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GetServices) Path() string {
|
||||||
|
return "/api/v1/services"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GetServices) Middlewares() []gin.HandlerFunc {
|
||||||
|
return []gin.HandlerFunc{
|
||||||
|
jwt.AuthMiddleware.MiddlewareFunc(),
|
||||||
|
midlleware.SetUserFromJWT(),
|
||||||
|
}
|
||||||
|
}
|
||||||
33
router/controller/service/public_get.go
Normal file
33
router/controller/service/public_get.go
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"git.ostiwe.com/ostiwe-com/status/repository"
|
||||||
|
"git.ostiwe.com/ostiwe-com/status/router/controller"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PublicGetServicesController struct {
|
||||||
|
serviceRepository repository.Service
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PublicGetServicesController) New() controller.Controller {
|
||||||
|
return &PublicGetServicesController{
|
||||||
|
serviceRepository: repository.NewServiceRepository(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PublicGetServicesController) Handler() gin.HandlerFunc {
|
||||||
|
return func(c *gin.Context) {
|
||||||
|
processGetServicesHandler(c, true, p.serviceRepository)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PublicGetServicesController) Method() string {
|
||||||
|
return http.MethodGet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PublicGetServicesController) Path() string {
|
||||||
|
return "/api/v1/public/services"
|
||||||
|
}
|
||||||
@@ -4,30 +4,46 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"git.ostiwe.com/ostiwe-com/status/modules/jwt"
|
||||||
"git.ostiwe.com/ostiwe-com/status/repository"
|
"git.ostiwe.com/ostiwe-com/status/repository"
|
||||||
"github.com/go-chi/jwtauth/v5"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
func SetUserFromJWT(next http.Handler) http.Handler {
|
type ContextKey string
|
||||||
fn := func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
ctx := r.Context()
|
const (
|
||||||
token, _, err := jwtauth.FromContext(ctx)
|
UserContextKey ContextKey = "user"
|
||||||
|
)
|
||||||
|
|
||||||
|
func SetUserFromJWT() gin.HandlerFunc {
|
||||||
|
return func(c *gin.Context) {
|
||||||
|
ctx := c.Request.Context()
|
||||||
|
token, err := jwt.AuthMiddleware.ParseToken(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteHeader(http.StatusUnauthorized)
|
c.Writer.WriteHeader(http.StatusUnauthorized)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
userRepo := repository.NewUserRepository()
|
userRepo := repository.NewUserRepository()
|
||||||
user, err := userRepo.FindByLogin(ctx, token.Subject())
|
subject, err := token.Claims.GetSubject()
|
||||||
if err != nil || user == nil {
|
if err != nil {
|
||||||
w.WriteHeader(http.StatusUnauthorized)
|
c.Writer.WriteHeader(http.StatusUnauthorized)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx = context.WithValue(ctx, "user", user)
|
user, err := userRepo.FindByLogin(ctx, subject)
|
||||||
next.ServeHTTP(w, r.WithContext(ctx))
|
if err != nil || user == nil {
|
||||||
|
c.Writer.WriteHeader(http.StatusUnauthorized)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = context.WithValue(ctx, UserContextKey, user)
|
||||||
|
|
||||||
|
c.Request = c.Request.WithContext(ctx)
|
||||||
|
|
||||||
|
c.Next()
|
||||||
}
|
}
|
||||||
return http.HandlerFunc(fn)
|
|
||||||
}
|
}
|
||||||
|
|||||||
100
router/server.go
100
router/server.go
@@ -2,100 +2,94 @@ package router
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"maps"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.ostiwe.com/ostiwe-com/status/modules/jwt"
|
||||||
"git.ostiwe.com/ostiwe-com/status/modules/log"
|
"git.ostiwe.com/ostiwe-com/status/modules/log"
|
||||||
"git.ostiwe.com/ostiwe-com/status/router/controller"
|
"git.ostiwe.com/ostiwe-com/status/router/controller"
|
||||||
"git.ostiwe.com/ostiwe-com/status/router/controller/auth"
|
"git.ostiwe.com/ostiwe-com/status/router/controller/auth"
|
||||||
"git.ostiwe.com/ostiwe-com/status/router/controller/ping"
|
"git.ostiwe.com/ostiwe-com/status/router/controller/ping"
|
||||||
"git.ostiwe.com/ostiwe-com/status/router/controller/service"
|
"git.ostiwe.com/ostiwe-com/status/router/controller/service"
|
||||||
"git.ostiwe.com/ostiwe-com/status/version"
|
"git.ostiwe.com/ostiwe-com/status/version"
|
||||||
"github.com/go-andiamo/chioas"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/go-chi/chi/v5"
|
"github.com/swaggest/openapi-go/openapi3"
|
||||||
"github.com/go-chi/chi/v5/middleware"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func getControllers() []controller.Controller {
|
func getControllers() []controller.Controller {
|
||||||
return []controller.Controller{
|
return []controller.Controller{
|
||||||
new(ping.Controller).New(),
|
new(ping.Controller).New(),
|
||||||
new(service.Controller).New(),
|
new(service.GetServices).New(),
|
||||||
new(auth.Controller).New(),
|
new(auth.PlainAuthController).New(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitRoutes() *chi.Mux {
|
func InitRoutes() *gin.Engine {
|
||||||
log.Global.Get(log.SERVER).Info("Setting up routers")
|
log.Global.Get(log.SERVER).Info("Setting up routers")
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
|
|
||||||
httpLogger := middleware.RequestLogger(&middleware.DefaultLogFormatter{Logger: log.Global.Get(log.SERVER), NoColor: false})
|
jwt.Init()
|
||||||
|
|
||||||
r := chi.NewRouter()
|
r := gin.New()
|
||||||
r.Use(httpLogger)
|
|
||||||
r.Use(
|
r.Use(
|
||||||
middleware.RequestID,
|
gin.Recovery(),
|
||||||
middleware.RealIP,
|
gin.LoggerWithConfig(gin.LoggerConfig{
|
||||||
middleware.StripSlashes,
|
Output: log.Global.Get(log.SERVER).Out,
|
||||||
middleware.Recoverer,
|
}),
|
||||||
middleware.CleanPath,
|
|
||||||
middleware.Timeout(15*time.Second),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
ctrlList := getControllers()
|
ctrlList := getControllers()
|
||||||
for _, ctrl := range ctrlList {
|
for _, ctrl := range ctrlList {
|
||||||
r.Group(ctrl.Group)
|
secured, ok := ctrl.(controller.SecuredController)
|
||||||
|
if ok {
|
||||||
|
r.Handle(
|
||||||
|
ctrl.Method(),
|
||||||
|
ctrl.Path(),
|
||||||
|
append(secured.Middlewares(), ctrl.Handler())...,
|
||||||
|
)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Handle(
|
||||||
|
ctrl.Method(),
|
||||||
|
ctrl.Path(),
|
||||||
|
ctrl.Handler(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Global.Get(log.SERVER).Info(fmt.Sprintf("Initialized %d routers", len(ctrlList)))
|
log.Global.Get(log.SERVER).Info(fmt.Sprintf("Initialized %d routers", len(ctrlList)))
|
||||||
log.Global.Get(log.SERVER).Info(fmt.Sprintf("Setting up routers is done for %dms, start server", time.Since(startTime).Milliseconds()))
|
log.Global.Get(log.SERVER).Info(fmt.Sprintf(
|
||||||
|
"Setting up routers is done for %dms, start server",
|
||||||
|
time.Since(startTime).Milliseconds(),
|
||||||
|
))
|
||||||
|
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func Documentate() chioas.Definition {
|
func Documentate() (*openapi3.Spec, error) {
|
||||||
ctrlList := getControllers()
|
ctrlList := getControllers()
|
||||||
apiDoc := chioas.Definition{
|
|
||||||
AutoHeadMethods: true,
|
reflector := &openapi3.Reflector{
|
||||||
DocOptions: chioas.DocOptions{
|
Spec: &openapi3.Spec{
|
||||||
ServeDocs: true,
|
Openapi: "3.0.3",
|
||||||
HideHeadMethods: true,
|
Info: openapi3.Info{
|
||||||
},
|
Title: "OstiweStatus API",
|
||||||
Info: chioas.Info{
|
|
||||||
Version: version.AppVersion(),
|
Version: version.AppVersion(),
|
||||||
Title: "Status page API Documentation",
|
|
||||||
},
|
},
|
||||||
Paths: make(chioas.Paths),
|
|
||||||
Components: &chioas.Components{
|
|
||||||
Schemas: make(chioas.Schemas, 0),
|
|
||||||
Requests: make(chioas.CommonRequests),
|
|
||||||
Responses: make(chioas.CommonResponses),
|
|
||||||
Examples: make(chioas.Examples, 0),
|
|
||||||
Parameters: make(chioas.CommonParameters),
|
|
||||||
SecuritySchemes: make(chioas.SecuritySchemes, 0),
|
|
||||||
Extensions: make(chioas.Extensions),
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, ctrl := range ctrlList {
|
for _, ctrl := range ctrlList {
|
||||||
documentatePaths, components := ctrl.Documentate()
|
documentated, ok := ctrl.(controller.DocumentateController)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if documentatePaths != nil {
|
err := reflector.AddOperation(documentated.Documentate(reflector))
|
||||||
for path, pathDoc := range *documentatePaths {
|
if err != nil {
|
||||||
apiDoc.Paths[path] = pathDoc
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if components != nil {
|
return reflector.Spec, nil
|
||||||
apiDoc.Components.Schemas = append(apiDoc.Components.Schemas, components.Schemas...)
|
|
||||||
apiDoc.Components.Examples = append(apiDoc.Components.Examples, components.Examples...)
|
|
||||||
apiDoc.Components.SecuritySchemes = append(apiDoc.Components.SecuritySchemes, components.SecuritySchemes...)
|
|
||||||
|
|
||||||
maps.Copy(apiDoc.Components.Requests, components.Requests)
|
|
||||||
maps.Copy(apiDoc.Components.Responses, components.Responses)
|
|
||||||
maps.Copy(apiDoc.Components.Parameters, components.Parameters)
|
|
||||||
maps.Copy(apiDoc.Components.Extensions, components.Extensions)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return apiDoc
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ func Run(serverArgs *args.ServerCmd) {
|
|||||||
connect, err := db.Connect()
|
connect, err := db.Connect()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
appLog.Global.Get(appLog.SYSTEM).Error(fmt.Sprintf("Startup server error, failed connect to database: %v", err))
|
appLog.Global.Get(appLog.SYSTEM).Error(fmt.Sprintf("Startup server error, failed connect to database: %v", err))
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,6 +27,7 @@ func Run(serverArgs *args.ServerCmd) {
|
|||||||
scheduler.GlobalAppScheduler, err = scheduler.NewAppScheduler()
|
scheduler.GlobalAppScheduler, err = scheduler.NewAppScheduler()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
appLog.Global.Get(appLog.SYSTEM).Error(fmt.Sprintf("Startup server error, failed create scheduler: %v", err))
|
appLog.Global.Get(appLog.SYSTEM).Error(fmt.Sprintf("Startup server error, failed create scheduler: %v", err))
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,11 +36,13 @@ func Run(serverArgs *args.ServerCmd) {
|
|||||||
|
|
||||||
if err = service.GlobalCheckService.RegisterTasks(context.Background()); err != nil {
|
if err = service.GlobalCheckService.RegisterTasks(context.Background()); err != nil {
|
||||||
appLog.Global.Get(appLog.SYSTEM).Error(fmt.Sprintf("Startup server error, failed create observe jobs: %v", err))
|
appLog.Global.Get(appLog.SYSTEM).Error(fmt.Sprintf("Startup server error, failed create observe jobs: %v", err))
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = scheduler.GlobalAppScheduler.StartJobs(); err != nil {
|
if err = scheduler.GlobalAppScheduler.StartJobs(); err != nil {
|
||||||
appLog.Global.Get(appLog.SYSTEM).Error(fmt.Sprintf("Startup server error, failed start jobs: %v", err))
|
appLog.Global.Get(appLog.SYSTEM).Error(fmt.Sprintf("Startup server error, failed start jobs: %v", err))
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,8 +17,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
httpObserveFailed = errors.New("http observe fail")
|
errHttpObserveFailed = errors.New("http observe fail")
|
||||||
httpObserveMaxTries = errors.New("http observe max tries")
|
|
||||||
|
|
||||||
GlobalCheckService Check
|
GlobalCheckService Check
|
||||||
)
|
)
|
||||||
@@ -111,7 +110,12 @@ func (c *check) Observe(ctx context.Context, srv *model.Service) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *check) RegisterStatus(ctx context.Context, serviceID uint64, status model.StatusCode, meta ResponseMeta) error {
|
func (c *check) RegisterStatus(
|
||||||
|
ctx context.Context,
|
||||||
|
serviceID uint64,
|
||||||
|
status model.StatusCode,
|
||||||
|
meta ResponseMeta,
|
||||||
|
) error {
|
||||||
return c.statusRepository.Add(ctx, model.Status{
|
return c.statusRepository.Add(ctx, model.Status{
|
||||||
ServiceID: serviceID,
|
ServiceID: serviceID,
|
||||||
Status: status,
|
Status: status,
|
||||||
@@ -163,7 +167,7 @@ func (c *check) ObserveHttp(ctx context.Context, service *model.Service) (*Respo
|
|||||||
}
|
}
|
||||||
|
|
||||||
if response.StatusCode != http.StatusOK {
|
if response.StatusCode != http.StatusOK {
|
||||||
return meta, httpObserveFailed
|
return meta, errHttpObserveFailed
|
||||||
}
|
}
|
||||||
|
|
||||||
return meta, nil
|
return meta, nil
|
||||||
|
|||||||
@@ -17,7 +17,9 @@ var (
|
|||||||
func init() {
|
func init() {
|
||||||
appLog.SetGlobalManager(appLog.NewManager())
|
appLog.SetGlobalManager(appLog.NewManager())
|
||||||
appLog.Global.Put(appLog.SYSTEM, logrus.New())
|
appLog.Global.Put(appLog.SYSTEM, logrus.New())
|
||||||
|
}
|
||||||
|
|
||||||
|
func Init() {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
WorkingDir, err = os.Getwd()
|
WorkingDir, err = os.Getwd()
|
||||||
|
|||||||
@@ -1,25 +1,67 @@
|
|||||||
package transform
|
package transform
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"slices"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"git.ostiwe.com/ostiwe-com/status/dto"
|
"git.ostiwe.com/ostiwe-com/status/dto"
|
||||||
"git.ostiwe.com/ostiwe-com/status/model"
|
"git.ostiwe.com/ostiwe-com/status/model"
|
||||||
|
"github.com/samber/lo"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const maxStatuses = 60
|
||||||
|
|
||||||
func PublicServices(items ...model.Service) []dto.PublicService {
|
func PublicServices(items ...model.Service) []dto.PublicService {
|
||||||
result := make([]dto.PublicService, 0, len(items))
|
result := make([]dto.PublicService, 0, len(items))
|
||||||
|
mu := new(sync.Mutex)
|
||||||
|
|
||||||
for _, item := range items {
|
chunked := slices.Chunk(items, 40)
|
||||||
result = append(result, PublicService(item))
|
|
||||||
|
for services := range chunked {
|
||||||
|
wg := new(sync.WaitGroup)
|
||||||
|
wg.Add(len(services))
|
||||||
|
|
||||||
|
for i := range services {
|
||||||
|
go func(_wg *sync.WaitGroup, item model.Service) {
|
||||||
|
defer _wg.Done()
|
||||||
|
|
||||||
|
transformed := PublicService(item)
|
||||||
|
mu.Lock()
|
||||||
|
result = append(result, transformed)
|
||||||
|
mu.Unlock()
|
||||||
|
}(wg, services[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func PublicService(item model.Service) dto.PublicService {
|
func PublicService(item model.Service) dto.PublicService {
|
||||||
|
statuses := make([]model.Status, maxStatuses)
|
||||||
|
itemStatusLen := len(item.Statuses)
|
||||||
|
|
||||||
|
for i := range statuses {
|
||||||
|
if i > itemStatusLen-1 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
statuses[i] = item.Statuses[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range statuses {
|
||||||
|
if statuses[i].Status == "" {
|
||||||
|
statuses[i].Status = model.StatusUncheck
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
slices.Reverse(statuses)
|
||||||
|
|
||||||
return dto.PublicService{
|
return dto.PublicService{
|
||||||
|
ID: int(item.ID),
|
||||||
Name: item.Name,
|
Name: item.Name,
|
||||||
Description: item.PublicDescription,
|
Description: lo.ToPtr(item.PublicDescription),
|
||||||
Statuses: item.Statuses,
|
Statuses: statuses,
|
||||||
Uptime: item.CalculateUptimePercent(),
|
Uptime: item.CalculateUptimePercent(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user