Overview:

In this step, we will prepare a simple FastAPI application that serves various endpoints for checking the health, configuration and environment variables of the system.

This Python application will be used in subsequent steps for deployment and testing in Kubernetes.

Understanding this application is essential as it forms the foundation for the other steps.

We will go through the application's endpoints, configurations, and how to run it locally.

Application Code:

For the purpose of this tutorial we will be using this artifacts repository https://gitlab.portaone.com:8949/read-only/tutorial-for-simple-application


from fastapi import APIRouter, FastAPI, HTTPException
import os
import yaml
import uvicorn

# Define the base path and configuration path
BASE_PATH = os.getenv("BASE_PATH", "/").rstrip("/")
CONFIG_PATH = os.environ.get("CONFIG_PATH")

# Initialize the FastAPI application with the base path
app = FastAPI(root_path=BASE_PATH)

# Function to read the YAML configuration file
def read_yaml_config():
    if CONFIG_PATH is None:
        raise HTTPException(
            status_code=500,
            detail='"CONFIG_PATH" environment variable is not set',
        )
    if not os.path.isfile(CONFIG_PATH):
        raise HTTPException(
            status_code=500,
            detail=f'Config file not found at "{CONFIG_PATH}"',
        )

    try:
        with open(CONFIG_PATH, 'r') as file:
            config = yaml.safe_load(file)
        return config

    except yaml.YAMLError as e:
        raise HTTPException(
            status_code=500,
            detail=f'Error parsing YAML file: {e}',
        )
    except Exception as e:
        raise HTTPException(
            status_code=500,
            detail=f'An unexpected error occurred: {e}',
        )

# Define the health check endpoint
@app.get("/health")
def health():
    return {"status": "OK"}

# Define the endpoint to read configuration values
@app.get("/config_values")
def read_config():
    return read_yaml_config()

# Define the endpoint to read environment variables
@app.get("/environment_variables")
def read_env():
    env_dict = {key: value for key, value in os.environ.items()}
    return env_dict

# Main function to run the application using uvicorn
if __name__ == "__main__":
    uvicorn.run(
        app,
        host="0.0.0.0",
        port=8000
    )

Key Components:

1. FastAPI Initialization

  • FastAPI(root_path=BASE_PATH): The application is initialized with a root_path to allow flexible endpoint paths in Kubernetes deployments.

  • BASE_PATH: This is the base path for the application, defined by the BASE_PATH environment variable. It defaults to / if not set. This allows you to adjust the endpoint paths dynamically, which is useful when deploying in different environments.

2. Reading Configuration File

  • CONFIG_PATH: This is the path to the YAML configuration file specified in the CONFIG_PATH environment variable. The application reads and parses this file to retrieve configuration values.

  • read_yaml_config(): This function reads the YAML configuration file. It raises an HTTPException if the CONFIG_PATH is not set or if the file cannot be found. This ensures that the application can reliably access its configuration.

3. Endpoints

The application provides the following endpoints:

  • /health: A simple health check endpoint that returns {"status": "OK"}. This is useful for monitoring the application's status and ensuring it is running correctly.

  • /config_values: Returns the parsed YAML configuration from the file specified by CONFIG_PATH. This allows you to view the current configuration settings used by the application.

  • /environment_variables: Returns all environment variables as a dictionary. This is helpful for debugging and understanding the environment in which the application is running.

4. Running the Application

  • uvicorn.run(): The application runs using uvicorn, a fast ASGI server. It listens on host 0.0.0.0 and port 8000, which means it will listen on all active network interfaces, and port 8000, allowing the application to accept incoming requests from any IP address on the specified port

Application Configuration:

To successfully run the application, you need to configure certain environment variables and settings:

  1. Environment Variables:

    • BASE_PATH: Define a base path for the application. The default value is /, but you can set it to something like /api/v1 to adjust endpoint paths in Kubernetes.
    • CONFIG_PATH: Must be set to the path of the YAML configuration file. The application reads and parses this file to retrieve configuration values.
  2. Port Configuration:

    • The application runs on port 8000 by default. This is crucial for deployment as it dictates where the application listens for incoming requests.

Example Configuration File:

Here's an example of the YAML configuration file (config.yaml) used by the application:

SERVER_URL: https://jsonplaceholder.typicode.com/users

CUSTOM_CONFIG_VALUE: "initial config value"

Example Outputs:

1. Endpoint /config_values

This endpoint will be returning the configuration values from the YAML file.

Request
curl -X 'GET' 'http://127.0.0.1:8000/config_values' | jq .
Response
{
  "SERVER_URL": "https://jsonplaceholder.typicode.com/users",
  "CUSTOM_CONFIG_VALUE": "initial config value",
}

2. Endpoint /environment_variables 

This endpoint will be returning all environment variables available to the application.

Request
curl -X 'GET' 'http://127.0.0.1:8000/environment_variables' | jq .
Response
{
  "PATH": "/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
  "HOSTNAME": "ead8df2344e0",
  "CUSTOM_ENV_VARIABLE": "initial_env_value",
  "CONFIG_PATH": "config.yaml",
  "LANG": "C.UTF-8",
  "GPG_KEY": "E3FF2839C048B25C084DEBE9B26995E310250568",
  "PYTHON_VERSION": "3.9.19",
  "PYTHON_PIP_VERSION": "23.0.1",
  "PYTHON_SETUPTOOLS_VERSION": "58.1.0",
  "PYTHON_GET_PIP_URL": "https://github.com/pypa/get-pip/raw/66d8a0f637083e2c3ddffc0cb1e65ce126afb856/public/get-pip.py",
  "PYTHON_GET_PIP_SHA256": "6fb7b781206356f45ad79efbb19322caa6c2a5ad39092d0d44d0fec94117e118",
  "HOME": "/root"
}

Summary:

At this point, you should have a clear understanding of how the FastAPI application works, its key components, and how it can be configured.

Ensure that the necessary environment variables and configuration files are set up correctly to utilize the application's features effectively.

This application will be used in subsequent steps, so understanding its setup and functionality is crucial.