Brijesh's Git Server — k3yst0n3 @ 90706b0412aaed46082b4bb5e78238a3f1630d06

feat(server): connect to database from server

# Changes Made
- Create basic structure for server
- Setup GORM for use with Postgres

# Details
avoiding use of sql directly to not face same problems as kickstart
Brijesh brijesh@wawdhane.com
Sat, 11 May 2024 15:39:28 +0530
commit

90706b0412aaed46082b4bb5e78238a3f1630d06

parent

95b6130fad85dcb7f7c4a0657b33eef63367ea78

M .air.toml.air.toml

@@ -1,38 +1,55 @@

+# Config file for [Air](https://github.com/cosmtrek/air) in TOML format + +# Working directory +# . or absolute path, please note that the directories following must be under root. root = "." -testdata_dir = "testdata" tmp_dir = "tmp" [build] - args_bin = [] - bin = "./tmp/main" - cmd = "go build -o ./tmp/main ." - delay = 1000 - exclude_dir = ["client", "tmp", "testdata"] - exclude_file = [] - exclude_regex = ["_test.go"] - exclude_unchanged = false - follow_symlink = false - full_bin = "" - include_dir = [] - include_ext = ["go", "tpl", "tmpl", "html"] - kill_delay = "0s" - log = "build-errors.log" - send_interrupt = false - stop_on_error = true +# Just plain old shell command. You could use `make` as well. +cmd = "go build -o ./tmp/main ./server" +# Binary file yields from `cmd`. +bin = "tmp/main" +# Customize binary, can setup environment variables when run your app. +full_bin = "APP_ENV=dev APP_USER=air ./tmp/main" +# Watch these filename extensions. +include_ext = ["go", "tpl", "tmpl", "html"] +# Ignore these filename extensions or directories. +exclude_dir = ["assets", "tmp", "vendor", "frontend/node_modules"] +# Watch these directories if you specified. +include_dir = [] +# Exclude files. +exclude_file = [] +# Exclude specific regular expressions. +exclude_regex = ["_test\\.go"] +# Exclude unchanged files. +exclude_unchanged = true +# Follow symlink for directories +follow_symlink = true +# This log file places in your tmp_dir. +log = "air.log" +# It's not necessary to trigger build each time file changes if it's too frequent. +delay = 1000 # ms +# Stop running old binary when build errors occur. +stop_on_error = true +# Send Interrupt signal before killing process (windows does not support this feature) +send_interrupt = false +# Delay after sending Interrupt signal +kill_delay = 500 # ms +# Add additional arguments when running binary (bin/full_bin). Will run './tmp/main hello world'. +args_bin = ["hello", "world"] + +[log] +# Show log time +time = false [color] - app = "" - build = "yellow" - main = "magenta" - runner = "green" - watcher = "cyan" - -[log] - time = false +# Customize each part's color. If no color found, use the raw app log. +main = "magenta" +watcher = "cyan" +build = "yellow" +runner = "green" [misc] - clean_on_exit = false - -[screen] - clear_on_rebuild = false - +# Delete tmp directory on exit +clean_on_exit = true
M .gitignore.gitignore

@@ -3,3 +3,4 @@ .env

# build k3yst0n3 +tmp
M DockerfileDockerfile

@@ -1,23 +1,8 @@

FROM golang:latest -# Set the current working directory inside the container -WORKDIR /app +WORKDIR /usr/src/app -# Copy go.mod and go.sum files to the workspace -COPY go.mod go.sum ./ +RUN go install github.com/cosmtrek/air@latest -# Download all dependencies -RUN go mod download - -# Copy the source from the current directory to the workspace COPY . . - -# Build the Go app -RUN go build -o main server/main.go - -# Expose port 4000 to the outside world -EXPOSE 4000 - -# Run the app -ENTRYPOINT ["./main"] - +RUN go mod tidy
A database/database.go

@@ -0,0 +1,46 @@

