From f3c14cc18daa678a0b2026d7dee67499ae0c9c98 Mon Sep 17 00:00:00 2001
From: Garet Halliday <ghalliday@gfxlabs.io>
Date: Wed, 21 Sep 2022 16:43:16 -0500
Subject: [PATCH] fix potential panic if pggat is configured wrong

---
 Dockerfile                            |  6 +++
 config_data.yml                       |  6 +--
 lib/gat/gatling/client/client.go      | 12 +++---
 lib/gat/gatling/server/server_test.go | 10 +++--
 lib/gat/pool/session/pool.go          | 53 ++++++++++++++++++++-------
 test/Dockerfile                       | 19 ----------
 test/docker-compose.yml               | 11 +++++-
 7 files changed, 70 insertions(+), 47 deletions(-)
 create mode 100644 Dockerfile
 delete mode 100644 test/Dockerfile

diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 00000000..3179a291
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,6 @@
+FROM golang
+
+WORKDIR /wd
+COPY . /wd
+RUN go build ./cmd/cgat
+ENTRYPOINT ["./cgat"]
diff --git a/config_data.yml b/config_data.yml
index f80da562..f339a88b 100644
--- a/config_data.yml
+++ b/config_data.yml
@@ -13,7 +13,7 @@ general:
   admin_password: postgres
 pools:
   simple_db:
-    pool_mode: transaction
+    pool_mode: session
     default_role: primary
     query_parser_enabled: true
     primary_reads_enabled: true
@@ -29,12 +29,12 @@ pools:
         statement_timeout: 0
         database: postgres
         servers:
-          - host: localhost
+          - host: db
             port: 5432
             role: primary
             username: postgres
             password: password
-          - host: localhost
+          - host: db
             role: replica
             port: 5432
             username: postgres
