diff --git a/api/.dockerignore b/api/.dockerignore
index 7513741..2f9c94d 100644
--- a/api/.dockerignore
+++ b/api/.dockerignore
@@ -1,4 +1,5 @@
-config.yml
+.env
+.env.deployment
README.md
.idea
internal
diff --git a/api/.env b/api/.env
new file mode 100644
index 0000000..d5e69e1
--- /dev/null
+++ b/api/.env
@@ -0,0 +1,10 @@
+PORT=8080
+GIN_MODE="debug"#["release", "debug"]
+
+MYSQL_DATABASE="api"#database name
+MYSQL_ROOT_USER="root"#login name
+MYSQL_ROOT_PASSWORD="Root#123"
+MYSQL_HOST="localhost"
+MYSQL_PORT=3306
+
+
diff --git a/api/.env.deployment b/api/.env.deployment
new file mode 100644
index 0000000..614a6a8
--- /dev/null
+++ b/api/.env.deployment
@@ -0,0 +1,9 @@
+PORT="8080"
+GIN_MODE="release"#["release", "debug"]
+
+MYSQL_DATABASE="api"#database name
+MYSQL_ROOT_USER="root"#login name
+MYSQL_ROOT_PASSWORD="changeme" #TODO change me.
+MYSQL_HOST="mysql"
+MYSQL_PORT="3306"
+
diff --git a/api/Dockerfile b/api/Dockerfile
index 774b58c..61d431d 100644
--- a/api/Dockerfile
+++ b/api/Dockerfile
@@ -18,8 +18,6 @@ CMD ["go", "test", "./tests"]
#Stage 2b: Run Api
FROM scratch as release
-#Copy config
-COPY config.deployment.yml ./config.yml
#Copy migration scripts
COPY migrations migrations
#Copy build result to next stage
diff --git a/api/README.md b/api/README.md
index f6ec256..fc048cc 100644
--- a/api/README.md
+++ b/api/README.md
@@ -1,4 +1,20 @@
## TL;DR
-`` docker compose build; `` `` docker compose up ``
-
+Change MYSQL password in .env.deployment
+`` docker compose build; `` `` docker compose up -d``
The api will be exposed to port 8080, access it with `localhost:8080`.
+
+
+## Environment variables
+The docker image will use the following environment variables:
+
+| Key | Default Value | Options |
+|----------------------------------------------------|---------------|--------------------|
+| PORT | "8080" | |
+| GIN_MODE | "release" | "release", "debug" |
+| MYSQL_HOST | "mysql" | |
+| MYSQL_PORT | "3306" | |
+| MYSQL_DATABASE | "api" | |
+| MYSQL_ROOT_USER | "root" | |
+| MYSQL_ROOT_PASSWORD | "changeme" | |
+
+If you use the docker image directly (without our provided docker-compose), you must specify them.
\ No newline at end of file
diff --git a/api/cmd/main.go b/api/cmd/main.go
index f5b153e..ca09e0d 100644
--- a/api/cmd/main.go
+++ b/api/cmd/main.go
@@ -9,9 +9,10 @@ import (
"fmt"
"github.com/gin-gonic/gin"
_ "github.com/go-sql-driver/mysql"
- "github.com/spf13/viper"
+ "github.com/joho/godotenv"
"log"
"net/http"
+ "os"
)
func setupRouter(db *sql.DB) *gin.Engine {
@@ -41,17 +42,17 @@ func setupRouter(db *sql.DB) *gin.Engine {
}
func loadConfig() {
- viper.SetConfigFile("config.yml")
- err := viper.ReadInConfig()
+ err := godotenv.Load(".env")
if err != nil {
- log.Fatal(err.Error())
+ log.Println(fmt.Sprintf("Failed to load .env file: %s", err))
+ log.Println("Environment variables will be used")
}
}
func setupDatabase() *sql.DB {
//Create database if it is not existing yet.
//We might have to remove this if we use an azure database
- scripts.CreateDatabaseIfNotExists(viper.GetString("DATABASE.NAME"))
+ scripts.CreateDatabaseIfNotExists(os.Getenv("MYSQL_DATABASE"))
//Connect to the database
db := scripts.ConnectToDatabase()
//Check if database is online
@@ -73,11 +74,14 @@ func main() {
defer db.Close()
//Set Gin-gonic to debug or release mode
- gin.SetMode(viper.GetString("GIN_MODE"))
+ gin.SetMode(os.Getenv("GIN_MODE"))
//Setup Routes
r := setupRouter(db)
// Listen and Server in 0.0.0.0:8080
- r.Run(fmt.Sprintf(":%d", viper.GetInt("port")))
+ err := r.Run(fmt.Sprintf(":%s", os.Getenv("PORT")))
+ if err != nil {
+ log.Fatal(err.Error())
+ }
}
diff --git a/api/config.deployment.yml b/api/config.deployment.yml
deleted file mode 100644
index b91c431..0000000
--- a/api/config.deployment.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-## PRODUCTIVE CONFIG
-PORT: 8080
-GIN_MODE: release #["release", "debug"]
-DATABASE:
- NAME: api #database name
- USER: root #This login name is just for local deployment. TODO set it in productive deployment
- PASSWORD: Root#123 #This password is just for local deployment. TODO set it in productive deployment
- HOST: mysql
- PORT: 3306
diff --git a/api/config.yml b/api/config.yml
deleted file mode 100644
index cc996b9..0000000
--- a/api/config.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-PORT: 8080
-GIN_MODE: debug #["release", "debug"]
-DATABASE:
- NAME: api #database name
- USER: root #login name
- PASSWORD: Root#123 #This password is of course not production. Just local deployment
- HOST: localhost
- PORT: 3306
-
diff --git a/api/docker-compose.yml b/api/docker-compose.yml
index 1026cf8..9237152 100644
--- a/api/docker-compose.yml
+++ b/api/docker-compose.yml
@@ -1,32 +1,22 @@
#The docker-compose is for local deployment.
-#DON'T USE IT IN PRODUCTION IT CONTAINS HARDCODED PASSWORDS
services:
mysql:
- image: 'bitnami/mysql:8.3.0'
- environment:
- - MYSQL_ROOT_USER=root
- - MYSQL_ROOT_PASSWORD=Root#123
- - MYSQL_DATABASE=api
+ env_file: .env.deployment
+ image: 'mysql:8.4.0'
ports:
- - "3306:3306"
+ - "${MYSQL_PORT}:${MYSQL_PORT}"
volumes:
- ./internal/database:/bitnami/mysql/data
networks:
- api
healthcheck:
- test: mysql --user=root --password=Root#123 -e 'SELECT * FROM mysql.time_zone'
+ test: mysqladmin ping --host=${MYSQL_HOST} --port=${MYSQL_PORT} --user=${MYSQL_ROOT_USER} --password=${MYSQL_ROOT_PASSWORD}
restart: on-failure
- #command: # fix from https://github.com/bitnami/containers/issues/44854#issuecomment-1800945882
- # - "/opt/bitnami/mysql/bin/mysqld"
- # - "--defaults-file=/opt/bitnami/mysql/conf/my.cnf"
- # - "--basedir=/opt/bitnami/mysql"
- # - "--datadir=/bitnami/mysql/data"
- # - "--socket=/opt/bitnami/mysql/tmp/mysql.sock"
- # - "--pid-file=/opt/bitnami/mysql/tmp/mysqld.pid"
api:
+ env_file: .env.deployment
build: .
ports:
- - "8080:8080"
+ - "${PORT}:${PORT}"
restart: on-failure
networks:
- api
diff --git a/api/go.mod b/api/go.mod
index 36cd187..ff57214 100644
--- a/api/go.mod
+++ b/api/go.mod
@@ -8,7 +8,6 @@ require (
github.com/gin-gonic/gin v1.9.1
github.com/go-sql-driver/mysql v1.8.1
github.com/google/uuid v1.4.0
- github.com/spf13/viper v1.18.2
)
require (
@@ -24,6 +23,7 @@ require (
github.com/go-playground/validator/v10 v10.19.0 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
+ github.com/joho/godotenv v1.5.1 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
diff --git a/api/go.sum b/api/go.sum
index d326bfb..7762e57 100644
--- a/api/go.sum
+++ b/api/go.sum
@@ -46,6 +46,8 @@ github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
+github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
+github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kisielk/sqlstruct v0.0.0-20201105191214-5f3e10d3ab46/go.mod h1:yyMNCyc/Ib3bDTKd379tNMpB/7/H5TjM2Y9QJ5THLbE=
diff --git a/api/scripts/databaseScripts.go b/api/scripts/databaseScripts.go
index 4050b15..d0b0379 100644
--- a/api/scripts/databaseScripts.go
+++ b/api/scripts/databaseScripts.go
@@ -4,7 +4,6 @@ import (
"api/shared"
"database/sql"
"fmt"
- "github.com/spf13/viper"
"log"
"os"
"regexp"
@@ -16,11 +15,11 @@ import (
func ConnectToDatabase() *sql.DB {
// connect to db using standard Go database/sql API
connectionString := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s",
- viper.GetString("DATABASE.USER"),
- viper.GetString("DATABASE.PASSWORD"),
- viper.GetString("DATABASE.HOST"),
- viper.GetString("DATABASE.PORT"),
- viper.GetString("DATABASE.NAME"))
+ os.Getenv("MYSQL_ROOT_USER"),
+ os.Getenv("MYSQL_ROOT_PASSWORD"),
+ os.Getenv("MYSQL_HOST"),
+ os.Getenv("MYSQL_PORT"),
+ os.Getenv("MYSQL_DATABASE"))
db, err := sql.Open("mysql", connectionString)
@@ -102,7 +101,7 @@ func MigrateDatabase(db *sql.DB) {
log.Println("Finished migrations")
}
-// getMigrationIds returns the Ids of migrations which have been applied to the database.
+// getMigrationIds returns the Ids of migrations which have been applied to the database
func getMigrationIds(db *sql.DB) []int {
var migrations []int
@@ -133,21 +132,24 @@ func getMigrationIds(db *sql.DB) []int {
func CreateDatabaseIfNotExists(database string) {
// connect to db using standard Go database/sql API
connectionString := fmt.Sprintf("%s:%s@tcp(%s:%s)/",
- viper.GetString("DATABASE.USER"),
- viper.GetString("DATABASE.PASSWORD"),
- viper.GetString("DATABASE.HOST"),
- viper.GetString("DATABASE.PORT"))
+ os.Getenv("MYSQL_ROOT_USER"),
+ os.Getenv("MYSQL_ROOT_PASSWORD"),
+ os.Getenv("MYSQL_HOST"),
+ os.Getenv("MYSQL_PORT"))
db, err := sql.Open("mysql", connectionString)
if err != nil {
- log.Fatal(err)
+ log.Fatal("Error connecting to database: ", err)
}
defer db.Close()
_, err = db.Exec(fmt.Sprintf("Create database if not exists %s", database))
if err != nil {
- log.Fatal(err)
+ if connectionString == ":@tcp(:)/" {
+ log.Println("Environment variables have not been set. See https://github.com/AustrianDataLAB/IndieGameStream/tree/develop/api")
+ }
+ log.Fatal("Error creating database: ", err)
}
return