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
85 changes: 85 additions & 0 deletions app_python/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import os
import socket
import platform
import logging
from datetime import datetime, timezone
from flask import Flask, jsonify, request

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

app = Flask(__name__)

HOST = os.getenv('HOST', '0.0.0.0')
PORT = int(os.getenv('PORT', 5000))
START_TIME = datetime.now(timezone.utc)

def get_system_info():
return {
'hostname': socket.gethostname(),
'platform': platform.system(),
'platform_version': platform.release(),
'architecture': platform.machine(),
'cpu_count': os.cpu_count(),
'python_version': platform.python_version()
}

def get_uptime():
delta = datetime.now(timezone.utc) - START_TIME
seconds = int(delta.total_seconds())
hours, remainder = divmod(seconds, 3600)
minutes, _ = divmod(remainder, 60)
return {
'seconds': seconds,
'human': f"{hours} hour{'s' if hours != 1 else ''}, {minutes} minute{'s' if minutes != 1 else ''}"
}

@app.route('/', methods=['GET'])
def index():
logger.info(f"Request: {request.method} {request.path} from {request.remote_addr}")
uptime = get_uptime()
return jsonify({
"service": {
"name": "devops-info-service",
"version": "1.0.0",
"description": "DevOps course info service",
"framework": "Flask"
},
"system": get_system_info(),
"runtime": {
"uptime_seconds": uptime['seconds'],
"uptime_human": uptime['human'],
"current_time": datetime.now(timezone.utc).isoformat(),
"timezone": "UTC"
},
"request": {
"client_ip": request.remote_addr or 'unknown',
"user_agent": request.headers.get('User-Agent', 'unknown'),
"method": request.method,
"path": request.path
},
"endpoints": [
{"path": "/", "method": "GET", "description": "Service information"},
{"path": "/health", "method": "GET", "description": "Health check"}
]
})

@app.route('/health', methods=['GET'])
def health():
return jsonify({
'status': 'healthy',
'timestamp': datetime.now(timezone.utc).isoformat(),
'uptime_seconds': get_uptime()['seconds']
})

@app.errorhandler(404)
def not_found(error):
return jsonify({'error': 'Not Found', 'message': 'Endpoint does not exist'}), 404

@app.errorhandler(500)
def internal_error(error):
return jsonify({'error': 'Internal Server Error', 'message': 'An unexpected error occurred'}), 500

if __name__ == '__main__':
logger.info('Application starting...')
app.run(host=HOST, port=PORT, debug=False)
33 changes: 33 additions & 0 deletions app_python/docs/LAB01.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# LAB01 - DevOps Info Service

## Framework Selection
Flask 3.0.3 - lightweight framework suitable for simple APIs and microservices.

## Best Practices Applied
1. Structured logging with timestamps
2. Error handling for 404/500 responses
3. Environment variables for configuration
4. PEP8 compliant code organization

## API Documentation
GET / - Service and system information
GET /health - Health check endpoint

text

## Testing Evidence
![Main endpoint](screenshots/01-main-endpoint.png)
![Health check](screenshots/02-health-check.png)
![Terminal output](screenshots/03-formatted-output.png)

## GitHub Community Engagement
- Starred: inno-devops-labs/DevOps-Core-Course
- Starred: simple-container-com/api
- Following: Cre-eD, marat-biriushev, pierrepicaud
- Following 3 classmates

Stars increase project visibility. Following helps track best practices.

## Challenges & Solutions
- Windows venv activation via direct python.exe path
- Client IP shows 127.0.0.1 for localhost correctly
Binary file added app_python/docs/screenshots/01-main-endpoint.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/02-health-check.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions app_python/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Flask==3.0.3
Empty file added app_python/tests/__init__.py
Empty file.