base-deployment-controller 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- base_deployment_controller-0.1.0/PKG-INFO +184 -0
- base_deployment_controller-0.1.0/README.md +163 -0
- base_deployment_controller-0.1.0/pyproject.toml +49 -0
- base_deployment_controller-0.1.0/setup.cfg +4 -0
- base_deployment_controller-0.1.0/src/base_deployment_controller/__init__.py +59 -0
- base_deployment_controller-0.1.0/src/base_deployment_controller/builder.py +90 -0
- base_deployment_controller-0.1.0/src/base_deployment_controller/models/__init__.py +33 -0
- base_deployment_controller-0.1.0/src/base_deployment_controller/models/compose.py +11 -0
- base_deployment_controller-0.1.0/src/base_deployment_controller/models/container.py +31 -0
- base_deployment_controller-0.1.0/src/base_deployment_controller/models/deployment.py +57 -0
- base_deployment_controller-0.1.0/src/base_deployment_controller/models/environment.py +42 -0
- base_deployment_controller-0.1.0/src/base_deployment_controller/routers/__init__.py +7 -0
- base_deployment_controller-0.1.0/src/base_deployment_controller/routers/container.py +398 -0
- base_deployment_controller-0.1.0/src/base_deployment_controller/routers/deployment.py +281 -0
- base_deployment_controller-0.1.0/src/base_deployment_controller/routers/environment.py +174 -0
- base_deployment_controller-0.1.0/src/base_deployment_controller/services/__init__.py +5 -0
- base_deployment_controller-0.1.0/src/base_deployment_controller/services/config.py +560 -0
- base_deployment_controller-0.1.0/src/base_deployment_controller.egg-info/PKG-INFO +184 -0
- base_deployment_controller-0.1.0/src/base_deployment_controller.egg-info/SOURCES.txt +21 -0
- base_deployment_controller-0.1.0/src/base_deployment_controller.egg-info/dependency_links.txt +1 -0
- base_deployment_controller-0.1.0/src/base_deployment_controller.egg-info/requires.txt +11 -0
- base_deployment_controller-0.1.0/src/base_deployment_controller.egg-info/top_level.txt +1 -0
- base_deployment_controller-0.1.0/tests/test_api_integration.py +191 -0
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: base-deployment-controller
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: REST API to control the basic operations of a deployment
|
|
5
|
+
Author: Tknika
|
|
6
|
+
License: Creative Commons Atribución-NoComercial (CC BY-NC)
|
|
7
|
+
Classifier: Development Status :: 3 - Alpha
|
|
8
|
+
Classifier: Intended Audience :: Developers
|
|
9
|
+
Requires-Python: >=3.8
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
Requires-Dist: fastapi>=0.128.0
|
|
12
|
+
Requires-Dist: uvicorn[standard]>=0.40.0
|
|
13
|
+
Requires-Dist: python-dotenv>=1.2.1
|
|
14
|
+
Requires-Dist: pyyaml>=6.0.3
|
|
15
|
+
Requires-Dist: websockets>=16.0
|
|
16
|
+
Requires-Dist: python-on-whales>=0.80.0
|
|
17
|
+
Provides-Extra: dev
|
|
18
|
+
Requires-Dist: pytest>=7.4.0; extra == "dev"
|
|
19
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
20
|
+
Requires-Dist: requests>=2.31.0; extra == "dev"
|
|
21
|
+
|
|
22
|
+
# Base Deployment Controller
|
|
23
|
+
|
|
24
|
+
REST API para la gestión básica de un deployment.
|
|
25
|
+
|
|
26
|
+
## Características
|
|
27
|
+
|
|
28
|
+
- **Gestión del deployment**: Inicia, detiene y borrar el deploy (`compose.yaml`)
|
|
29
|
+
- **Gestión de variables de entorno**: Lee configuración de `x-env-vars` en `compose.yaml` y permite actualizar valores en `.env`
|
|
30
|
+
- **Control de contenedores**: Inicia, detiene y reinicia contenedores del deploy
|
|
31
|
+
- **Logs en tiempo real**: WebSocket para streaming de logs de contenedores
|
|
32
|
+
- **Validación de tipos**: Valida automáticamente valores según schemas (regex, rangos, enums)
|
|
33
|
+
|
|
34
|
+
## Requisitos
|
|
35
|
+
|
|
36
|
+
- Python 3.8+
|
|
37
|
+
- Docker y Docker Compose
|
|
38
|
+
|
|
39
|
+
## Instalación
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
# Crear entorno virtual
|
|
43
|
+
python3 -m venv .venv
|
|
44
|
+
source .venv/bin/activate
|
|
45
|
+
|
|
46
|
+
# Instalar como librería
|
|
47
|
+
pip install base-deployment-controller
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Uso
|
|
51
|
+
|
|
52
|
+
### Iniciar el servidor (demo)
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# Ejecutar la app demo desde la raíz del repo
|
|
56
|
+
python3 main.py
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
El servidor estará disponible en `http://localhost:8000`
|
|
60
|
+
|
|
61
|
+
### Uso como librería
|
|
62
|
+
|
|
63
|
+
#### Uso básico (factory)
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
from base_deployment_controller import create_app
|
|
67
|
+
|
|
68
|
+
app = create_app(
|
|
69
|
+
compose_file="compose.yaml",
|
|
70
|
+
env_file=".env",
|
|
71
|
+
)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
#### Uso avanzado (builder + routers personalizados)
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
from fastapi import APIRouter
|
|
78
|
+
from base_deployment_controller import AppBuilder
|
|
79
|
+
|
|
80
|
+
custom_router = APIRouter(prefix="/custom")
|
|
81
|
+
|
|
82
|
+
builder = AppBuilder("compose.yaml", ".env")
|
|
83
|
+
app = builder.register_router(custom_router).build()
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### API Endpoints
|
|
87
|
+
|
|
88
|
+
#### GET /
|
|
89
|
+
Obtiene información sobre el deploy:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
curl http://localhost:8000/
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
#### POST /up|down|stop
|
|
96
|
+
Controla el deploy:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
# Levanta todos los servicio del deploy
|
|
100
|
+
curl -X POST http://localhost:8000/up
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
#### GET /envs
|
|
104
|
+
Obtiene todas las variables de entorno con sus valores actuales:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
curl http://localhost:8000/envs
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
#### PUT /envs
|
|
111
|
+
Actualiza variables de entorno. Usa `restart_services` (por defecto `true`) para controlar si se reinician los servicios afectados.
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
# Actualización múltiple
|
|
115
|
+
curl -X PUT http://localhost:8000/envs \
|
|
116
|
+
-H "Content-Type: application/json" \
|
|
117
|
+
-d '{"variables": {"MCC": "214", "MNC": "07"}, "restart_services": false}'
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
#### GET /containers
|
|
121
|
+
Lista el estado de todos los contenedores:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
curl http://localhost:8000/containers
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
#### POST /containers/{name}/start|stop|restart
|
|
128
|
+
Controla un contenedor específico:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
# Reiniciar el MME
|
|
132
|
+
curl -X POST http://localhost:8000/containers/mme/restart
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
#### WebSocket /containers/{container_name}/logs
|
|
136
|
+
Logs en tiempo real via WebSocket:
|
|
137
|
+
|
|
138
|
+
```javascript
|
|
139
|
+
const ws = new WebSocket('ws://localhost:8000/containers/mme/logs');
|
|
140
|
+
ws.onmessage = (event) => {
|
|
141
|
+
console.log(event.data);
|
|
142
|
+
};
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
#### GET /ping
|
|
146
|
+
Health check del servicio:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
curl http://localhost:8000/ping
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Documentación Interactiva
|
|
153
|
+
|
|
154
|
+
FastAPI genera automáticamente documentación interactiva:
|
|
155
|
+
|
|
156
|
+
- **Swagger UI**: http://localhost:8000/docs
|
|
157
|
+
- **ReDoc**: http://localhost:8000/redoc
|
|
158
|
+
|
|
159
|
+
## Arquitectura
|
|
160
|
+
|
|
161
|
+
### Configuración de Tres Niveles
|
|
162
|
+
|
|
163
|
+
1. **compose.yaml**: Define servicios y dependencias
|
|
164
|
+
2. **x-env-vars**: Schema maestro con validaciones
|
|
165
|
+
3. **.env**: Valores en tiempo de ejecución
|
|
166
|
+
|
|
167
|
+
## Validación de Tipos
|
|
168
|
+
|
|
169
|
+
Las variables se validan según el schema de `x-env-vars`:
|
|
170
|
+
|
|
171
|
+
- **String con regex**: `"string:0;^\d{3}$"` - MCC debe ser 3 dígitos
|
|
172
|
+
- **Integer con rango**: `"integer:0;2048"` - MAX_NUM_UE entre 0-2048
|
|
173
|
+
- **Enum**: `"enum:tun,tap"` - UPF_TUNTAP_MODE solo acepta tun o tap
|
|
174
|
+
|
|
175
|
+
## Seguridad
|
|
176
|
+
|
|
177
|
+
- Solo permite actualizar variables existentes en el schema
|
|
178
|
+
- No permite agregar nuevas variables
|
|
179
|
+
- No permite eliminar variables
|
|
180
|
+
- Valida todos los valores antes de escribir en `.env`
|
|
181
|
+
|
|
182
|
+
## Licencia
|
|
183
|
+
|
|
184
|
+
Este proyecto es parte del controlador de despliegue 5G de Tknika.
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# Base Deployment Controller
|
|
2
|
+
|
|
3
|
+
REST API para la gestión básica de un deployment.
|
|
4
|
+
|
|
5
|
+
## Características
|
|
6
|
+
|
|
7
|
+
- **Gestión del deployment**: Inicia, detiene y borrar el deploy (`compose.yaml`)
|
|
8
|
+
- **Gestión de variables de entorno**: Lee configuración de `x-env-vars` en `compose.yaml` y permite actualizar valores en `.env`
|
|
9
|
+
- **Control de contenedores**: Inicia, detiene y reinicia contenedores del deploy
|
|
10
|
+
- **Logs en tiempo real**: WebSocket para streaming de logs de contenedores
|
|
11
|
+
- **Validación de tipos**: Valida automáticamente valores según schemas (regex, rangos, enums)
|
|
12
|
+
|
|
13
|
+
## Requisitos
|
|
14
|
+
|
|
15
|
+
- Python 3.8+
|
|
16
|
+
- Docker y Docker Compose
|
|
17
|
+
|
|
18
|
+
## Instalación
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# Crear entorno virtual
|
|
22
|
+
python3 -m venv .venv
|
|
23
|
+
source .venv/bin/activate
|
|
24
|
+
|
|
25
|
+
# Instalar como librería
|
|
26
|
+
pip install base-deployment-controller
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Uso
|
|
30
|
+
|
|
31
|
+
### Iniciar el servidor (demo)
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
# Ejecutar la app demo desde la raíz del repo
|
|
35
|
+
python3 main.py
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
El servidor estará disponible en `http://localhost:8000`
|
|
39
|
+
|
|
40
|
+
### Uso como librería
|
|
41
|
+
|
|
42
|
+
#### Uso básico (factory)
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
from base_deployment_controller import create_app
|
|
46
|
+
|
|
47
|
+
app = create_app(
|
|
48
|
+
compose_file="compose.yaml",
|
|
49
|
+
env_file=".env",
|
|
50
|
+
)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
#### Uso avanzado (builder + routers personalizados)
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
from fastapi import APIRouter
|
|
57
|
+
from base_deployment_controller import AppBuilder
|
|
58
|
+
|
|
59
|
+
custom_router = APIRouter(prefix="/custom")
|
|
60
|
+
|
|
61
|
+
builder = AppBuilder("compose.yaml", ".env")
|
|
62
|
+
app = builder.register_router(custom_router).build()
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### API Endpoints
|
|
66
|
+
|
|
67
|
+
#### GET /
|
|
68
|
+
Obtiene información sobre el deploy:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
curl http://localhost:8000/
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
#### POST /up|down|stop
|
|
75
|
+
Controla el deploy:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# Levanta todos los servicio del deploy
|
|
79
|
+
curl -X POST http://localhost:8000/up
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
#### GET /envs
|
|
83
|
+
Obtiene todas las variables de entorno con sus valores actuales:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
curl http://localhost:8000/envs
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
#### PUT /envs
|
|
90
|
+
Actualiza variables de entorno. Usa `restart_services` (por defecto `true`) para controlar si se reinician los servicios afectados.
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
# Actualización múltiple
|
|
94
|
+
curl -X PUT http://localhost:8000/envs \
|
|
95
|
+
-H "Content-Type: application/json" \
|
|
96
|
+
-d '{"variables": {"MCC": "214", "MNC": "07"}, "restart_services": false}'
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
#### GET /containers
|
|
100
|
+
Lista el estado de todos los contenedores:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
curl http://localhost:8000/containers
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
#### POST /containers/{name}/start|stop|restart
|
|
107
|
+
Controla un contenedor específico:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
# Reiniciar el MME
|
|
111
|
+
curl -X POST http://localhost:8000/containers/mme/restart
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
#### WebSocket /containers/{container_name}/logs
|
|
115
|
+
Logs en tiempo real via WebSocket:
|
|
116
|
+
|
|
117
|
+
```javascript
|
|
118
|
+
const ws = new WebSocket('ws://localhost:8000/containers/mme/logs');
|
|
119
|
+
ws.onmessage = (event) => {
|
|
120
|
+
console.log(event.data);
|
|
121
|
+
};
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
#### GET /ping
|
|
125
|
+
Health check del servicio:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
curl http://localhost:8000/ping
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Documentación Interactiva
|
|
132
|
+
|
|
133
|
+
FastAPI genera automáticamente documentación interactiva:
|
|
134
|
+
|
|
135
|
+
- **Swagger UI**: http://localhost:8000/docs
|
|
136
|
+
- **ReDoc**: http://localhost:8000/redoc
|
|
137
|
+
|
|
138
|
+
## Arquitectura
|
|
139
|
+
|
|
140
|
+
### Configuración de Tres Niveles
|
|
141
|
+
|
|
142
|
+
1. **compose.yaml**: Define servicios y dependencias
|
|
143
|
+
2. **x-env-vars**: Schema maestro con validaciones
|
|
144
|
+
3. **.env**: Valores en tiempo de ejecución
|
|
145
|
+
|
|
146
|
+
## Validación de Tipos
|
|
147
|
+
|
|
148
|
+
Las variables se validan según el schema de `x-env-vars`:
|
|
149
|
+
|
|
150
|
+
- **String con regex**: `"string:0;^\d{3}$"` - MCC debe ser 3 dígitos
|
|
151
|
+
- **Integer con rango**: `"integer:0;2048"` - MAX_NUM_UE entre 0-2048
|
|
152
|
+
- **Enum**: `"enum:tun,tap"` - UPF_TUNTAP_MODE solo acepta tun o tap
|
|
153
|
+
|
|
154
|
+
## Seguridad
|
|
155
|
+
|
|
156
|
+
- Solo permite actualizar variables existentes en el schema
|
|
157
|
+
- No permite agregar nuevas variables
|
|
158
|
+
- No permite eliminar variables
|
|
159
|
+
- Valida todos los valores antes de escribir en `.env`
|
|
160
|
+
|
|
161
|
+
## Licencia
|
|
162
|
+
|
|
163
|
+
Este proyecto es parte del controlador de despliegue 5G de Tknika.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "base-deployment-controller"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "REST API to control the basic operations of a deployment"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.8"
|
|
11
|
+
authors = [
|
|
12
|
+
{ name = "Tknika" }
|
|
13
|
+
]
|
|
14
|
+
license = { text = "Creative Commons Atribución-NoComercial (CC BY-NC)" }
|
|
15
|
+
dependencies = [
|
|
16
|
+
"fastapi>=0.128.0",
|
|
17
|
+
"uvicorn[standard]>=0.40.0",
|
|
18
|
+
"python-dotenv>=1.2.1",
|
|
19
|
+
"pyyaml>=6.0.3",
|
|
20
|
+
"websockets>=16.0",
|
|
21
|
+
"python-on-whales>=0.80.0",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
classifiers = [
|
|
25
|
+
"Development Status :: 3 - Alpha",
|
|
26
|
+
"Intended Audience :: Developers",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
[project.optional-dependencies]
|
|
30
|
+
dev = [
|
|
31
|
+
"pytest>=7.4.0",
|
|
32
|
+
"pytest-asyncio>=0.21.0",
|
|
33
|
+
"requests>=2.31.0",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
[tool.setuptools]
|
|
37
|
+
packages = { find = { where = ["src"] } }
|
|
38
|
+
include-package-data = false
|
|
39
|
+
|
|
40
|
+
[tool.setuptools.exclude-package-data]
|
|
41
|
+
"*" = ["data/*", "data/**", "tests/*", "tests/**", "test_*", "*.md"]
|
|
42
|
+
|
|
43
|
+
[tool.pytest.ini_options]
|
|
44
|
+
testpaths = ["tests"]
|
|
45
|
+
python_files = ["test_*.py"]
|
|
46
|
+
python_classes = ["Test*"]
|
|
47
|
+
python_functions = ["test_*"]
|
|
48
|
+
addopts = "-v --tb=short"
|
|
49
|
+
asyncio_mode = "auto"
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"""Base Deployment Controller package entry point."""
|
|
2
|
+
from fastapi import FastAPI
|
|
3
|
+
|
|
4
|
+
from .services.config import ConfigService
|
|
5
|
+
from .routers.environment import EnvRoutes
|
|
6
|
+
from .routers.container import ContainerRoutes
|
|
7
|
+
from .routers.deployment import DeploymentRoutes
|
|
8
|
+
from .builder import AppBuilder
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def create_app(
|
|
12
|
+
compose_file: str = "compose.yaml",
|
|
13
|
+
env_file: str = ".env",
|
|
14
|
+
include_routers: bool = True,
|
|
15
|
+
title: str = "Base Deployment Controller",
|
|
16
|
+
description: str = "REST API to control the basic operations of a deployment",
|
|
17
|
+
version: str = "1.0.0",
|
|
18
|
+
) -> FastAPI:
|
|
19
|
+
"""
|
|
20
|
+
Factory function to create a preconfigured FastAPI application.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
compose_file: Path to compose.yaml file.
|
|
24
|
+
env_file: Path to .env file.
|
|
25
|
+
include_routers: If True, registers base routers (envs, containers, deployment).
|
|
26
|
+
title: FastAPI application title.
|
|
27
|
+
description: FastAPI application description.
|
|
28
|
+
version: Application version string.
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
FastAPI app ready to use or extend.
|
|
32
|
+
"""
|
|
33
|
+
app = FastAPI(
|
|
34
|
+
title=title,
|
|
35
|
+
description=description,
|
|
36
|
+
version=version,
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
if include_routers:
|
|
40
|
+
config_service = ConfigService(compose_file, env_file)
|
|
41
|
+
env_routes = EnvRoutes(config_service)
|
|
42
|
+
container_routes = ContainerRoutes(config_service)
|
|
43
|
+
deployment_routes = DeploymentRoutes(config_service)
|
|
44
|
+
|
|
45
|
+
app.include_router(env_routes.router)
|
|
46
|
+
app.include_router(container_routes.router)
|
|
47
|
+
app.include_router(deployment_routes.router)
|
|
48
|
+
|
|
49
|
+
return app
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
__all__ = [
|
|
53
|
+
"ConfigService",
|
|
54
|
+
"EnvRoutes",
|
|
55
|
+
"ContainerRoutes",
|
|
56
|
+
"DeploymentRoutes",
|
|
57
|
+
"AppBuilder",
|
|
58
|
+
"create_app",
|
|
59
|
+
]
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"""Application builder for composing the FastAPI app and custom routers."""
|
|
2
|
+
from typing import List, Tuple
|
|
3
|
+
|
|
4
|
+
from fastapi import APIRouter, FastAPI
|
|
5
|
+
|
|
6
|
+
from .services.config import ConfigService
|
|
7
|
+
from .routers.environment import EnvRoutes
|
|
8
|
+
from .routers.container import ContainerRoutes
|
|
9
|
+
from .routers.deployment import DeploymentRoutes
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class AppBuilder:
|
|
13
|
+
"""
|
|
14
|
+
Builder for constructing a Base Deployment Controller FastAPI application.
|
|
15
|
+
|
|
16
|
+
Allows registration of custom routers before building the final app.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
compose_file: Path to Docker Compose file.
|
|
20
|
+
env_file: Path to environment variables file.
|
|
21
|
+
title: FastAPI application title.
|
|
22
|
+
description: FastAPI application description.
|
|
23
|
+
version: Application version string.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
def __init__(
|
|
27
|
+
self,
|
|
28
|
+
compose_file: str = "compose.yaml",
|
|
29
|
+
env_file: str = ".env",
|
|
30
|
+
title: str = "Base Deployment Controller",
|
|
31
|
+
description: str = "REST API for managing base deployment",
|
|
32
|
+
version: str = "1.0.0",
|
|
33
|
+
) -> None:
|
|
34
|
+
"""
|
|
35
|
+
Initialize the builder and register default routers.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
compose_file: Path to Docker Compose file.
|
|
39
|
+
env_file: Path to environment variables file.
|
|
40
|
+
title: FastAPI application title.
|
|
41
|
+
description: FastAPI application description.
|
|
42
|
+
version: Application version string.
|
|
43
|
+
"""
|
|
44
|
+
self.compose_file = compose_file
|
|
45
|
+
self.env_file = env_file
|
|
46
|
+
self.title = title
|
|
47
|
+
self.description = description
|
|
48
|
+
self.version = version
|
|
49
|
+
self._custom_routers: List[Tuple[APIRouter, str]] = []
|
|
50
|
+
|
|
51
|
+
def register_router(self, router: APIRouter, prefix: str = "") -> "AppBuilder":
|
|
52
|
+
"""
|
|
53
|
+
Register a custom router to include when building the app.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
router: Router instance to register.
|
|
57
|
+
prefix: Optional path prefix for the router.
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
AppBuilder instance for fluent chaining.
|
|
61
|
+
"""
|
|
62
|
+
self._custom_routers.append((router, prefix))
|
|
63
|
+
return self
|
|
64
|
+
|
|
65
|
+
def build(self) -> FastAPI:
|
|
66
|
+
"""
|
|
67
|
+
Build and return a FastAPI app with base and custom routers.
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
FastAPI application instance.
|
|
71
|
+
"""
|
|
72
|
+
app = FastAPI(
|
|
73
|
+
title=self.title,
|
|
74
|
+
description=self.description,
|
|
75
|
+
version=self.version,
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
config_service = ConfigService(self.compose_file, self.env_file)
|
|
79
|
+
env_routes = EnvRoutes(config_service)
|
|
80
|
+
container_routes = ContainerRoutes(config_service)
|
|
81
|
+
deployment_routes = DeploymentRoutes(config_service)
|
|
82
|
+
|
|
83
|
+
app.include_router(env_routes.router)
|
|
84
|
+
app.include_router(container_routes.router)
|
|
85
|
+
app.include_router(deployment_routes.router)
|
|
86
|
+
|
|
87
|
+
for router, prefix in self._custom_routers:
|
|
88
|
+
app.include_router(router, prefix=prefix)
|
|
89
|
+
|
|
90
|
+
return app
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""Pydantic models for the Base Deployment Controller."""
|
|
2
|
+
|
|
3
|
+
from .environment import (
|
|
4
|
+
EnvVariable,
|
|
5
|
+
EnvVariablesResponse,
|
|
6
|
+
BulkEnvUpdateRequest,
|
|
7
|
+
EnvUpdateResponse,
|
|
8
|
+
)
|
|
9
|
+
from .container import ContainerInfo, ContainersInfoResponse, ContainerControlResponse
|
|
10
|
+
from .deployment import (
|
|
11
|
+
DeploymentStatus,
|
|
12
|
+
DeploymentMetadata,
|
|
13
|
+
DeploymentInfoResponse,
|
|
14
|
+
DeploymentPingResponse,
|
|
15
|
+
DeploymentActionResponse,
|
|
16
|
+
)
|
|
17
|
+
from .compose import ComposeActionResponse
|
|
18
|
+
|
|
19
|
+
__all__ = [
|
|
20
|
+
"EnvVariable",
|
|
21
|
+
"EnvVariablesResponse",
|
|
22
|
+
"BulkEnvUpdateRequest",
|
|
23
|
+
"EnvUpdateResponse",
|
|
24
|
+
"ContainerInfo",
|
|
25
|
+
"ContainersInfoResponse",
|
|
26
|
+
"ContainerControlResponse",
|
|
27
|
+
"DeploymentStatus",
|
|
28
|
+
"DeploymentMetadata",
|
|
29
|
+
"DeploymentInfoResponse",
|
|
30
|
+
"DeploymentPingResponse",
|
|
31
|
+
"DeploymentActionResponse",
|
|
32
|
+
"ComposeActionResponse",
|
|
33
|
+
]
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"""Docker Compose operation models."""
|
|
2
|
+
from typing import List
|
|
3
|
+
|
|
4
|
+
from pydantic import BaseModel, Field
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class ComposeActionResponse(BaseModel):
|
|
8
|
+
"""Response after executing a docker-compose action (up/stop/restart)."""
|
|
9
|
+
|
|
10
|
+
success: bool = Field(..., description="Operation success status")
|
|
11
|
+
message: str = Field(..., description="Operation result message")
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Container models."""
|
|
2
|
+
from datetime import datetime
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel, Field, field_validator
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ContainerInfo(BaseModel):
|
|
9
|
+
"""Docker container information and service metadata."""
|
|
10
|
+
|
|
11
|
+
name: str = Field(..., description="Container name")
|
|
12
|
+
image: str = Field(..., description="Container image")
|
|
13
|
+
status: str = Field(..., description="Container status")
|
|
14
|
+
started_at: Optional[datetime] = Field(None, description="Container start time")
|
|
15
|
+
ports: list[str] = Field(..., description="Exposed ports")
|
|
16
|
+
depends_on: list[str] = Field(..., description="Service dependencies")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class ContainersInfoResponse(BaseModel):
|
|
20
|
+
"""Response with list of containers and their current status."""
|
|
21
|
+
|
|
22
|
+
containers: list[ContainerInfo] = Field(..., description="List of containers")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class ContainerControlResponse(BaseModel):
|
|
26
|
+
"""Response after executing a control action on a container."""
|
|
27
|
+
|
|
28
|
+
success: bool = Field(..., description="Action success status")
|
|
29
|
+
container: str = Field(..., description="Container name")
|
|
30
|
+
action: str = Field(..., description="Action performed")
|
|
31
|
+
message: str = Field(..., description="Status message")
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"""Deployment models."""
|
|
2
|
+
from enum import Enum
|
|
3
|
+
|
|
4
|
+
from .environment import EnvVariable
|
|
5
|
+
from pydantic import BaseModel, Field
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class DeploymentStatus(str, Enum):
|
|
9
|
+
"""
|
|
10
|
+
Deployment status enumeration.
|
|
11
|
+
|
|
12
|
+
Values:
|
|
13
|
+
running: All services running.
|
|
14
|
+
partially_running: Some services running.
|
|
15
|
+
stopped: No services running.
|
|
16
|
+
unknown: Status cannot be determined.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
RUNNING = "running"
|
|
20
|
+
PARTIALLY_RUNNING = "partially_running"
|
|
21
|
+
STOPPED = "stopped"
|
|
22
|
+
UNKNOWN = "unknown"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class DeploymentMetadata(BaseModel):
|
|
26
|
+
"""Deployment metadata from x-metadata section in compose.yaml."""
|
|
27
|
+
|
|
28
|
+
id: str = Field(..., description="Deployment unique identifier")
|
|
29
|
+
name: str = Field(..., description="Deployment name")
|
|
30
|
+
description: str = Field(..., description="Deployment description")
|
|
31
|
+
version: str = Field(..., description="Deployment version")
|
|
32
|
+
author: str = Field(..., description="Deployment author")
|
|
33
|
+
changelog: str = Field(..., description="Deployment changelog")
|
|
34
|
+
documentation_url: str = Field(..., description="Documentation URL")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class DeploymentInfoResponse(BaseModel):
|
|
38
|
+
"""Response with basic deployment information."""
|
|
39
|
+
|
|
40
|
+
metadata: DeploymentMetadata = Field(..., description="Deployment metadata")
|
|
41
|
+
status: DeploymentStatus
|
|
42
|
+
env_vars: dict[str, EnvVariable] = Field(..., description="List of environment variables")
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class DeploymentPingResponse(BaseModel):
|
|
46
|
+
"""Response for deployment ping endpoint."""
|
|
47
|
+
|
|
48
|
+
success: bool = Field(..., description="Ping success status")
|
|
49
|
+
message: str = Field(..., description="Ping message")
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class DeploymentActionResponse(BaseModel):
|
|
53
|
+
"""Response after performing a deployment action."""
|
|
54
|
+
|
|
55
|
+
success: bool = Field(..., description="Action success status")
|
|
56
|
+
action: str = Field(..., description="Action performed")
|
|
57
|
+
message: str = Field(..., description="Status message")
|