diff --git a/cmd/caddygat/pgbouncer_spilo.go b/cmd/caddygat/pgbouncer_spilo.go deleted file mode 100644 index 306615d9316975b90b1925975c993ecb4d782f44..0000000000000000000000000000000000000000 --- a/cmd/caddygat/pgbouncer_spilo.go +++ /dev/null @@ -1,59 +0,0 @@ -package main - -import ( - "time" - - "github.com/caddyserver/caddy/v2" - "github.com/caddyserver/caddy/v2/caddyconfig" - caddycmd "github.com/caddyserver/caddy/v2/cmd" - - "gfx.cafe/gfx/pggat/lib/gat" - "gfx.cafe/gfx/pggat/lib/gat/handlers/pgbouncer_spilo" - "gfx.cafe/gfx/pggat/lib/util/dur" - - "gfx.cafe/util/go/gun" -) - -func init() { - caddycmd.RegisterCommand(caddycmd.Command{ - Name: "pgbouncer-spilo", - Short: "Runs in pgbouncer-spilo compatibility mode", - Func: runPgbouncerSpilo, - }) -} - -func runPgbouncerSpilo(flags caddycmd.Flags) (int, error) { - caddy.TrapSignals() - - var config pgbouncer_spilo.Config - gun.Load(&config) - - var pggat gat.Config - pggat.StatLogPeriod = dur.Duration(1 * time.Minute) - - var server gat.ServerConfig - server.Listen = config.Listen() - server.Routes = append(server.Routes, gat.RouteConfig{ - Handle: caddyconfig.JSONModuleObject( - pgbouncer_spilo.Module{ - Config: config, - }, - "handler", - "pgbouncer_spilo", - nil, - ), - }) - pggat.Servers = append(pggat.Servers, server) - - caddyConfig := caddy.Config{ - AppsRaw: caddy.ModuleMap{ - "pggat": caddyconfig.JSON(pggat, nil), - }, - } - - if err := caddy.Run(&caddyConfig); err != nil { - return caddy.ExitCodeFailedStartup, err - } - - select {} -} diff --git a/go.mod b/go.mod index ac588dfd480eff2336b20d7f6cc84ebc1b9b8816..706ee3ef0a02205ea95d65c8de93efd4799b8496 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,6 @@ go 1.20 require ( gfx.cafe/ghalliday1/scram v0.0.2 - gfx.cafe/util/go/gun v0.0.0-20230721185457-c559e86c829c github.com/caddyserver/caddy/v2 v2.7.4 github.com/digitalocean/godo v1.102.1 github.com/google/uuid v1.3.0 @@ -23,8 +22,6 @@ require ( github.com/caddyserver/certmagic v0.19.2 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect - github.com/cristalhq/aconfig v0.18.3 // indirect - github.com/cristalhq/aconfig/aconfigdotenv v0.17.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/emicklei/go-restful/v3 v3.9.0 // indirect github.com/go-logr/logr v1.2.4 // indirect @@ -48,7 +45,6 @@ require ( github.com/hashicorp/go-retryablehttp v0.7.4 // indirect github.com/imdario/mergo v0.3.12 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/joho/godotenv v1.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/cpuid/v2 v2.2.5 // indirect diff --git a/go.sum b/go.sum index ba1b8f2a7d3ec5723452673eda401e89cbac9272..91e67319bb9289efbb9802a3f740a5306fbb6e00 100644 --- a/go.sum +++ b/go.sum @@ -37,8 +37,6 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= gfx.cafe/ghalliday1/scram v0.0.2 h1:uuScaL7DUEP/lKWJnA5kKHq5RJev26q8DMbP3gKviAg= gfx.cafe/ghalliday1/scram v0.0.2/go.mod h1:qt6+WJoFcX2id67G5w+/dktBJ56Se0sZAa7WjqfNNu0= -gfx.cafe/util/go/gun v0.0.0-20230721185457-c559e86c829c h1:4XxKaHfYPam36FibTiy1Te7ycfW4+ys08WYyDih5VmU= -gfx.cafe/util/go/gun v0.0.0-20230721185457-c559e86c829c/go.mod h1:zxq7FdmfdrI4oGeze0MPJt9WqdkFj3BDDSAWRuB63JQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -76,11 +74,6 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/cristalhq/aconfig v0.17.0/go.mod h1:NXaRp+1e6bkO4dJn+wZ71xyaihMDYPtCSvEhMTm/H3E= -github.com/cristalhq/aconfig v0.18.3 h1:Or12LIWIF+2mQpcGWA2PQnNc55+WiHFAqRjYh/pQNtM= -github.com/cristalhq/aconfig v0.18.3/go.mod h1:NXaRp+1e6bkO4dJn+wZ71xyaihMDYPtCSvEhMTm/H3E= -github.com/cristalhq/aconfig/aconfigdotenv v0.17.1 h1:HG2ql5fGe4FLL2fUv6o+o0YRyF1mWEcYkNfWGWD82k4= -github.com/cristalhq/aconfig/aconfigdotenv v0.17.1/go.mod h1:gQIKkh+HkVcODvMNz/cLbH65Pk9b0r4tfolCOsI8G9I= 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/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -215,8 +208,6 @@ github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= -github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= diff --git a/lib/gat/gatcaddyfile/handler.go b/lib/gat/gatcaddyfile/handler.go index 316b80ea616630a9a09cf88f00720ddbcbf9fa55..cc8d4255e2d6fcd41204d3ed4acef570f6dc8ba2 100644 --- a/lib/gat/gatcaddyfile/handler.go +++ b/lib/gat/gatcaddyfile/handler.go @@ -1,6 +1,8 @@ package gatcaddyfile import ( + "gfx.cafe/gfx/pggat/lib/gat/handlers/pgbouncer_spilo" + "strconv" "strings" "time" @@ -245,6 +247,121 @@ func init() { } } + return &module, nil + }) + RegisterDirective(Handler, "pgbouncer_spilo", func(d *caddyfile.Dispenser, warnings *[]caddyconfig.Warning) (caddy.Module, error) { + module := pgbouncer_spilo.Module{} + + if !d.NextBlock(d.Nesting()) { + return nil, d.ArgErr() + } + + for { + if d.Val() == "}" { + break + } + + directive := d.Val() + switch directive { + case "host": + if !d.NextArg() { + return nil, d.ArgErr() + } + + module.Host = d.Val() + case "port": + if !d.NextArg() { + return nil, d.ArgErr() + } + + var err error + module.Port, err = strconv.Atoi(d.Val()) + if err != nil { + return nil, d.WrapErr(err) + } + case "user": + if !d.NextArg() { + return nil, d.ArgErr() + } + + module.User = d.Val() + case "schema": + if !d.NextArg() { + return nil, d.ArgErr() + } + + module.Schema = d.Val() + case "password": + if !d.NextArg() { + return nil, d.ArgErr() + } + + module.Password = d.Val() + case "mode": + if !d.NextArg() { + return nil, d.ArgErr() + } + + module.Mode = d.Val() + case "default_size": + if !d.NextArg() { + return nil, d.ArgErr() + } + + var err error + module.DefaultSize, err = strconv.Atoi(d.Val()) + if err != nil { + return nil, d.WrapErr(err) + } + case "min_size": + if !d.NextArg() { + return nil, d.ArgErr() + } + + var err error + module.MinSize, err = strconv.Atoi(d.Val()) + if err != nil { + return nil, d.WrapErr(err) + } + case "reserve_size": + if !d.NextArg() { + return nil, d.ArgErr() + } + + var err error + module.ReserveSize, err = strconv.Atoi(d.Val()) + if err != nil { + return nil, d.WrapErr(err) + } + case "max_client_conn": + if !d.NextArg() { + return nil, d.ArgErr() + } + + var err error + module.MaxClientConn, err = strconv.Atoi(d.Val()) + if err != nil { + return nil, d.WrapErr(err) + } + case "max_db_conn": + if !d.NextArg() { + return nil, d.ArgErr() + } + + var err error + module.MaxDBConn, err = strconv.Atoi(d.Val()) + if err != nil { + return nil, d.WrapErr(err) + } + default: + return nil, d.ArgErr() + } + + if !d.NextLine() { + return nil, d.EOFErr() + } + } + return &module, nil }) } diff --git a/lib/gat/handlers/pgbouncer_spilo/config.go b/lib/gat/handlers/pgbouncer_spilo/config.go index 81dc370759448d31b433483a8df6f8a92cd0d5ba..f303c6eb99b7091d81e6ded8b1ddfabf6e399a53 100644 --- a/lib/gat/handlers/pgbouncer_spilo/config.go +++ b/lib/gat/handlers/pgbouncer_spilo/config.go @@ -1,44 +1,15 @@ package pgbouncer_spilo -import ( - "strconv" - - "github.com/caddyserver/caddy/v2/caddyconfig" - - "gfx.cafe/gfx/pggat/lib/gat" - "gfx.cafe/gfx/pggat/lib/gat/ssl/servers/x509_key_pair" -) - type Config struct { - Host string `json:"host" env:"PGHOST"` - Port int `json:"port" env:"PGPORT"` - User string `json:"user" env:"PGUSER"` - Schema string `json:"schema" env:"PGSCHEMA"` - Password string `json:"password" env:"PGPASSWORD"` - PoolerPort int `json:"pooler_port" env:"CONNECTION_POOLER_PORT"` - PoolerMode string `json:"pooler_mode" env:"CONNECTION_POOLER_MODE"` - PoolerDefaultSize int `json:"pooler_default_size" env:"CONNECTION_POOLER_DEFAULT_SIZE"` - PoolerMinSize int `json:"pooler_min_size" env:"CONNECTION_POOLER_MIN_SIZE"` - PoolerReserveSize int `json:"pooler_reserve_size" env:"CONNECTION_POOLER_RESERVE_SIZE"` - PoolerMaxClientConn int `json:"pooler_max_client_conn" env:"CONNECTION_POOLER_MAX_CLIENT_CONN"` - PoolerMaxDBConn int `json:"pooler_max_db_conn" env:"CONNECTION_POOLER_MAX_DB_CONN"` -} - -func (T Config) Listen() []gat.ListenerConfig { - ssl := caddyconfig.JSONModuleObject( - x509_key_pair.Server{ - CertFile: "/etc/ssl/certs/pgbouncer.crt", - KeyFile: "/etc/ssl/certs/pgbouncer.key", - }, - "provider", - "x509_key_pair", - nil, - ) - - return []gat.ListenerConfig{ - { - Address: ":" + strconv.Itoa(T.PoolerPort), - SSL: ssl, - }, - } + Host string `json:"host"` + Port int `json:"port"` + User string `json:"user"` + Schema string `json:"schema"` + Password string `json:"password"` + Mode string `json:"mode"` + DefaultSize int `json:"default_size"` + MinSize int `json:"min_size"` + ReserveSize int `json:"reserve_size"` + MaxClientConn int `json:"max_client_conn"` + MaxDBConn int `json:"max_db_conn"` } diff --git a/lib/gat/handlers/pgbouncer_spilo/module.go b/lib/gat/handlers/pgbouncer_spilo/module.go index 5a80a19bf9a7a1a8b1d3e48e55123fd6bb79c43a..dc41720b5b91196e3dd19d2f6d636d5dc5412f23 100644 --- a/lib/gat/handlers/pgbouncer_spilo/module.go +++ b/lib/gat/handlers/pgbouncer_spilo/module.go @@ -42,9 +42,7 @@ func (T *Module) Provision(ctx caddy.Context) error { Port: T.Port, AuthUser: T.User, } - pgb.PgBouncer.PoolMode = pgbouncer.PoolMode(T.PoolerMode) - pgb.PgBouncer.ListenPort = T.PoolerPort - pgb.PgBouncer.ListenAddr = "*" + pgb.PgBouncer.PoolMode = pgbouncer.PoolMode(T.Mode) pgb.PgBouncer.AuthType = "md5" pgb.PgBouncer.AuthFile = pgbouncer.AuthFile{ T.User: T.Password, @@ -66,10 +64,10 @@ func (T *Module) Provision(ctx caddy.Context) error { pgb.PgBouncer.LogConnections = 0 pgb.PgBouncer.LogDisconnections = 0 - pgb.PgBouncer.DefaultPoolSize = T.PoolerDefaultSize - pgb.PgBouncer.ReservePoolSize = T.PoolerReserveSize - pgb.PgBouncer.MaxClientConn = T.PoolerMaxClientConn - pgb.PgBouncer.MaxDBConnections = T.PoolerMaxDBConn + pgb.PgBouncer.DefaultPoolSize = T.DefaultSize + pgb.PgBouncer.ReservePoolSize = T.ReserveSize + pgb.PgBouncer.MaxClientConn = T.MaxClientConn + pgb.PgBouncer.MaxDBConnections = T.MaxDBConn pgb.PgBouncer.IdleTransactionTimeout = 600 pgb.PgBouncer.ServerLoginRetry = 5 diff --git a/presets/pgbouncer_spilo.Caddyfile b/presets/pgbouncer_spilo.Caddyfile new file mode 100644 index 0000000000000000000000000000000000000000..b481eff38e34108537ab61fe698fc049ec950f0f --- /dev/null +++ b/presets/pgbouncer_spilo.Caddyfile @@ -0,0 +1,18 @@ +:{$CONNECTION_POOLER_PORT:5432} { + ssl x509_key_pair /etc/ssl/certs/pgbouncer.crt /etc/ssl/certs/pgbouncer.key + require_ssl + + pgbouncer_spilo { + host {$PGHOST} + port {$PGPORT} + user {$PGUSER} + schema {$PGSCHEMA} + password {$PGPASSWORD} + mode {$CONNECTION_POOLER_MODE} + default_size {$CONNECTION_POOLER_DEFAULT_SIZE} + min_size {$CONNECTION_POOLER_MIN_SIZE} + reserve_size {$CONNECTION_POOLER_RESERVE_SIZE} + max_client_conn {$CONNECTION_POOLER_MAX_CLIENT_CONN} + max_db_conn {$CONNECTION_POOLER_MAX_DB_CONN} + } +} \ No newline at end of file