Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions app_python/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Python
__pycache__/
*.py[cod]
.venv/
*.log

# IDE
.vscode/
.idea/

# OS
.DS_Store
48 changes: 48 additions & 0 deletions app_python/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Overview

Lightweight web application built using __FastAPI__. It provides essential service and system information, along with a health check endpoint to monitor application status. The application shares various details about the server environment, including runtime status and configuration.

## Prerequisites

Before you begin, ensure you have the following prerequisites:

Python Version: Python 3.11 or higher
Dependencies: The application depends on the FastAPI framework and other packages specified in the requirements.txt file.

## Installation

```bash
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
```

## Running the Application

```bash python app.py
# Or with custom config
PORT=8080 python app.py
```

## API Endpoints

| Method | Endpoint | Description |
|--------|------------|-----------------------------------------|
| GET | / | Service and system information. |
| GET | /health | Health check for the application. |

### `/` - Service and System Information

This endpoint returns information about the service, system details, and configuration.

### `/health` - Health Check

This endpoint returns the health status of the application along with the current timestamp.

## Configuration

| Environment Variable | Description | Default Value |
|----------------------|-----------------------------------------|---------------|
| `HOST` | The host address for the application. | `0.0.0.0` |
| `PORT` | The port the application listens on. | `5000` |
| `DEBUG` | Enables debug mode if set to `true`. | `false` |
116 changes: 116 additions & 0 deletions app_python/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
from typing import Union

from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
import os
import platform
import socket
from datetime import datetime, timezone
import logging

HOST = os.getenv('HOST', '0.0.0.0')
PORT = int(os.getenv('PORT', 5000))
DEBUG = os.getenv('DEBUG', 'False').lower() == 'true'

logging.basicConfig(
level=logging.INFO if not DEBUG else logging.DEBUG,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)


app = FastAPI()
start_time = datetime.now()


@app.get("/")
def read_root(request: Request):
logger.debug(f'Request: {request.method} {request.url}')
hostname = socket.gethostname()
platform_name = platform.system()
platform_ver = platform.release()
architecture = platform.machine()
cpu_cores = os.cpu_count()
python_version = platform.python_version()
url_list = [{"path": route.path, "description": route.name,
"methods": route.methods} for route in app.routes]
return {
"service": {
"name": "devops-info-service",
"version": "1.0.0",
"description": "DevOps course info service",
"framework": "FastAPI"
},
"system": {
"hostname": hostname,
"platform": platform_name,
"platform_version": platform_ver,
"architecture": architecture,
"cpu_count": cpu_cores,
"python_version": python_version
},
"runtime": {
"uptime_seconds": get_uptime()['seconds'],
"uptime_human": get_uptime()['human'],
"current_time": datetime.now(timezone.utc).isoformat(),
"timezone": "UTC"
},
"request": {
"client_ip": request.client.host,
"user_agent": request.headers.get('user-agent'),
"method": request.method,
"path": request.url.path
},
"endpoints": url_list
}


@app.get("/health")
def health(request: Request):
logger.debug(f'Request: {request.method} {request.url}')
return {
'status': 'healthy',
'timestamp': datetime.now(timezone.utc).isoformat(),
'uptime_seconds': get_uptime()['seconds']
}


def get_uptime():
delta = datetime.now() - start_time
seconds = int(delta.total_seconds())
hours = seconds // 3600
minutes = (seconds % 3600) // 60
return {
'seconds': seconds,
'human': f"{hours} hours, {minutes} minutes"
}


@app.exception_handler(404)
async def not_found(request, exc):
return JSONResponse(
status_code=404,
content={
'error': 'Not Found',
'message': 'Endpoint does not exist'
}
)

# Custom error handler for 500 Internal Server Error


@app.exception_handler(500)
async def internal_error(request, exc):
return JSONResponse(
status_code=500,
content={
'error': 'Internal Server Error',
'message': 'An unexpected error occurred'
}
)

if __name__ == "__main__":
import uvicorn
logger.info('Application starting...')
uvicorn.run(app, host=HOST, port=PORT,
log_level='debug' if DEBUG else 'info')
97 changes: 97 additions & 0 deletions app_python/docs/LAB01.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Lab 01

## Framework Selection

Choice: FastAPI

Why? FastAPI is designed specifically for building high-performance APIs with Python. It provides automatic data validation and generates interactive documentation (Swagger UI) out of the box.

## Best Practices Applied

### Environment configation

The application avoids hardcoding sensitive or environment-specific values. It uses os.getenv to allow configuration via container environments or .env files.

```python
HOST = os.getenv('HOST', '0.0.0.0')
PORT = int(os.getenv('PORT', 5000))
DEBUG = os.getenv('DEBUG', 'False').lower() == 'true'
```

### Logging

Instead of using print() statements, the service implements the standard logging library with configurable levels.

```python
logging.basicConfig(
level=logging.INFO if not DEBUG else logging.DEBUG,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
```

## API Documentation

### Endpoint: Root Info

Path: /

Method: GET

Response Example:

```json
{
"service": { "name": "devops-info-service", "version": "1.0.0" },
"system": { "hostname": "local-machine", "platform": "Linux" },
"runtime": { "uptime_seconds": 120 }
}
```

### Endpoint: Health Check

Path: /health

Method: GET

Response Example:

```json
{
"status": "healthy",
"timestamp": "2026-01-27T18:30:00Z",
"uptime_seconds": 120
}
```

### Testing Commands

To test the service via CLI, use curl:

```bash
# Test Root Info
curl http://localhost:5000/

# Test Health Check
curl http://localhost:5000/health
```

### Testing Evidence

![application](screenshots/startup.png?raw=true "Running application")

![health endpoint](screenshots/health.png?raw=true "Health endpoint")

![root endpoint](screenshots/root.png?raw=true "Root info")

### Challenges & Solutions

I forgot how to launch a fastapi application via uicorn without a direct command in the terminal.

Solution:

```python
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host=HOST, port=PORT,
log_level='debug' if DEBUG else 'info')
```
Binary file added app_python/docs/screenshots/health.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app_python/docs/screenshots/root.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app_python/docs/screenshots/startup.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
42 changes: 42 additions & 0 deletions app_python/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
annotated-doc==0.0.4
annotated-types==0.7.0
anyio==4.12.1
certifi==2026.1.4
click==8.3.1
dnspython==2.8.0
email-validator==2.3.0
fastapi==0.128.0
fastapi-cli==0.0.20
fastapi-cloud-cli==0.11.0
fastar==0.8.0
h11==0.16.0
httpcore==1.0.9
httptools==0.7.1
httpx==0.28.1
idna==3.11
Jinja2==3.1.6
markdown-it-py==4.0.0
MarkupSafe==3.0.3
mdurl==0.1.2
pydantic==2.12.5
pydantic-extra-types==2.11.0
pydantic-settings==2.12.0
pydantic_core==2.41.5
Pygments==2.19.2
python-dotenv==1.2.1
python-multipart==0.0.22
PyYAML==6.0.3
rich==14.3.1
rich-toolkit==0.17.1
rignore==0.7.6
sentry-sdk==2.50.0
shellingham==1.5.4
starlette==0.50.0
typer==0.21.1
typing-inspection==0.4.2
typing_extensions==4.15.0
urllib3==2.6.3
uvicorn==0.40.0
uvloop==0.22.1
watchfiles==1.1.1
websockets==16.0
Empty file added app_python/tests/__init__.py
Empty file.