DEV Community

Syed Mohammad Ibrahim
Syed Mohammad Ibrahim

Posted on

How to handle different application environments like Prod, Dev, Test, etc.?

Introduction

There are times when we are in a dilemma as to how to properly use application environments. It gets confusing really fast. I will try to explain the approach (that I see) makes sense.

I will be using Python in this blog, but this implementation is agnostic of the programming language.

Pre-requisites

  1. Python 3.8.x or higher
  2. PyYaml library - To read our YAML configuration files

Lets get started!

  • Create a yaml file just like below
# settings.yml
default: &default
  api_url: "https://example.com/dev"
  aws: &aws
    s3_bucket:
      - my-bucket

dev: &dev
  <<: *default

test: &test
  <<: *default
  api_url: "https://example.com/test"

prod: &prod
  <<: *default
  api_url: "https://prod.example.com/"
  aws:
    <<: *aws
    s3_bucket:
      - my-prod-bucket
Enter fullscreen mode Exit fullscreen mode

In the above yaml, we are using the inheritance to override the configurations for individual environments.

  • To pass the correct configuration, we can leverage argparse which parses command-line arguments for us. The following python script does that.
# main.py
import argparse

def read_cli_arguments():
  arg_parser = argparse.ArgumentParser()
  arg_parser.add_argument(
        "--app-env",
        required=True,
        action="store",
        choices=("prod", "dev", "test"),
        help="Application environment to run in"
    )
  return arg_parser.parse_args()
Enter fullscreen mode Exit fullscreen mode
  • Next, we read the configuration file based on the environment
# main.py
from typing import Dict
import yaml

def read_settings(app_env: str) -> Dict:
  try:
    with open("settings.yml", mode="r", encoding="utf-8") as config:
      configs: Dict = yaml.safe_load(config)
  except yaml.YAMLError as yaml_err:
    print(f"Error occurred while reading the file. Error: {yaml_err}")
    raise
  return configs[app_env]
Enter fullscreen mode Exit fullscreen mode
  • Reading the configuration dictionary is now as easy as
# main.py

settings_prod: Dict = read_settings("prod")
print(f"Prod Configurations: {settings_prod}")

settings_test: Dict = read_settings("test")
print(f"Test Configurations: {settings_test}")
Enter fullscreen mode Exit fullscreen mode
  • Finally, we use this as part of running our main.py file from the command-line like this
$ ls
main.py     settings.yml

$ python3 main.py --app-env prod
Enter fullscreen mode Exit fullscreen mode

Complete Code

# main.py
from typing import Dict
import argparse
import yaml

def read_cli_arguments():
  arg_parser = argparse.ArgumentParser()
  arg_parser.add_argument(
        "--app-env",
        required=True,
        action="store",
        choices=("prod", "dev", "test"),
        help="Application environment to run in"
    )
  return arg_parser.parse_args()

def read_settings(app_env: str) -> Dict:
  try:
    with open("settings.yml", mode="r", encoding="utf-8") as config:
      configs: Dict = yaml.safe_load(config)
  except yaml.YAMLError as yaml_err:
    print(f"Error occurred while reading the file. Error: {yaml_err}")
    raise
  return configs[app_env]


# Program Execution Starts Here
if __name__ == "__main__":
  # Read CLI arguments
  args = read_cli_arguments()

  # Retrieve specific configurations
  settings: Dict = read_settings(app_env=args.app_env)

  print(f"Configs: {settings}")
Enter fullscreen mode Exit fullscreen mode

Executing the above code on the terminal

$ python3 main.py --app-env prod
Configs: {"api_url": "https://prod.example.com/", "aws": {"s3_bucket": ["my-prod-bucket"]}}
Enter fullscreen mode Exit fullscreen mode

Cheers!

Top comments (0)