Merge pull request 'topic/cleaning' (#4) from topic/cleaning into master
Reviewed-on: #4
This commit is contained in:
commit
dee68080d7
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -15,6 +15,9 @@
|
||||||
# Dependency directories (remove the comment below to include it)
|
# Dependency directories (remove the comment below to include it)
|
||||||
# vendor/
|
# vendor/
|
||||||
|
|
||||||
|
# Output directories
|
||||||
|
bins/
|
||||||
|
|
||||||
# ---> macOS
|
# ---> macOS
|
||||||
# General
|
# General
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
FROM golang:alpine as builder
|
|
||||||
|
|
||||||
RUN mkdir -p /go/src/app
|
|
||||||
WORKDIR /go/src/app
|
|
||||||
|
|
||||||
ADD . /go/src/app
|
|
||||||
|
|
||||||
RUN go get -d -v
|
|
14
Makefile
Normal file
14
Makefile
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
build:
|
||||||
|
docker-compose build
|
||||||
|
|
||||||
|
up: build
|
||||||
|
docker-compose up
|
||||||
|
|
||||||
|
build-binary:
|
||||||
|
go mod download
|
||||||
|
GOOS=linux GOARCH=amd64 go build -o bins/genityapp -v cmd/*
|
||||||
|
|
||||||
|
run: build-binary up
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: build-binary run build up
|
13
README.md
13
README.md
|
@ -1,6 +1,15 @@
|
||||||
|
|
||||||
|
|
||||||
Just basic golang and postgres docker poc.
|
#How to run this project
|
||||||
|
|
||||||
|
##Navigate to root of project, run following command
|
||||||
|
`make run`
|
||||||
|
|
||||||
|
###API interfacing
|
||||||
|
* Get request
|
||||||
|
`curl http://localhost:5000/get-data?title=shahzad`
|
||||||
|
* Post request
|
||||||
|
`curl --request POST 'http://localhost:5000/post-data' --data "title=shahzad"`
|
||||||
|
|
||||||
To build docker compose
|
To build docker compose
|
||||||
`docker-compose up --build`
|
`docker-compose up --build`
|
||||||
|
@ -10,6 +19,6 @@ To run docker compose
|
||||||
|
|
||||||
|
|
||||||
To connect with psql using following command
|
To connect with psql using following command
|
||||||
`docker exec -it poc-golang-postgres-docker_db_1 psql -U root_user -W db_genity`
|
`docker exec -it genitywebapp_db_1 psql -U root_user -W db_genity`
|
||||||
|
|
||||||
|
|
||||||
|
|
8
build/Dockerfile
Normal file
8
build/Dockerfile
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
FROM golang:alpine as builder
|
||||||
|
|
||||||
|
|
||||||
|
ADD bins/genityapp /etc/local/genityapp
|
||||||
|
|
||||||
|
WORKDIR /etc/local/
|
||||||
|
|
||||||
|
ENTRYPOINT ["./genityapp"]
|
22
cmd/main.go
Normal file
22
cmd/main.go
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"domain/genityapp/internal/app"
|
||||||
|
"fmt"
|
||||||
|
_ "github.com/lib/pq"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
app.InitDb()
|
||||||
|
|
||||||
|
defer app.CloseDB()
|
||||||
|
|
||||||
|
http.HandleFunc("/get-data", app.UserGetHandler)
|
||||||
|
http.HandleFunc("/post-data", app.UserPostHandler)
|
||||||
|
|
||||||
|
fmt.Println("Listening on :5000")
|
||||||
|
log.Fatal(http.ListenAndServe(":5000", nil))
|
||||||
|
|
||||||
|
}
|
3
configs/db.env
Normal file
3
configs/db.env
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
POSTGRES_DB=db_genity
|
||||||
|
POSTGRES_USER=root_user
|
||||||
|
POSTGRES_PASSWORD=shahzad12
|
5
configs/web.env
Normal file
5
configs/web.env
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
dbhost=genitywebapp_db_1
|
||||||
|
dbport=5432
|
||||||
|
dbuser=root_user
|
||||||
|
dbpass=shahzad12
|
||||||
|
dbname=db_genity
|
4
db_dump
4
db_dump
|
@ -1,4 +0,0 @@
|
||||||
CREATE TABLE users ( user_id serial PRIMARY KEY, title VARCHAR ( 50 ) UNIQUE NOT NULL, created_on TIMESTAMP NOT NULL);
|
|
||||||
INSERT INTO users (title,created_on) VALUES('shahzad','2013-06-01');
|
|
||||||
|
|
||||||
|
|
|
@ -1,30 +1,33 @@
|
||||||
version: '3'
|
version: "3"
|
||||||
services:
|
services:
|
||||||
db:
|
db:
|
||||||
image: postgres
|
image: postgres
|
||||||
environment:
|
env_file: ./configs/db.env
|
||||||
POSTGRES_DB: db_genity
|
|
||||||
POSTGRES_USER: root_user
|
|
||||||
POSTGRES_PASSWORD: shahzad12
|
|
||||||
volumes:
|
volumes:
|
||||||
- db_postgres:/var/lib/postgresql/data
|
- db_postgres:/var/lib/postgresql/data
|
||||||
ports:
|
- ./scripts/db/ddl_01.sql:/docker-entrypoint-initdb.d/10_schema.sql
|
||||||
- "5436:5432"
|
- ./scripts/db/dml_01.sql:/docker-entrypoint-initdb.d/20_insert.sql
|
||||||
|
expose:
|
||||||
|
- "5432"
|
||||||
|
restart: always
|
||||||
networks:
|
networks:
|
||||||
- genity_network
|
- genityapp_network
|
||||||
app:
|
web:
|
||||||
build: ""
|
build:
|
||||||
command: [ "go", "run", "main.go","api.go"]
|
context: .
|
||||||
|
dockerfile: build/Dockerfile
|
||||||
|
env_file: ./configs/web.env
|
||||||
ports:
|
ports:
|
||||||
- "8080:8080"
|
- "5000:5000"
|
||||||
|
restart: always
|
||||||
depends_on:
|
depends_on:
|
||||||
- db
|
- db
|
||||||
links:
|
links:
|
||||||
- db
|
- db
|
||||||
networks:
|
networks:
|
||||||
- genity_network
|
- genityapp_network
|
||||||
volumes:
|
volumes:
|
||||||
db_postgres:
|
db_postgres:
|
||||||
networks:
|
networks:
|
||||||
genity_network:
|
genityapp_network:
|
||||||
driver: bridge
|
driver: bridge
|
3
go.mod
3
go.mod
|
@ -1,7 +1,8 @@
|
||||||
module genity-code-review
|
module domain/genityapp
|
||||||
|
|
||||||
go 1.14
|
go 1.14
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/lib/pq v1.8.0
|
github.com/lib/pq v1.8.0
|
||||||
|
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
package main
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
uuid "github.com/nu7hatch/gouuid"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -11,53 +12,81 @@ type User struct {
|
||||||
UserID int
|
UserID int
|
||||||
Title string
|
Title string
|
||||||
CreatedOn time.Time
|
CreatedOn time.Time
|
||||||
|
Uuid string
|
||||||
}
|
}
|
||||||
|
|
||||||
type Users struct {
|
type Users struct {
|
||||||
users []User
|
users []User
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sample request http://localhost:5000/get-data?title=shahzad
|
||||||
|
*/
|
||||||
func UserGetHandler(w http.ResponseWriter, req *http.Request) {
|
func UserGetHandler(w http.ResponseWriter, req *http.Request) {
|
||||||
if req.Method == "GET" {
|
if req.Method == "GET" {
|
||||||
users := Users{}
|
|
||||||
|
|
||||||
err := queryRepos(&users)
|
title, ok := req.URL.Query()["title"]
|
||||||
|
|
||||||
|
if !ok || len(title[0]) < 1 {
|
||||||
|
http.Error(w, "Url Param 'title' is missing", 400)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query()["key"] will return an array of items,
|
||||||
|
// we only want the single item.
|
||||||
|
userTitle := title[0]
|
||||||
|
|
||||||
|
usersData := Users{}
|
||||||
|
|
||||||
|
err := queryRepos(&usersData, userTitle)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, err.Error(), 500)
|
http.Error(w, err.Error(), 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
out, err := json.Marshal(users.users)
|
if len(usersData.users) > 0 {
|
||||||
if err != nil {
|
|
||||||
http.Error(w, err.Error(), 500)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprintf(w, string(out))
|
out, err := json.Marshal(usersData.users)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(w, string(out))
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(w, "User does not exist")
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
fmt.Fprintf(w, "Sorry, only Get methods are supported for thus api.")
|
fmt.Fprintf(w, "Sorry, only Get methods are supported for thus api.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sample request curl --request POST 'http://localhost:5000/post-data' --data "title=shahzad"
|
||||||
|
*/
|
||||||
func UserPostHandler(w http.ResponseWriter, req *http.Request) {
|
func UserPostHandler(w http.ResponseWriter, req *http.Request) {
|
||||||
if req.Method == "POST" {
|
if req.Method == "POST" {
|
||||||
if err := req.ParseForm(); err != nil {
|
if err := req.ParseForm(); err != nil {
|
||||||
fmt.Fprintf(w, "ParseForm() err: %v", err)
|
fmt.Fprintf(w, "ParseForm() err: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uuid, err := uuid.NewV4()
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), 500)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
title := req.FormValue("title")
|
title := req.FormValue("title")
|
||||||
sqlInsert := `
|
|
||||||
INSERT INTO users (title, created_on)
|
|
||||||
VALUES ($1, $2)
|
|
||||||
RETURNING user_id`
|
|
||||||
if len(title) > 0 {
|
if len(title) > 0 {
|
||||||
user_id := 0
|
user_id := 0
|
||||||
row := db.QueryRow(sqlInsert, title, time.Now())
|
row := Db.QueryRow(SqlPostUser, title, time.Now().Format(time.RFC3339), uuid.String())
|
||||||
err := row.Scan(&user_id)
|
err := row.Scan(&user_id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
fmt.Fprintf(w, err.Error())
|
||||||
}
|
}
|
||||||
fmt.Fprintf(w, "user creted")
|
fmt.Fprintf(w, `title=`+title)
|
||||||
} else {
|
} else {
|
||||||
fmt.Fprintf(w, "Invalid data")
|
fmt.Fprintf(w, "Invalid data")
|
||||||
}
|
}
|
||||||
|
@ -66,15 +95,9 @@ RETURNING user_id`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func queryRepos(users *Users) error {
|
func queryRepos(users *Users, userTitle string) error {
|
||||||
rows, err := db.Query(`
|
|
||||||
SELECT
|
rows, err := Db.Query(SqlGetUser, userTitle)
|
||||||
user_id,
|
|
||||||
title,
|
|
||||||
created_on
|
|
||||||
|
|
||||||
FROM users;
|
|
||||||
`)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -85,6 +108,7 @@ func queryRepos(users *Users) error {
|
||||||
&user.UserID,
|
&user.UserID,
|
||||||
&user.Title,
|
&user.Title,
|
||||||
&user.CreatedOn,
|
&user.CreatedOn,
|
||||||
|
&user.Uuid,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
90
internal/app/db.go
Normal file
90
internal/app/db.go
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
dbhost = "dbhost"
|
||||||
|
dbport = "dbport"
|
||||||
|
dbuser = "dbuser"
|
||||||
|
dbpass = "dbpass"
|
||||||
|
dbname = "dbname"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
SqlGetUser = `
|
||||||
|
SELECT
|
||||||
|
user_id,
|
||||||
|
title,
|
||||||
|
created_on,
|
||||||
|
uuid
|
||||||
|
|
||||||
|
FROM users
|
||||||
|
WHERE title=$1;
|
||||||
|
`
|
||||||
|
SqlPostUser = `
|
||||||
|
INSERT INTO users (title, created_on,uuid)
|
||||||
|
VALUES ($1, $2, $3)
|
||||||
|
RETURNING user_id`
|
||||||
|
)
|
||||||
|
|
||||||
|
var Db *sql.DB
|
||||||
|
|
||||||
|
func InitDb() {
|
||||||
|
config := dbConfig()
|
||||||
|
var err error
|
||||||
|
psqlInfo := fmt.Sprintf("postgres://%v:%v@%v:%v/%v?sslmode=disable",
|
||||||
|
config[dbuser], config[dbpass],
|
||||||
|
config[dbhost], config[dbport], config[dbname])
|
||||||
|
|
||||||
|
fmt.Println(psqlInfo)
|
||||||
|
Db, err = sql.Open("postgres", psqlInfo)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
err = Db.Ping()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Println("Successfully connected!")
|
||||||
|
}
|
||||||
|
|
||||||
|
func CloseDB() {
|
||||||
|
Db.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func dbConfig() map[string]string {
|
||||||
|
|
||||||
|
conf := make(map[string]string)
|
||||||
|
|
||||||
|
host, ok := os.LookupEnv(dbhost)
|
||||||
|
if !ok {
|
||||||
|
panic("DBHOST environment variable required but not set")
|
||||||
|
}
|
||||||
|
port, ok := os.LookupEnv(dbport)
|
||||||
|
if !ok {
|
||||||
|
panic("DBPORT environment variable required but not set")
|
||||||
|
}
|
||||||
|
user, ok := os.LookupEnv(dbuser)
|
||||||
|
if !ok {
|
||||||
|
panic("DBUSER environment variable required but not set")
|
||||||
|
}
|
||||||
|
password, ok := os.LookupEnv(dbpass)
|
||||||
|
if !ok {
|
||||||
|
panic("DBPASS environment variable required but not set")
|
||||||
|
}
|
||||||
|
name, ok := os.LookupEnv(dbname)
|
||||||
|
if !ok {
|
||||||
|
panic("DBNAME environment variable required but not set")
|
||||||
|
}
|
||||||
|
|
||||||
|
conf[dbhost] = host
|
||||||
|
conf[dbport] = port
|
||||||
|
conf[dbuser] = user
|
||||||
|
conf[dbpass] = password
|
||||||
|
conf[dbname] = name
|
||||||
|
return conf
|
||||||
|
}
|
66
main.go
66
main.go
|
@ -1,66 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"database/sql"
|
|
||||||
"fmt"
|
|
||||||
_ "github.com/lib/pq"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
var db *sql.DB
|
|
||||||
|
|
||||||
const (
|
|
||||||
dbhost = "DBHOST"
|
|
||||||
dbport = "DBPORT"
|
|
||||||
dbuser = "DBUSER"
|
|
||||||
dbpass = "DBPASS"
|
|
||||||
dbname = "DBNAME"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
initDb()
|
|
||||||
defer db.Close()
|
|
||||||
|
|
||||||
http.HandleFunc("/api/users", UserGetHandler)
|
|
||||||
http.HandleFunc("/api/user", UserPostHandler)
|
|
||||||
|
|
||||||
fmt.Println("Listening on :8080")
|
|
||||||
log.Fatal(http.ListenAndServe(":8080", nil))
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func initDb() {
|
|
||||||
config := dbConfig()
|
|
||||||
var err error
|
|
||||||
psqlInfo := fmt.Sprintf("postgres://%v:%v@%v:%v/%v?sslmode=disable",
|
|
||||||
config[dbuser], config[dbpass],
|
|
||||||
config[dbhost], config[dbport], config[dbname])
|
|
||||||
|
|
||||||
fmt.Println(psqlInfo)
|
|
||||||
db, err = sql.Open("postgres", psqlInfo)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
err = db.Ping()
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
fmt.Println("Successfully connected!")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func dbConfig() map[string]string {
|
|
||||||
conf := make(map[string]string)
|
|
||||||
conf[dbhost] = "poc-golang-postgres-docker_db_1"
|
|
||||||
conf[dbport] = "5432"
|
|
||||||
conf[dbuser] = "root_user"
|
|
||||||
conf[dbpass] = "shahzad12"
|
|
||||||
conf[dbname] = "db_genity"
|
|
||||||
return conf
|
|
||||||
}
|
|
2
scripts/db/ddl_01.sql
Normal file
2
scripts/db/ddl_01.sql
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
CREATE TABLE users (user_id serial PRIMARY KEY, title VARCHAR ( 50 ) UNIQUE NOT NULL,
|
||||||
|
uuid VARCHAR ( 50 ) UNIQUE NOT NULL, created_on TIMESTAMP NOT NULL);
|
1
scripts/db/dml_01.sql
Normal file
1
scripts/db/dml_01.sql
Normal file
|
@ -0,0 +1 @@
|
||||||
|
INSERT INTO users (title,created_on, uuid) VALUES('shahzad','2013-06-01', '8272-28292-287292');
|
Loading…
Reference in a new issue