Commit ac6b00c6 authored by Tikhomirov Kirill Andreevich's avatar Tikhomirov Kirill Andreevich
Browse files

Add more configs && postgres support

parent 6a3c8b78
......@@ -14,7 +14,7 @@
| ENV | Влияние | Пример значения|
|-------|-------|---------|
|SERVERPORT| Порт на котором будут приниматься запросы |:8080|
|SQLITEPATH| Путь к sqlite3 БД |./example.db?parseTime\=true|
|DBPATH| Путь к БД (DSN для SQLite/Postgres) |./example.db?parseTime\=true|
|MINIOHOST| Путь к API Minio |0.0.0.0:9000|
|MINIOUSER| minio-access-key |minio|
|MINIOPASS| minio-secret-key |minio123|
......
......@@ -3,10 +3,9 @@ version: '3.7'
services:
minio:
image: minio/minio:latest
container_name: minio
restart: unless-stopped
command: server --console-address ":9001" /data/
ports:
- "9000:9000"
- "9001:9001"
environment:
MINIO_ROOT_USER: ozontech
MINIO_ROOT_PASSWORD: minio123
......@@ -17,5 +16,74 @@ services:
interval: 30s
timeout: 20s
retries: 3
networks:
- app-network
samokater:
image: samokater:latest
container_name: samokater
build:
context: ./
dockerfile: samokater.Dockerfile
restart: unless-stopped
networks:
- app-network
environment:
SERVERPORT: :8000
DBPATH: user=postgres password=devpass dbname=postgres host=db port=5432 sslmode=disable
MINIOHOST: minio:9000
MINIOUSER: ozontech
MINIOPASS: minio123
depends_on:
- db
- minio
initDB:
image: mingration:latest
container_name: init
environment:
DBPATH: user=postgres password=devpass dbname=postgres host=db port=5432 sslmode=disable
build:
context: ./
dockerfile: mingration.Dockerfile
networks:
- app-network
depends_on:
- db
db:
container_name: db
image: postgres
restart: always
environment:
POSTGRES_PASSWORD: devpass
volumes:
- pg-storage:/var/lib/postgresql/data
networks:
- app-network
nginx:
image: nginx-custom:latest
build:
context: ./
dockerfile: nginx.Dockerfile
restart: unless-stopped
tty: true
container_name: nginx
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
ports:
- 8080:8080
- 9090:9090
networks:
- app-network
depends_on:
- samokater
networks:
app-network:
driver: bridge
volumes:
minio-storage:
pg-storage:
#!/bin/bash
goose postgres "$DBPATH" up
\ No newline at end of file
......@@ -7,6 +7,41 @@ variables:
DOCKER_TLS_CERTDIR: ""
DOCKER_HOST: tcp://localhost:2375
build-go:
stage: build-go
image:
name: golang:latest
script:
- |-
CGO_ENABLED=0 go build \
-installsuffix 'static' \
-o ./app ./
artifacts:
paths:
- app
expire_in: 1 day
when: always
only:
- tags
- deploy
build-container:
stage: build-container
image: gitlab/dind
services:
- docker:stable-dind
script:
- docker build -t back .
- docker login $CI_REGISTRY -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD
- docker tag back $CI_REGISTRY/sudoku-api/back:$CI_COMMIT_SHORT_SHA
- docker push $CI_REGISTRY/sudoku-api/back:$CI_COMMIT_SHORT_SHA
dependencies:
- build-go
when: always
only:
- tags
- deploy
build-js:
stage: build-js
image:
......@@ -26,6 +61,6 @@ deploy-front:
# Логинемся в наш Minio
- mc config host add --insecure deploy $CI_OBJECT_STORAGE $CI_OBJECT_STORAGE_USER $CI_OBJECT_STORAGE_PASSWORD
# И все собранное ранее переносим в наш бакет
- mc cp dist/* deploy/home --insecure -c -r
- mc cp dist/* deploy/static --insecure -c -r
dependencies:
- build-js
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: example-static
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/proxy-body-size: 100m
spec:
rules:
- host: "domain.ru"
http:
paths:
- backend:
serviceName: minio-svc
servicePort: 9000
path: /(.+)
pathType: Prefix
......@@ -21,17 +21,14 @@ kubectl krew upgrade
# Установим плагин в сам K8S
kubectl krew install minio
# Создадим неймспейс для нашего ператора
kubectl create namespace minio
# Инициализируем оператора (Важно заранее убедится в том что у нас есть PVC-провизионер!)
kubectl minio init -n minio
kubectl minio init
# Пробросим порты до Minio с нашего куба до машины
kubectl minio proxy -n minio
# Пробросим порты до Minio-operator с нашего куба до машины
kubectl minio proxy -n minio-operator
# Поднимаем проксю к дашборду minio-svc
kubectl -n minio port-forward service/minio-svc-console 9090:9090
kubectl -n minio-operator port-forward service/minio-svc-console 9090:9090
# Поднимаем прокю к API minio-svc
kubectl -n minio port-forward service/minio-svc-hl 9000:9000
\ No newline at end of file
kubectl -n minio-operator port-forward service/minio-svc-hl 9000:9000
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: minio-cluster
name: home-cluster
nodes:
- role: control-plane
- role: worker
- role: worker
- role: worker
- role: worker
\ No newline at end of file
- role: worker
......@@ -2,10 +2,10 @@
-- +goose StatementBegin
create table if not exists sessions
(
rent_id int not null
rent_id bigint not null
constraint sessions_pk
primary key,
user_id int,
user_id bigint,
started_at timestamp,
completed_at timestamp,
images_before text,
......@@ -15,20 +15,10 @@ create table if not exists sessions
create unique index if not exists sessions_rent_id_uindex
on sessions (rent_id);
create table if not exists users
(
id int not null,
name text not null
);
create unique index if not exists users_id_uindex
on users (id);
-- +goose StatementEnd
-- +goose Down
-- +goose StatementBegin
DROP TABLE if exists sessions;
DROP index if exists sessions_rent_id_uindex;
DROP index if exists users_id_uindex;
-- +goose StatementEnd
FROM gomicro/goose
ADD ./migrations/*.sql /migrations/
ADD entrypoint.sh /migrations/
ENTRYPOINT ["/migrations/entrypoint.sh"]
version: '3.7'
services:
minio:
image: minio/minio:latest
command: server --console-address ":9001" /data/
ports:
- "9000:9000"
- "9001:9001"
environment:
MINIO_ROOT_USER: ozontech
MINIO_ROOT_PASSWORD: minio123
volumes:
- minio-storage:/data
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 30s
timeout: 20s
retries: 3
volumes:
minio-storage:
\ No newline at end of file
---
apiVersion: v1
kind: Service
metadata:
name: minio-svc
namespace: deploy
spec:
ports:
- port: 9000
protocol: TCP
targetPort: 9000
sessionAffinity: None
type: ExternalName
FROM nginx:alpine
COPY nginx.conf /etc/nginx/nginx.conf
\ No newline at end of file
worker_processes 1;
events { worker_connections 1024; }
http {
sendfile on;
upstream docker-minio-api {
server minio:9000;
}
upstream docker-minio-console {
server minio:9001;
}
upstream docker-samokater {
server samokater:8000;
}
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
server {
listen 8080;
underscores_in_headers on;
proxy_pass_request_headers on;
location / {
proxy_pass http://docker-samokater;
}
location /samokater {
proxy_pass http://docker-minio-api;
}
}
server {
listen 9090;
location / {
proxy_pass http://docker-minio-console;
proxy_redirect off;
}
}
}
\ No newline at end of file
FROM gcr.io/distroless/static:nonroot-arm64
LABEL maintainer="Kirill Tikhomirov"
USER nonroot:nonroot
COPY --chown=nonroot:nonroot ./app /app
ENTRYPOINT ["/app"]
......@@ -3,7 +3,7 @@ package main
import (
"log"
"os"
"samokater/internal/db/sqlite"
pgdb "samokater/internal/db/postgres"
"samokater/internal/image_storage/minio_provider"
"samokater/internal/samokater"
)
......@@ -19,7 +19,7 @@ func main() {
log.Fatalln("Init image_storage error: ", err)
}
db, err := sqlite.NewDataBase(os.Getenv("SQLITEPATH"))
db, err := pgdb.NewDataBase(os.Getenv("DBPATH"))
if err != nil {
log.Fatalln("Init db error: ", err)
}
......
......@@ -5,6 +5,8 @@ go 1.16
require (
github.com/dghubble/sling v1.4.0
github.com/gorilla/mux v1.8.0
github.com/jmoiron/sqlx v1.3.4
github.com/lib/pq v1.2.0
github.com/mattn/go-sqlite3 v1.14.8
github.com/minio/minio-go/v7 v7.0.12
github.com/sirupsen/logrus v1.8.1
......
......@@ -5,6 +5,8 @@ github.com/dghubble/sling v1.4.0 h1:/n8MRosVTthvMbwlNZgLx579OGVjUOy3GNEv5BIqAWY=
github.com/dghubble/sling v1.4.0/go.mod h1:0r40aNsU9EdDUVBNhfCstAtFgutjgJGYbO1oNzkMoM8=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
......@@ -16,6 +18,8 @@ github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGa
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/jmoiron/sqlx v1.3.4 h1:wv+0IJZfL5z0uZoUjlpKgHkgaFSYD+r9CfrXjEXsO7w=
github.com/jmoiron/sqlx v1.3.4/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ=
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
......@@ -26,6 +30,9 @@ github.com/klauspost/cpuid v1.3.1/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.8 h1:gDp86IdQsN/xWjIEmr9MF6o9mpksUgh0fu+9ByFxzIU=
github.com/mattn/go-sqlite3 v1.14.8/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/minio/md5-simd v1.1.0 h1:QPfiOqlZH+Cj9teu0t9b1nTBfPbyTl16Of5MeuShdK4=
......
package pgdb
import (
"database/sql"
"log"
"samokater/internal/db"
"samokater/internal/models"
"strings"
"github.com/jmoiron/sqlx"
_ "github.com/lib/pq"
"github.com/sirupsen/logrus"
)
type PGS struct {
db *sqlx.DB
}
func NewDataBase(dbPath string) (db.DB, error) {
db, err := sqlx.Connect(
"postgres",
dbPath)
if err != nil {
log.Fatalln(err)
}
return &PGS{db: db}, err
}
func (s *PGS) CreateNewRentSession(rent models.Rent) error {
_, err := s.db.Exec(create_rent_session, rent.User.ID, rent.RentID)
if err != nil {
logrus.Errorf("Can`t create rent record in db: %v\n", err)
}
return err
}
func (s *PGS) StartRentSession(rent models.Rent) error {
_, err := s.db.Exec(start_rent_session, rent.User.ID, rent.RentID)
if err != nil {
logrus.Errorf("Can`t update rent record in db: %v\n", err)
}
return err
}
func (s *PGS) CompleteRentSession(rent models.Rent) error {
_, err := s.db.Exec(complete_rent_session, rent.User.ID, rent.RentID)
if err != nil {
logrus.Errorf("Can`t update rent record in db: %v\n", err)
}
return err
}
func (s *PGS) GetRentSessions(user models.User) ([]models.Rent, error) {
rentSessionsList := make([]models.Rent, 0)
rows, err := s.db.Query(get_rent_sessions, user.ID)
if err != nil {
logrus.Errorf("Can`t get rent records in db: %v\n", err)
return rentSessionsList, err
}
defer rows.Close()
for rows.Next() {
r := models.Rent{}
var imagesBefore, imagesAfter sql.NullString
var startedAt, completedAt sql.NullTime
err := rows.Scan(&r.RentID, &r.User.ID, &startedAt, &completedAt, &imagesBefore, &imagesAfter)
if err != nil {
logrus.Errorf("Can`t get rent record from rows: %v\n", err)
continue
}
r.StartedAt = startedAt.Time
r.CompletedAt = completedAt.Time
r.RentInfo.ImagesBefore = getArrayFromStr(imagesBefore.String)
r.RentInfo.ImagesAfter = getArrayFromStr(imagesAfter.String)
rentSessionsList = append(rentSessionsList, r)
}
return rentSessionsList, nil
}
func (s *PGS) AddImageRecord(img string, rentID int) error {
// Получаем информацию о сессии аренды
rent, err := s.GetRentStatus(rentID)
if err != nil {
logrus.Errorf("Can`t get rent record in db: %v\n", err)
return err
}
// В зависимости от того были ли загружены фото ДО начала аренды
// Или после добавляем запись в соответствующее поле в БД
if rent.StartedAt.IsZero() {
return s.updateImages(rent.ImagesBefore, img, update_images_before, rentID)
}
return s.updateImages(rent.ImagesAfter, img, update_images_after, rentID)
}
func (s *PGS) GetRentStatus(rentID int) (models.Rent, error) {
rent := models.Rent{}
var imagesBefore, imagesAfter sql.NullString
var startedAt, completedAt sql.NullTime
rows, err := s.db.Query(get_started_at_status, rentID)
if err != nil {
logrus.Errorf("Can`t get rent record in db: %v\n", err)
return rent, err
}
defer rows.Close()
for rows.Next() {
err := rows.Scan(&rent.RentID, &rent.User.ID, &startedAt, &completedAt, &imagesBefore, &imagesAfter)
if err != nil {
logrus.Errorf("Can`t get rent record from rows: %v\n", err)
continue
}
}
rent.StartedAt = startedAt.Time
rent.CompletedAt = completedAt.Time
rent.RentInfo.ImagesBefore = getArrayFromStr(imagesBefore.String)
rent.RentInfo.ImagesAfter = getArrayFromStr(imagesAfter.String)
return rent, err
}
func (s *PGS) updateImages(old []string, new, req string, rentID int) error {
// Добавляем в список старых записей в поле
// новую запись об изображении
old = append(old, new)
new = strings.Join(old, ",")
_, err := s.db.Exec(req, new, rentID)
if err != nil {
logrus.Errorf("Can`t update image record in db: %v\n", err)
}
return err
}
func (s *PGS) Close() {
s.db.Close()
}
func getArrayFromStr(in string) []string {
if in != "" {
return strings.Split(in, ",")
}
return []string{}
}
package pgdb
const (
create_rent_session = "insert into sessions (user_id, rent_id) values ($1, $2)"
start_rent_session = "update sessions set started_at = CURRENT_TIMESTAMP where user_id = $1 and rent_id = $2"
complete_rent_session = "update sessions set completed_at = CURRENT_TIMESTAMP where user_id = $1 and rent_id = $2"
get_rent_sessions = "select * from sessions where rent_id = $1"
get_started_at_status = "select * from sessions where rent_id = $1"
update_images_before = "update sessions set images_before = $1 where rent_id = $2"
update_images_after = "update sessions set images_after = $1 where rent_id = $2"
)
......@@ -80,13 +80,15 @@ func (s *SQLiteDB) GetRentSessions(user models.User) ([]models.Rent, error) {
}
func (s *SQLiteDB) AddImageRecord(img string, rentID int) error {
// Получаем информацию о сессии аренды
rent, err := s.GetRentStatus(rentID)
if err != nil {
logrus.Errorf("Can`t get rent record in db: %v\n", err)
return err
}
// В зависимости от того были ли загружены фото ДО начала аренды
// Или после добавляем запись в соответствующее поле в БД
if rent.StartedAt.IsZero() {
return s.updateImages(rent.ImagesBefore, img, update_images_before, rentID)
}
......@@ -124,7 +126,8 @@ func (s *SQLiteDB) GetRentStatus(rentID int) (models.Rent, error) {
}
func (s *SQLiteDB) updateImages(old []string, new, req string, rentID int) error {
// Добавляем в список старых записей в поле
// новую запись об изображении
old = append(old, new)
new = strings.Join(old, ",")
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment