React Gin Blog (10/19): 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

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: