A RESTful API built with FastAPI for managing servers across multiple datacenters
- Create, read, update, and delete servers
- Manage server configurations as JSON
- Link servers to datacenters
- Comprehensive API documentation with Swagger UI
- Health check endpoint
- Python 3.8+
- PostgreSQL 12+
- pip (Python package manager)
git clone https://github.com/krasnoshchok/server-management-api.git
cd server-management-apipython -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activatepip install -r requirements.txtCreate a new database:
createdb server_managementRun the SQL schema file to create tables:
psql server_management < sql/schema.sqlThis will create the following tables:
datacenter- Stores datacenter informationswitch- Network switch informationserver- Server inventoryswitch_to_server- Many-to-many relationship between switches and servers
The schema file also includes sample data for testing.
Create a .env file in the project root:
# Database
DB_HOST=localhost
DB_NAME=server_management
DB_USER=postgres
DB_PASSWORD=your_password_here
DB_PORT=5432
# Logging
LOG_LEVEL=INFO
LOG_FILE=logs/app.logStart the development server:
uvicorn app.main:app --reloadThe API will be available at http://localhost:8000
Once the server is running, access the interactive API documentation:
- Swagger UI: http://localhost:8000/docs
- ReDoc: http://localhost:8000/redoc
- GET
/health- Verify the service is running
- GET
/servers/- Retrieve all servers - GET
/servers/{server_id}- Retrieve a specific server by ID - POST
/servers/- Create a new server - PUT
/servers/{server_id}- Update an existing server - DELETE
/servers/{server_id}- Delete a server
curl -X POST "http://localhost:8000/servers/" \
-H "Content-Type: application/json" \
-d '{
"hostname": "webserver.local.lan",
"configuration": {"cpu_cores": 8, "ram_gb": 32},
"datacenter_id": 1
}'Important
Resource Limits Enforced
The server configuration strictly enforces hardware limits. Invalid values will result in a 400 Bad Request error.
cpu_cores: Must be between 1 and 128ram_gb: Must be between 1 and 4096
Get first 100 servers (default):
curl -X GET "http://localhost:8000/servers/"Get first 10 servers:
curl -X GET "http://localhost:8000/servers/?limit=10"Get servers 11-20 (skip first 10, return next 10):
curl -X GET "http://localhost:8000/servers/?skip=10&limit=10"Get servers 101-200:
curl -X GET "http://localhost:8000/servers/?skip=100&limit=100"curl -X GET "http://localhost:8000/servers/1"curl -X PUT "http://localhost:8000/servers/1" \
-H "Content-Type: application/json" \
-d '{
"hostname": "updated-webserver.local.lan",
"configuration": {"cpu_cores": 16, "ram_gb": 64}
}'curl -X DELETE "http://localhost:8000/servers/1"server-management-api/
│
├── app/
│ ├── __init__.py
│ ├── main.py # FastAPI application entry point
│ ├── database.py # Database connection management
│ ├── models.py # Pydantic models for validation
│ ├── constants.py # Database table constants
│ ├── logging_config.py # Logging configuration
│ └── routers/
│ ├── __init__.py
│ └── servers.py # Server endpoint definitions
│
├── logs/
│ └── app.log # Application logs (gitignored)
│
├── sql/
│ └── schema.sql # Database schema and sample data
│
├── .env # Environment variables (gitignored)
├── .gitignore
├── requirements.txt # Python dependencies
└── README.md
- Used context managers (
@asynccontextmanager) for automatic connection cleanup RealDictCursorreturns query results as dictionaries for easier JSON serialization- Manual transaction management (commit/rollback) for better control
- Direct SQL queries using
asyncpgas per requirements - Parameterized queries to prevent SQL injection
- Dynamic query building for partial updates
- RESTful conventions (GET, POST, PUT, DELETE)
- Proper HTTP status codes (200, 201, 204, 400, 404)
- Comprehensive error handling with descriptive messages
- Request/response validation using Pydantic models
- Server
configurationfield stored as JSONB in PostgreSQL - Flexible schema allows different configurations per server
- Validated as dictionary type in Pydantic models
The API returns standard HTTP error codes:
200 OK- Successful GET request201 Created- Successful POST request204 No Content- Successful DELETE request400 Bad Request- Invalid input or missing required fields404 Not Found- Resource not found500 Internal Server Error- Server-side error
You can test the API using:
- Swagger UI at http://localhost:8000/docs (interactive testing)
- curl commands (see examples above)
- Postman or similar API clients
- Python requests library
The application includes comprehensive logging for monitoring and debugging.
Configure logging in your .env file:
# Logging (optional)
LOG_LEVEL=INFO # Options: DEBUG, INFO, WARNING, ERROR, CRITICAL
LOG_FILE=logs/app.log # Leave empty to disable file logging- DEBUG: Detailed information for diagnosing problems (shows all query details)
- INFO: General informational messages (default, recommended for production)
- WARNING: Warning messages for unexpected events
- ERROR: Error messages for serious problems
- CRITICAL: Critical errors that may cause the application to stop
Logs are written to two locations:
- Console/Terminal - All logs appear in the terminal where you run uvicorn
- Log File - Persistent logs saved to
logs/app.log(if configured)
View logs in real-time:
tail -f logs/app.log2024-05-28 15:30:52 - INFO - Fetching servers with skip=0, limit=100
2024-05-28 15:30:52 - INFO - Retrieved 3 servers
2024-05-28 15:31:10 - INFO - Creating server: hostname=newserver.local, datacenter_id=1
2024-05-28 15:31:10 - INFO - Created server with id=4, hostname=newserver.local
2024-05-28 15:31:45 - WARNING - Server with id=99 not found
The following files are ignored by git (see .gitignore):
.env- Contains sensitive database credentialslogs/- Log files can grow large and contain sensitive data__pycache__/and*.pyc- Python bytecode files
To run in development mode with auto-reload:
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000- The API follows PEP 8 style guidelines
- All endpoints include comprehensive docstrings
- Foreign key constraints are validated before operations
- Timestamps are automatically managed by PostgreSQL
- The
modified_atfield is updated on every server update