Compare commits

...

5 Commits

15 changed files with 186 additions and 114 deletions

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="SwaggerSettings">
<option name="defaultPreviewType" value="SWAGGER_UI" />
</component>
</project>

View File

@ -2,10 +2,12 @@ GO := go
PKG_BASE := $(shell head -n 1 go.mod | awk '{print $$2}')
BUILD_TIME := $(shell date -u '+%Y%m%d-%I%M%S')
VERSION := $(shell cat VERSION)+$(shell git rev-parse --short HEAD)
VERSION := $(shell cat VERSION)
GIT_COMMIT := $(shell git rev-parse HEAD)
LDFLAGS += -X $(PKG_BASE)/cmd.BuildTime=$(BUILD_TIME)
LDFLAGS += -X $(PKG_BASE)/cmd.Version=$(VERSION)
LDFLAGS += -X $(PKG_BASE)/cmd.GitCommit=$(GIT_COMMIT)
LDFLAGS += -X $(PKG_BASE)/cmd.SentryDSN=$(shell cat dsn.txt)
LDFLAGS += -s -w

View File

@ -39,20 +39,26 @@ var App = &cli.App{
var (
BuildTime string
Version string
GitCommit string
SentryDSN string
)
func init() {
if BuildTime == "" {
BuildTime = "2022-09-06-01-00-00"
// First Commit
BuildTime = "20220907-153437"
}
App.Compiled = getBuildTime()
if Version == "" {
Version = "0.0.0+None"
Version = "0.0.0"
}
App.Version = Version
if GitCommit == "" {
GitCommit = "out-of-tree"
}
if SentryDSN != "" {
setupSentry()
}
@ -73,7 +79,7 @@ func setupSentry() {
EnableTracing: true,
TracesSampleRate: 1.0,
SendDefaultPII: true,
Release: Version,
Release: GitCommit,
})
if err != nil {
log.Fatalf("sentry.Init: %s", err)

View File

@ -37,10 +37,10 @@ func main() {
Action: wrap(appServer.RunServer),
},
{
Name: "init",
Aliases: []string{"i"},
Usage: "init database",
Action: wrap(appServer.RunServerInit),
Name: "migrate",
Aliases: []string{"m"},
Usage: "migrate database",
Action: wrap(appServer.RunServerMigrate),
},
{
Name: "runner",
@ -94,10 +94,13 @@ func prepareServices(c *cli.Context) *do.Injector {
func wrap(f func(i *do.Injector) error) func(*cli.Context) error {
return func(c *cli.Context) error {
defer func() {
if r := recover(); r != nil {
sentry.CaptureException(r.(error))
sentry.Flush(time.Second * 2)
slog.Printf("Panic Captured: %v", r)
if cmd.SentryDSN != "" {
// only recover when sentry is enabled
if r := recover(); r != nil {
sentry.CaptureException(r.(error))
sentry.Flush(time.Second * 2)
slog.Printf("Panic Captured: %v", r)
}
}
}()

View File

@ -23,7 +23,7 @@ import (
"time"
)
func RunServerInit(i *do.Injector) error {
func RunServerMigrate(i *do.Injector) error {
slog := do.MustInvoke[log.Service](i).GetLogger("app.server")
// Migrate and shutdown database

View File

@ -1,6 +1,7 @@
package log
import (
"git.0x7f.app/WOJ/woj-server/cmd"
"git.0x7f.app/WOJ/woj-server/internal/misc/config"
"git.0x7f.app/WOJ/woj-server/pkg/utils"
"github.com/TheZeroSlave/zapsentry"
@ -48,7 +49,9 @@ func NewService(i *do.Injector) (Service, error) {
return nil, err
}
srv.logger = attachSentry(srv.logger)
if cmd.SentryDSN != "" {
srv.logger = attachSentry(srv.logger)
}
return srv, nil
}

View File

@ -7,11 +7,13 @@ import (
"git.0x7f.app/WOJ/woj-server/internal/misc/config"
"git.0x7f.app/WOJ/woj-server/internal/misc/log"
"git.0x7f.app/WOJ/woj-server/internal/model"
"git.0x7f.app/WOJ/woj-server/pkg/utils"
"github.com/samber/do"
"go.uber.org/zap"
"gorm.io/driver/postgres"
"gorm.io/gorm"
"gorm.io/gorm/schema"
"hash/fnv"
"moul.io/zapgorm2"
"time"
)
@ -108,11 +110,34 @@ func (s *service) setup(conf *model.Config) {
func (s *service) migrateDatabase() {
s.log.Info("Auto Migrating database...")
// Running AutoMigrate concurrently on the same model fails with various race conditions
// https://github.com/go-gorm/gorm/pull/6680
// https://github.com/go-gorm/postgres/pull/224
// Obtain a lock to prevent concurrent AutoMigrate
lockID := func(s string) int64 {
h := fnv.New64a()
_, err := h.Write([]byte(s))
return utils.If(err != nil, int64(0x4242AA55), int64(h.Sum64()))
}("gorm:migrator")
s.err = s.db.Exec("SELECT pg_advisory_lock(?)", lockID).Error
if s.err != nil {
s.log.Error("Failed to obtain lock", zap.Error(s.err))
return
}
_ = s.db.AutoMigrate(&model.User{})
_ = s.db.AutoMigrate(&model.Problem{})
_ = s.db.AutoMigrate(&model.ProblemVersion{})
_ = s.db.AutoMigrate(&model.Submission{})
_ = s.db.AutoMigrate(&model.Status{})
s.err = s.db.Exec("SELECT pg_advisory_unlock(?)", lockID).Error
if s.err != nil {
s.log.Error("Failed to release lock", zap.Error(s.err))
}
}
func (s *service) checkAlive(retry int) (*sql.DB, error) {

View File

@ -10,7 +10,7 @@ import (
)
func (s *service) EnsureDeps(force bool) e.Status {
mark := filepath.Join(Prefix, ".mark.container")
mark := filepath.Join(Prefix, ".mark.image")
if force {
_ = os.Remove(mark)

View File

@ -79,7 +79,7 @@ func (s *service) initRouters(conf *model.Config, injector *do.Injector) *gin.En
r.Use(cors.New(cors.Config{
AllowAllOrigins: true,
AllowMethods: []string{"GET", "POST", "PUT", "OPTIONS"},
AllowHeaders: []string{"Origin", "Content-Length", "Content-Type"},
AllowHeaders: []string{"Authorization", "Origin", "Content-Length", "Content-Type"},
AllowCredentials: true,
}))

View File

@ -1,16 +1,5 @@
---
apiVersion: v1
kind: ConfigMap
metadata:
namespace: woj
name: cache-config
labels:
app: cache
data:
redis.conf: |
requirepass YeT_An0tHeR_VeRy-S3cUr3^PaSsWoRd
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
namespace: woj
@ -45,22 +34,23 @@ spec:
spec:
containers:
- name: cache
image: docker.io/library/redis:7-alpine
image: docker.io/bitnami/redis:7.2
imagePullPolicy: IfNotPresent
ports:
- containerPort: 6379
env:
- name: REDIS_PASSWORD
valueFrom:
configMapKeyRef:
name: shared-config
key: REDIS_PASSWORD
volumeMounts:
- name: cache-vol
mountPath: /data
- name: cache-config
mountPath: /etc/redis/
volumes:
- name: cache-vol
persistentVolumeClaim:
claimName: cache-pvc
- name: cache-config
configMap:
name: cache-config
---
apiVersion: v1
kind: Service

View File

@ -0,0 +1,12 @@
apiVersion: v1
kind: ConfigMap
metadata:
namespace: woj
name: shared-config
data:
POSTGRES_USER: "woj"
POSTGRES_PASSWORD: "A_VeRy-S3cUr3^PaSsWoRd"
POSTGRES_DB: "woj"
MINIO_ROOT_USER: "A_VeRy_CoMpLeX_AcCeSs_KeY"
MINIO_ROOT_PASSWORD: "A_VeRy_CoMpLeX_ScReT_KeY"
REDIS_PASSWORD: "YeT_An0tHeR_VeRy-S3cUr3^PaSsWoRd"

View File

@ -1,17 +1,5 @@
---
apiVersion: v1
kind: ConfigMap
metadata:
namespace: woj
name: db-config
labels:
app: db
data:
POSTGRES_USER: "woj"
POSTGRES_PASSWORD: "A_VeRy-S3cUr3^PaSsWoRd"
POSTGRES_DB: "woj"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
namespace: woj
@ -50,9 +38,22 @@ spec:
imagePullPolicy: IfNotPresent
ports:
- containerPort: 5432
envFrom:
- configMapRef:
name: db-config
env:
- name: POSTGRES_USER
valueFrom:
configMapKeyRef:
name: shared-config
key: POSTGRES_USER
- name: POSTGRES_PASSWORD
valueFrom:
configMapKeyRef:
name: shared-config
key: POSTGRES_PASSWORD
- name: POSTGRES_DB
valueFrom:
configMapKeyRef:
name: shared-config
key: POSTGRES_DB
volumeMounts:
- name: db-vol
mountPath: /var/lib/postgresql/data

View File

@ -1,26 +1,5 @@
---
apiVersion: v1
kind: ConfigMap
metadata:
namespace: woj
name: runner-config
labels:
app: runner
data:
DATABASE_HOST: "db-service.woj.svc.cluster.local"
DATABASE_USER: "woj"
DATABASE_PASSWORD: "A_VeRy-S3cUr3^PaSsWoRd"
DATABASE_NAME: "woj"
REDIS_ADDRESS: "cache-service.woj.svc.cluster.local"
REDIS_PASSWORD: "YeT_An0tHeR_VeRy-S3cUr3^PaSsWoRd"
STORAGE_ENDPOINT: "storage-service.woj.svc.cluster.local:9000"
STORAGE_ACCESS_KEY: "A_VeRy_CoMpLeX_AcCeSs_KeY"
STORAGE_SECRET_KEY: "A_VeRy_CoMpLeX_ScReT_KeY"
STORAGE_BUCKET: "woj"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
namespace: woj
@ -60,9 +39,28 @@ spec:
imagePullPolicy: IfNotPresent
args:
- runner
envFrom:
- configMapRef:
name: runner-config
env:
- name: REDIS_ADDRESS
value: "cache-service.woj.svc.cluster.local"
- name: REDIS_PASSWORD
valueFrom:
configMapKeyRef:
name: shared-config
key: REDIS_PASSWORD
- name: STORAGE_ENDPOINT
value: "storage-service.woj.svc.cluster.local:9000"
- name: STORAGE_ACCESS_KEY
valueFrom:
configMapKeyRef:
name: shared-config
key: MINIO_ROOT_USER
- name: STORAGE_SECRET_KEY
valueFrom:
configMapKeyRef:
name: shared-config
key: MINIO_ROOT_PASSWORD
- name: STORAGE_BUCKET
value: "woj"
securityContext:
privileged: true
volumeMounts:

View File

@ -1,25 +1,4 @@
---
apiVersion: v1
kind: ConfigMap
metadata:
namespace: woj
name: server-config
labels:
app: server
data:
DATABASE_HOST: "db-service.woj.svc.cluster.local"
DATABASE_USER: "woj"
DATABASE_PASSWORD: "A_VeRy-S3cUr3^PaSsWoRd"
DATABASE_NAME: "woj"
REDIS_ADDRESS: "cache-service.woj.svc.cluster.local"
REDIS_PASSWORD: "YeT_An0tHeR_VeRy-S3cUr3^PaSsWoRd"
STORAGE_ENDPOINT: "storage-service.woj.svc.cluster.local:9000"
STORAGE_ACCESS_KEY: "A_VeRy_CoMpLeX_AcCeSs_KeY"
STORAGE_SECRET_KEY: "A_VeRy_CoMpLeX_ScReT_KeY"
STORAGE_BUCKET: "woj"
---
apiVersion: apps/v1
kind: Deployment
metadata:
@ -45,18 +24,69 @@ spec:
imagePullPolicy: IfNotPresent
args:
- init
envFrom:
- configMapRef:
name: server-config
env:
- name: DATABASE_HOST
value: "db-service.woj.svc.cluster.local"
- name: DATABASE_USER
valueFrom:
configMapKeyRef:
name: shared-config
key: POSTGRES_USER
- name: DATABASE_PASSWORD
valueFrom:
configMapKeyRef:
name: shared-config
key: POSTGRES_PASSWORD
- name: DATABASE_NAME
valueFrom:
configMapKeyRef:
name: shared-config
key: POSTGRES_DB
containers:
- name: server
image: git.0x7f.app/woj/woj-server:1.1.0
imagePullPolicy: IfNotPresent
args:
- server
envFrom:
- configMapRef:
name: server-config
env:
- name: DATABASE_HOST
value: "db-service.woj.svc.cluster.local"
- name: DATABASE_USER
valueFrom:
configMapKeyRef:
name: shared-config
key: POSTGRES_USER
- name: DATABASE_PASSWORD
valueFrom:
configMapKeyRef:
name: shared-config
key: POSTGRES_PASSWORD
- name: DATABASE_NAME
valueFrom:
configMapKeyRef:
name: shared-config
key: POSTGRES_DB
- name: REDIS_ADDRESS
value: "cache-service.woj.svc.cluster.local"
- name: REDIS_PASSWORD
valueFrom:
configMapKeyRef:
name: shared-config
key: REDIS_PASSWORD
- name: STORAGE_ENDPOINT
value: "storage-service.woj.svc.cluster.local:9000"
- name: STORAGE_ACCESS_KEY
valueFrom:
configMapKeyRef:
name: shared-config
key: MINIO_ROOT_USER
- name: STORAGE_SECRET_KEY
valueFrom:
configMapKeyRef:
name: shared-config
key: MINIO_ROOT_PASSWORD
- name: STORAGE_BUCKET
value: "woj"
ports:
- containerPort: 8000
---

View File

@ -1,17 +1,5 @@
---
apiVersion: v1
kind: ConfigMap
metadata:
namespace: woj
name: storage-config
labels:
app: storage
data:
MINIO_ROOT_USER: "A_VeRy_CoMpLeX_AcCeSs_KeY"
MINIO_ROOT_PASSWORD: "A_VeRy_CoMpLeX_ScReT_KeY"
MINIO_VOLUMES: "/data"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
namespace: woj
@ -56,9 +44,17 @@ spec:
ports:
- containerPort: 9000
- containerPort: 9001
envFrom:
- configMapRef:
name: storage-config
env:
- name: MINIO_ROOT_USER
valueFrom:
configMapKeyRef:
name: shared-config
key: MINIO_ROOT_USER
- name: MINIO_ROOT_PASSWORD
valueFrom:
configMapKeyRef:
name: shared-config
key: MINIO_ROOT_PASSWORD
volumeMounts:
- name: storage-vol
mountPath: /data