DEV Community

Matija Krajnik
Matija Krajnik

Posted on • Edited on • Originally published at letscode.blog

Server configuration

#go

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)
}
Enter fullscreen mode Exit fullscreen mode

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,
  }
}
Enter fullscreen mode Exit fullscreen mode

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")
}
Enter fullscreen mode Exit fullscreen mode

cmd/rgb/main.go:

package main

import (
  "rgb/internal/conf"
  "rgb/internal/server"
)

func main() {
  server.Start(conf.NewConfig())
}
Enter fullscreen mode Exit fullscreen mode

One more change is required in migrations/main.go file. Just import rgb/internal/conf package and change line

store.SetDBConnection(database.NewDBOptions())
Enter fullscreen mode Exit fullscreen mode

to

store.SetDBConnection(database.NewDBOptions(conf.NewConfig()))
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Top comments (0)