Skip to content
Open

Lab01 #4544

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
40 changes: 40 additions & 0 deletions app_python/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# FastAPi web api

## Overview

This app have been build for the lab01 of the "Devops Core course". It give service and
system information and do health check for monitoring

## Prerequisites

```markdown
python 3.14.4
```

## 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=4999 HOST 127.0.0.1 python app.py
```

## API Endpoints

- GET / - Service and system information
- GET /health - Health check

## Configuration

|HOST|PORT|
|--------|----------|
|Host ip|tcp port number|

Binary file added app_python/__pycache__/app.cpython-314.pyc
Binary file not shown.
149 changes: 149 additions & 0 deletions app_python/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import os
import json
import logging
import socket



from datetime import datetime

import uvicorn
import platform
from fastapi import FastAPI, Request, HTTPException
from fastapi.responses import JSONResponse

#------------------Fonctions---------------------------------
start_time = datetime.now()


def getSystemInformation():
hostname = socket.gethostname()
plaform_version = platform.version()
platform_name = platform.system()
architecture = platform.machine()
python_version = platform.python_version()
cpu_count = os.cpu_count()

return {
"hostname": hostname,
"platform": platform_name,
"platform_version": plaform_version,
"architecture": architecture,
"cpu_count": cpu_count,
"python_version": python_version
}


def getService():
return {
"name": "devops-info-service",
"version": "1.0.0",
"description": "DevOps course info service",
"framework": "Flask"
}


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"
}


def getRuntime():
delta = datetime.now() - start_time
seconds = int(delta.total_seconds())
hours = seconds // 3600
minutes = (seconds % 3600) // 60

# la timezone
time_now = datetime.now()
local_now = time_now.astimezone()
local_tz = local_now.tzinfo
local_tzname = local_tz.tzname(local_now)

return {
"uptime_seconds": seconds,
"uptime_human": f"{hours} hours, {minutes} minutes",
"current_time": time_now,
"timezone": local_tzname
}


def getRequestInfo(request: Request):
return {
"client_ip": request.client.host,
"user_agent": request.headers.get('user-agent'),
"method": request.method,
"path": request.url.path
}


#--------------------logging----------------------------
def getLogging(request: Request):
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
filename="debug.log"
)
logger = logging.getLogger(__name__)

logger.info('Application starting...')
logger.info('Man-debugger')
logger.debug(f'Request: Ola{request.method} {request.url.path}')


#--------------------app----------------------------------------

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

@app.get("/")
def read_root(request:Request):
getLogging(request)
return {
"service": getService(),
"system": getSystemInformation(),
"runtime": getRuntime(),
"request": getRequestInfo(request),
"endpoints": [
{"path": "/", "method": "GET", "description": "Service information"},
{"path": "/health", "method": "GET", "description": "Health check"}
]
}

@app.get("/health")
def read_health(request: Request):
getLogging(request)
return {
'status': 'healthy',
'timestamp': datetime.now().isoformat(),
'uptime_seconds': get_uptime()['seconds']
}
#---------------------Error handlers----------------

@app.exception_handler(404)
def custom_404_handler(request: Request, __):
getLogging(request)
return JSONResponse({
"error": "404 not Found",
"message": "Endpoint does not exist"
})

@app.exception_handler(500)
def custom_500_handler(request: Request, __):
getLogging(request)
return JSONResponse({
"error": "505 internal Server Error",
"message": "An unexpected error occurred"
})


if __name__ == "__main__":
uvicorn.run(app, host=HOST, port=PORT)
136 changes: 136 additions & 0 deletions app_python/app.py~
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import os
import socket
from datetime import datetime

import uvicorn
import platform
from fastapi import FastAPI, Request, HTTPException
from fastapi.responses import HTMLResponse


#------------------constantes----------------------------
response_404 = """
<!DOCTYPE html>
<html lang="en">
<head>
<title>Not Found</title>
</head>
<body>
<p>The file you requested was not found.</p>
</body>
</html>
"""

#------------------Fonctions---------------------------------
start_time = datetime.now()


def getSystemInformation():
hostname = socket.gethostname()
plaform_version = platform.version()
platform_name = platform.system()
architecture = platform.machine()
python_version = platform.python_version()
cpu_count = os.cpu_count()

return {
"hostname": hostname,
"platform": platform_name,
"platform_version": plaform_version,
"architecture": architecture,
"cpu_count": cpu_count,
"python_version": python_version
}


def getService():
return {
"name": "devops-info-service",
"version": "1.0.0",
"description": "DevOps course info service",
"framework": "Flask"
}


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"
}


def getRuntime():
delta = datetime.now() - start_time
seconds = int(delta.total_seconds())
hours = seconds // 3600
minutes = (seconds % 3600) // 60

# la timezone
time_now = datetime.now()
local_now = time_now.astimezone()
local_tz = local_now.tzinfo
local_tzname = local_tz.tzname(local_now)

return {
"uptime_seconds": seconds,
"uptime_human": f"{hours} hours, {minutes} minutes",
"current_time": time_now,
"timezone": local_tzname
}


def getRequestInfo(request: Request):
return {
"client_ip": request.client.host,
"user_agent": request.headers.get('user-agent'),
"method": request.method,
"path": request.url.path
}



#--------------------app----------------------------------------

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

@app.get("/")
def read_root(request:Request):
return {
"service": getService(),
"system": getSystemInformation(),
"runtime": getRuntime(),
"request": getRequestInfo(request),
"endpoints": [
{"path": "/", "method": "GET", "description": "Service information"},
{"path": "/health", "method": "GET", "description": "Health check"}
]
}

@app.get("/health")
def read_health():
return {
'status': 'healthy',
'timestamp': datetime.now().isoformat(),
'uptime_seconds': get_uptime()['seconds']
}
#---------------------Error handlers----------------

@app.exception_handler(404)
def custom_404_handler(_, __):
return HTMLResponse(response_404)

@app.exception_handler(500)
def custom_500_handler(_, __):
return {
"error": "505 internal Server Error",
"message": ""
}
if __name__ == "__main__":
uvicorn.run(app, host=HOST, port=PORT)
44 changes: 44 additions & 0 deletions app_python/docs/LAB01.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# LAB01

## Framework Selection

I choose fastapi because I wanted to, plus I had already tried Flask some times ago.

## Best practices Applied

- Clear function names

![Image function](screenshots/cleanfunction)

- Proper import grouping

![Image proper import](screenshots/properImport)

- Follow PEP 8

![Image respect PEP 8](screenshots/pep8)

## API examples

- **/ route**

![Image respect PEP 8](screenshots/api_test_root)

- **/health route**

![Image respect PEP 8](screenshots/api_test_health)

## Testing Evidences

![Image respect PEP 8](screenshots/root_route)

![Image respect PEP 8](screenshots/health_route)

## Challenges and solutions

The main challenge was writing the documentation, I'm not really use to be detailed in my readmes. So the instructions in the lab helped a lot.

## Github Community

Starring repositories and following developers help in adding visibility to projects and help developers to get credit for their works.

Binary file added app_python/docs/screenshots/api_test_health
Binary file not shown.
Binary file added app_python/docs/screenshots/api_test_root
Binary file not shown.
Binary file added app_python/docs/screenshots/cleanfunction
Binary file not shown.
Binary file added app_python/docs/screenshots/health_route
Binary file not shown.
Binary file added app_python/docs/screenshots/pep8
Binary file not shown.
Binary file added app_python/docs/screenshots/properImport
Binary file not shown.
Binary file added app_python/docs/screenshots/root_route
Binary file not shown.
3 changes: 3 additions & 0 deletions app_python/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fastapi==0.115.0
uvicorn[standard]==0.32.0 # Includes performance extras