diff --git a/lib/gat/gatling/client/client.go b/lib/gat/gatling/client/client.go
index 79ab36d1..8c6d1b82 100644
--- a/lib/gat/gatling/client/client.go
+++ b/lib/gat/gatling/client/client.go
@@ -266,7 +266,7 @@ func (c *Client) Accept(ctx context.Context) error {
 	c.poolName, ok = params["database"]
 	if !ok {
 		return &pg_error.Error{
-			Severity: pg_error.Fatal,
+			Severity: pg_error.Err,
 			Code:     pg_error.InvalidAuthorizationSpecification,
 			Message:  "param database required",
 		}
@@ -275,7 +275,7 @@ func (c *Client) Accept(ctx context.Context) error {
 	c.username, ok = params["user"]
 	if !ok {
 		return &pg_error.Error{
-			Severity: pg_error.Fatal,
+			Severity: pg_error.Err,
 			Code:     pg_error.InvalidAuthorizationSpecification,
 			Message:  "param user required",
 		}
@@ -286,7 +286,7 @@ func (c *Client) Accept(ctx context.Context) error {
 	if c.conf.General.AdminOnly && !admin {
 		c.log.Debug().Msg("rejected non admin, since admin only mode")
 		return &pg_error.Error{
-			Severity: pg_error.Fatal,
+			Severity: pg_error.Err,
 			Code:     pg_error.InvalidAuthorizationSpecification,
 			Message:  "rejected non admin",
 		}
@@ -319,7 +319,7 @@ func (c *Client) Accept(ctx context.Context) error {
 		passwordResponse = r.Fields.Data
 	default:
 		return &pg_error.Error{
-			Severity: pg_error.Fatal,
+			Severity: pg_error.Err,
 			Code:     pg_error.InvalidAuthorizationSpecification,
 			Message:  fmt.Sprintf("wanted AuthenticationResponse packet, got '%+v'", rsp),
 		}
@@ -342,7 +342,7 @@ func (c *Client) Accept(ctx context.Context) error {
 		pw_hash := messages.Md5HashPassword(c.conf.General.AdminUsername, c.conf.General.AdminPassword, salt[:])
 		if !reflect.DeepEqual(pw_hash, passwordResponse) {
 			return &pg_error.Error{
-				Severity: pg_error.Fatal,
+				Severity: pg_error.Err,
 				Code:     pg_error.InvalidPassword,
 				Message:  "invalid password",
 			}
@@ -351,7 +351,7 @@ func (c *Client) Accept(ctx context.Context) error {
 		pw_hash := messages.Md5HashPassword(c.username, user.Password, salt[:])
 		if !reflect.DeepEqual(pw_hash, passwordResponse) {
 			return &pg_error.Error{
-				Severity: pg_error.Fatal,
+				Severity: pg_error.Err,
 				Code:     pg_error.InvalidPassword,
 				Message:  "invalid password",
 			}
diff --git a/lib/gat/gatling/server/server_test.go b/lib/gat/gatling/server/server_test.go
index b84d529c..3828290a 100644
--- a/lib/gat/gatling/server/server_test.go
+++ b/lib/gat/gatling/server/server_test.go
@@ -8,8 +8,12 @@ import (
 	"gfx.cafe/gfx/pggat/lib/config"
 )
 
-var test_address = "localhost"
-var test_port uint16 = 5432
+var test_server = config.Server{
+	Host: "localhost",
+	Port: 5432,
+}
+
+var test_shard = config.Shard{}
 
 var test_user = config.User{
 	Name:             "postgres",
@@ -19,7 +23,7 @@ var test_user = config.User{
 }
 
 func TestServerDial(t *testing.T) {
-	srv, err := Dial(context.TODO(), test_address, test_port, &test_user, "postgres", test_user.Name, test_user.Password)
+	srv, err := Dial(context.TODO(), &test_user, &test_shard, &test_server)
 	if err != nil {
 		t.Error(err)
 	}
diff --git a/lib/gat/pool/session/pool.go b/lib/gat/pool/session/pool.go
index 7db5b7f3..49354e30 100644
--- a/lib/gat/pool/session/pool.go
+++ b/lib/gat/pool/session/pool.go
@@ -35,14 +35,13 @@ func New(database gat.Database, dialer gat.Dialer, conf *config.Pool, user *conf
 	return p
 }
 
-func (p *Pool) getConnection() gat.Connection {
+func (p *Pool) getConnection() (gat.Connection, error) {
 	select {
 	case c := <-p.servers:
-		return c
+		return c, nil
 	default:
 		shard := p.c.Load().Shards[0]
-		s, _ := p.dialer(context.TODO(), p.user, shard, shard.Servers[0])
-		return s
+		return p.dialer(context.TODO(), p.user, shard, shard.Servers[0])
 	}
 }
 
@@ -50,15 +49,18 @@ func (p *Pool) returnConnection(c gat.Connection) {
 	p.servers <- c
 }
 
-func (p *Pool) getOrAssign(client gat.Client) gat.Connection {
+func (p *Pool) getOrAssign(client gat.Client) (gat.Connection, error) {
 	cid := client.GetId()
 	c, ok := p.assigned.Load(cid)
 	if !ok {
-		get := p.getConnection()
+		get, err := p.getConnection()
+		if err != nil {
+			return nil, err
+		}
 		p.assigned.Store(cid, get)
-		return get
+		return get, err
 	}
-	return c
+	return c, nil
 }
 
 func (p *Pool) GetDatabase() gat.Database {
@@ -83,29 +85,52 @@ func (p *Pool) GetUser() *config.User {
 }
 
 func (p *Pool) GetServerInfo() []*protocol.ParameterStatus {
-	c := p.getConnection()
+	c, err := p.getConnection()
+	if err != nil {
+		return nil
+	}
 	defer p.returnConnection(c)
 	return c.GetServerInfo()
 }
 
 func (p *Pool) Describe(ctx context.Context, client gat.Client, describe *protocol.Describe) error {
-	return p.getOrAssign(client).Describe(client, describe)
+	c, err := p.getOrAssign(client)
+	if err != nil {
+		return err
+	}
+	return c.Describe(client, describe)
 }
 
 func (p *Pool) Execute(ctx context.Context, client gat.Client, execute *protocol.Execute) error {
-	return p.getOrAssign(client).Execute(client, execute)
+	c, err := p.getOrAssign(client)
+	if err != nil {
+		return err
+	}
+	return c.Execute(client, execute)
 }
 
 func (p *Pool) SimpleQuery(ctx context.Context, client gat.Client, query string) error {
-	return p.getOrAssign(client).SimpleQuery(ctx, client, query)
+	c, err := p.getOrAssign(client)
+	if err != nil {
+		return err
+	}
+	return c.SimpleQuery(ctx, client, query)
 }
 
 func (p *Pool) Transaction(ctx context.Context, client gat.Client, query string) error {
-	return p.getOrAssign(client).Transaction(ctx, client, query)
+	c, err := p.getOrAssign(client)
+	if err != nil {
+		return err
+	}
+	return c.Transaction(ctx, client, query)
 }
 
 func (p *Pool) CallFunction(ctx context.Context, client gat.Client, payload *protocol.FunctionCall) error {
-	return p.getOrAssign(client).CallFunction(client, payload)
+	c, err := p.getOrAssign(client)
+	if err != nil {
+		return err
+	}
+	return c.CallFunction(client, payload)
 }
 
 var _ gat.Pool = (*Pool)(nil)
diff --git a/test/Dockerfile b/test/Dockerfile
deleted file mode 100644
index db6c8499..00000000
--- a/test/Dockerfile
+++ /dev/null
@@ -1,19 +0,0 @@
-FROM postgres:14
-
-
-RUN apt-get update && apt-get upgrade
-
-RUN apt-get -y install git build-essential libreadline-dev zlib1g-dev flex bison libxml2-dev libxslt-dev libssl-dev libxml2-utils xsltproc ccache
-
-
-WORKDIR /wd
-RUN chown postgres:postgres /wd
-USER postgres
-RUN git clone https://github.com/postgres/postgres.git
-WORKDIR /wd/postgres
-RUN git checkout REL_14_STABLE
-RUN ./configure
-RUN make
-USER root
-RUN make install
-USER postgres
diff --git a/test/docker-compose.yml b/test/docker-compose.yml
index dac58ba2..d10f7f8e 100644
--- a/test/docker-compose.yml
+++ b/test/docker-compose.yml
@@ -2,12 +2,19 @@ version: '3.9'
 
 services:
   db:
-    build: .
+    image: postgres
     restart: always
     environment:
-      POSTGRES_PASSWORD: example
+      POSTGRES_PASSWORD: exmaple
+    ports:
+      - 5432:5432
   adminer:
     image: adminer
     restart: always
     ports:
       - 8080:8080
+  pggat:
+    build: ../
+    restart: always
+    ports:
+      - 6432:6432
-- 
GitLab