+package database + +import ( + "fmt" + "k3yst0n3/models" + "log" + "os" + + "gorm.io/driver/postgres" + "gorm.io/gorm" + "gorm.io/gorm/logger" +) + +type Dbinstance struct { + Db *gorm.DB +} + +var DB Dbinstance + +func ConnectDb() { + dsn := fmt.Sprintf( + "host=postgres user=%s password=%s dbname=%s port=5432 sslmode=disable TimeZone=Asia/Shanghai", + "test", "test", "test", + // os.Getenv("DB_USER"), + // os.Getenv("DB_PASSWORD"), + // os.Getenv("DB_NAME"), + ) + + db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{ + Logger: logger.Default.LogMode(logger.Info), + }) + if err != nil { + log.Fatal("Failed to connect to database. \n", err) + os.Exit(2) + } + + log.Println("connected") + db.Logger = logger.Default.LogMode(logger.Info) + + log.Println("running migrations") + db.AutoMigrate(&models.Fact{}) + + DB = Dbinstance{ + Db: db, + } +}
M docker-compose.yamldocker-compose.yaml

@@ -1,20 +1,11 @@

services: - postgres: - image: postgres:latest - environment: - - POSTGRES_DB=keystone_db - - POSTGRES_USER=postgres - - POSTGRES_PASSWORD=postgres - restart: always - healthcheck: - test: ["CMD-SHELL", "pg_isready"] - interval: 30s - timeout: 5s - retries: 5 + server: + build: . ports: - - '5432:5432' + - "4000:4000" volumes: - - postgres_volume:/var/lib/postgresql/data + - .:/usr/src/app + command: air ./cmd/main.go -b 0.0.0.0 minio: image: quay.io/minio/minio:latest command: server --console-address ":9001" /data

@@ -25,23 +16,19 @@ - "9001:9001"

expose: - "9000" - "9001" - healthcheck: - test: ["CMD", "mc", "ready", "local"] - interval: 30s - timeout: 5s - retries: 5 volumes: - - minio_volume:/data - k3yst0n3: - hostname: k3yst0n3 - build: . - depends_on: - - postgres - - minio + - minio-volume:/data + postgres: + image: postgres:alpine + environment: + - POSTGRES_USER=test + - POSTGRES_PASSWORD=test + - POSTGRES_DB=test ports: - - 4000:4000 + - "5432:5432" + volumes: + - postgres-volume:/var/lib/postgresql/data volumes: - postgres_volume: - minio_volume: - + minio-volume: + postgres-volume:
M go.modgo.mod

@@ -3,16 +3,26 @@

go 1.22.2 require ( - github.com/golang-jwt/jwt v3.2.2+incompatible // indirect - github.com/labstack/echo/v4 v4.12.0 // indirect + github.com/labstack/echo/v4 v4.12.0 + gorm.io/driver/postgres v1.5.7 + gorm.io/gorm v1.25.10 +) + +require ( + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 // indirect + github.com/jackc/pgx/v5 v5.5.5 // indirect + github.com/jackc/puddle/v2 v2.2.1 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect github.com/labstack/gommon v0.4.2 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect - golang.org/x/crypto v0.22.0 // indirect + golang.org/x/crypto v0.23.0 // indirect golang.org/x/net v0.24.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect - golang.org/x/time v0.5.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/text v0.15.0 // indirect )
M go.sumgo.sum

@@ -1,5 +1,18 @@

-github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= -github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +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= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 h1:L0QtFUgDarD7Fpv9jeVMgy/+Ec0mtnmYuImjTz6dtDA= +github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw= +github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A= +github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= +github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/labstack/echo/v4 v4.12.0 h1:IKpw49IMryVB2p1a4dzwlhP1O2Tf2E0Ir/450lH+kI0= github.com/labstack/echo/v4 v4.12.0/go.mod h1:UP9Cr2DJXbOK3Kr9ONYzNowSh7HP0aG0ShAyycHSJvM= github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=

@@ -9,19 +22,34 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=

github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= -golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= -golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +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/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/driver/postgres v1.5.7 h1:8ptbNJTDbEmhdr62uReG5BGkdQyeasu/FZHxI0IMGnM= +gorm.io/driver/postgres v1.5.7/go.mod h1:3e019WlBaYI5o5LIdNV+LyxCMNtLOQETBXL2h4chKpA= +gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s= +gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
A handlers/facts.go

@@ -0,0 +1,23 @@

+package handlers + +import ( + "k3yst0n3/database" + "k3yst0n3/models" + + "github.com/labstack/echo/v4" +) + +func ListFacts(c echo.Context) error { + facts := []models.Fact{} + database.DB.Db.Find(&facts) + return c.JSON(200, facts) +} + +func CreateFact(c echo.Context) error { + fact := new(models.Fact) + if err := c.Bind(fact); err != nil { + return c.JSON(500, map[string]string{"message": err.Error()}) + } + database.DB.Db.Create(&fact) + return c.JSON(200, fact) +}
M handlers/server.gohandlers/health_check.go

@@ -6,11 +6,11 @@

"github.com/labstack/echo/v4" ) -func HealthCHeckHandler(c echo.Context) error { +func HealthCheckHandler(c echo.Context) error { return c.JSON( http.StatusOK, map[string]string{ - "status": "ok", + "status": "okay", }, ) }
A models/models.go

@@ -0,0 +1,9 @@

+package models + +import "gorm.io/gorm" + +type Fact struct { + gorm.Model + Question string `json:"question" gorm:"text;not null;default:null` + Answer string `json:"answer" gorm:"text;not null;default:null` +}
M server/main.goserver/main.go

@@ -1,15 +1,17 @@

package main import ( - "k3yst0n3/handlers" + "k3yst0n3/database" "github.com/labstack/echo/v4" ) func main() { + database.ConnectDb() + e := echo.New() - e.GET("/health", handlers.HealthCHeckHandler) + setupRoutes(e) e.Logger.Fatal(e.Start(":4000")) }
A server/routes.go

@@ -0,0 +1,15 @@

+package main + +import ( + "k3yst0n3/handlers" + + "github.com/labstack/echo/v4" +) + +func setupRoutes(e *echo.Echo) { + e.GET("/health-check", handlers.HealthCheckHandler) + + e.GET("/facts", handlers.ListFacts) + + e.POST("/fact", handlers.CreateFact) +}