15
Server configuration
Currently we have hardcoded values for server address and port. Same goes for database options required for connecting to our database. That is obviously not a great solution, so let's extract this configuration to ENV variables and add logic to read values from there. First we will create new directory internal/conf/
and there we will create conf.go
file with content:
package conf
import (
"log"
"os"
"strconv"
)
const (
hostKey = "RGB_HOST"
portKey = "RGB_PORT"
dbHostKey = "RGB_DB_HOST"
dbPortKey = "RGB_DB_PORT"
dbNameKey = "RGB_DB_NAME"
dbUserKey = "RGB_DB_USER"
dbPasswordKey = "RGB_DB_PASSWORD"
)
type Config struct {
Host string
Port string
DbHost string
DbPort string
DbName string
DbUser string
DbPassword string
}
func NewConfig() Config {
host, ok := os.LookupEnv(hostKey)
if !ok || host == "" {
logAndPanic(hostKey)
}
port, ok := os.LookupEnv(portKey)
if !ok || port == "" {
if _, err := strconv.Atoi(port); err != nil {
logAndPanic(portKey)
}
}
dbHost, ok := os.LookupEnv(dbHostKey)
if !ok || dbHost == "" {
logAndPanic(dbHostKey)
}
dbPort, ok := os.LookupEnv(dbPortKey)
if !ok || dbPort == "" {
if _, err := strconv.Atoi(dbPort); err != nil {
logAndPanic(dbPortKey)
}
}
dbName, ok := os.LookupEnv(dbNameKey)
if !ok || dbName == "" {
logAndPanic(dbNameKey)
}
dbUser, ok := os.LookupEnv(dbUserKey)
if !ok || dbUser == "" {
logAndPanic(dbUserKey)
}
dbPassword, ok := os.LookupEnv(dbPasswordKey)
if !ok || dbPassword == "" {
logAndPanic(dbPasswordKey)
}
return Config{
Host: host,
Port: port,
DbHost: dbHost,
DbPort: dbPort,
DbName: dbName,
DbUser: dbUser,
DbPassword: dbPassword,
}
}
func logAndPanic(envVar string) {
log.Println("ENV variable not set or value not valid: ", envVar)
panic(envVar)
}
With configuration logic implemented, all that is left to do is use it. For that we will need to slightly refactor our existing code. Our files will then look like this:
internal/database/database.go
:
package database
import (
"rgb/internal/conf"
"github.com/go-pg/pg/v10"
)
func NewDBOptions(cfg conf.Config) *pg.Options {
return &pg.Options{
Addr: cfg.DbHost + ":" + cfg.DbPort,
Database: cfg.DbName,
User: cfg.DbUser,
Password: cfg.DbPassword,
}
}
internal/server/server.go
:
package server
import (
"rgb/internal/conf"
"rgb/internal/database"
"rgb/internal/store"
)
func Start(cfg conf.Config) {
store.SetDBConnection(database.NewDBOptions(cfg))
router := setRouter()
// Start listening and serving requests
router.Run(":8080")
}
cmd/rgb/main.go
:
package main
import (
"rgb/internal/conf"
"rgb/internal/server"
)
func main() {
server.Start(conf.NewConfig())
}
One more change is required in migrations/main.go
file. Just import rgb/internal/conf
package and change line
store.SetDBConnection(database.NewDBOptions())
to
store.SetDBConnection(database.NewDBOptions(conf.NewConfig()))
We are now ready to read ENV variables required for our configuration. But one more thing is missing. We need to feed those values to ENV. To do that let's create new file in root project directory named .env
:
export RGB_HOST=0.0.0.0
export RGB_PORT=8080
export RGB_DB_HOST=localhost
export RGB_DB_PORT=5432
export RGB_DB_NAME=rgb
export RGB_DB_USER=postgres
export RGB_DB_PASSWORD=postgres
We can feed these values to ENV using source
command. So, now we can start our server like this:
source .env
go run cmd/rgb/main.go
15