Merge _configs/ into config/ for single configuration directory. Update all path references. Changes: - Move _configs/* to config/ - Update .gitignore for new patterns - No code references to _configs/ found Impact: -1 root directory (layout_conventions.md compliance)
940 lines
25 KiB
Markdown
940 lines
25 KiB
Markdown
# 🚀 PLAN DE IMPLEMENTACIÓN CORRECTO - KCL Modular en Syntaxis
|
|
|
|
**Fecha**: 2025-11-20
|
|
**Estado**: Listo para implementación
|
|
**Basado en**: ARCHITECTURE_CORRECT_FINAL.md
|
|
|
|
---
|
|
|
|
## 📋 Resumen Ejecutivo
|
|
|
|
Crearemos 5 módulos KCL en `syntaxis/configs/` que definan completamente el proyecto:
|
|
- Validación nativa
|
|
- Defaults inteligentes
|
|
- Herencia de presets
|
|
- Sin generación almacenada
|
|
|
|
---
|
|
|
|
## 🔧 Fase 1: Módulos KCL (5 archivos)
|
|
|
|
### Paso 1.1: Crear `syntaxis/configs/schemas.k`
|
|
|
|
**Archivo**: `/Users/Akasha/Development/syntaxis/configs/schemas.k`
|
|
|
|
```kcl
|
|
# syntaxis/configs/schemas.k
|
|
# Definiciones de tipos y esquemas con validación nativa
|
|
|
|
import regex
|
|
|
|
# Service Schema
|
|
schema Service:
|
|
"""Define un servicio de syntaxis"""
|
|
name: str
|
|
type: "binary" | "service" | "database"
|
|
|
|
# Validación: port requerido si type es service
|
|
port?: int
|
|
check: port is not None if type == "service", "Service debe tener port"
|
|
check: 1 <= port <= 65535 if port is not None, "Port debe estar entre 1-65535"
|
|
|
|
enabled: bool = False
|
|
requires: [str] = []
|
|
|
|
# Configuración operativa
|
|
restart_policy: "always" | "on-failure" | "never" = "on-failure"
|
|
restart_delay_seconds: int = 5
|
|
|
|
# Health check
|
|
health_check?: {
|
|
type: "http" | "tcp" | "script"
|
|
endpoint?: str
|
|
interval_seconds: int = 10
|
|
timeout_seconds: int = 5
|
|
}
|
|
|
|
# Database Schema
|
|
schema Database:
|
|
"""Configuración de base de datos"""
|
|
type: "sqlite" | "postgres" | "mysql" | "surrealdb"
|
|
|
|
# Validación por tipo
|
|
path?: str
|
|
check: path is not None if type == "sqlite", "SQLite requiere path"
|
|
|
|
host?: str = "localhost"
|
|
check: host is not None if type != "sqlite", "BD remota requiere host"
|
|
|
|
port?: int
|
|
user?: str = "syntaxis"
|
|
password?: str
|
|
|
|
# Cache Schema
|
|
schema Cache:
|
|
"""Configuración de caché"""
|
|
enabled: bool = False
|
|
type: "redis" | "memcached" = "redis"
|
|
host: str = "localhost"
|
|
port: int = 6379
|
|
|
|
# Preset Schema
|
|
schema Preset:
|
|
"""Define un preset de deployment"""
|
|
name: str
|
|
description: str
|
|
services_enabled: [str]
|
|
|
|
# Overrides específicos del preset
|
|
database_type?: "sqlite" | "postgres" | "mysql" | "surrealdb"
|
|
cache_enabled?: bool
|
|
|
|
# Manager para este preset
|
|
manager: "manual" | "provctl" | "provisioning" = "manual"
|
|
|
|
# Full Deployment Schema
|
|
schema Deployment:
|
|
"""Configuración completa de deployment"""
|
|
project: str = "syntaxis"
|
|
version: str
|
|
|
|
services: {str: Service}
|
|
presets: {str: Preset}
|
|
|
|
default_database: Database
|
|
default_cache: Cache
|
|
```
|
|
|
|
**Checklist**:
|
|
- [ ] Archivo creado en `/Users/Akasha/Development/syntaxis/configs/schemas.k`
|
|
- [ ] KCL compila sin errores: `kcl run schemas.k`
|
|
- [ ] Contiene 6 schemas (Service, Database, Cache, Preset, Deployment, más validaciones)
|
|
|
|
---
|
|
|
|
### Paso 1.2: Crear `syntaxis/configs/defaults.k`
|
|
|
|
**Archivo**: `/Users/Akasha/Development/syntaxis/configs/defaults.k`
|
|
|
|
```kcl
|
|
# syntaxis/configs/defaults.k
|
|
# Valores por defecto y constraints reutilizables
|
|
|
|
import .schemas
|
|
|
|
# Servicios por defecto (basados en services-catalog.toml)
|
|
default_services: {str: schemas.Service} = {
|
|
cli = schemas.Service {
|
|
name = "syntaxis-cli"
|
|
display_name = "syntaxis CLI"
|
|
description = "Command-line interface for project management"
|
|
type = "cli"
|
|
enabled = True
|
|
platform_support = ["linux", "macos", "windows"]
|
|
min_disk_space_mb = 50
|
|
min_memory_mb = 64
|
|
background_service = False
|
|
config_location = "~/.config/syntaxis"
|
|
database_required = True
|
|
database_types = ["sqlite", "surrealdb"]
|
|
}
|
|
|
|
tui = schemas.Service {
|
|
name = "syntaxis-tui"
|
|
display_name = "syntaxis TUI"
|
|
description = "Terminal UI for interactive project management"
|
|
type = "tui"
|
|
enabled = False
|
|
requires = ["syntaxis-cli"]
|
|
platform_support = ["linux", "macos"]
|
|
min_disk_space_mb = 50
|
|
min_memory_mb = 128
|
|
background_service = False
|
|
config_location = "~/.config/syntaxis"
|
|
database_required = True
|
|
database_types = ["sqlite", "surrealdb"]
|
|
}
|
|
|
|
api = schemas.Service {
|
|
name = "syntaxis-api"
|
|
display_name = "syntaxis REST API"
|
|
description = "REST API server for programmatic access to syntaxis"
|
|
type = "server"
|
|
port = 3000
|
|
enabled = False
|
|
requires = ["syntaxis-cli"]
|
|
optional = ["surrealdb"]
|
|
platform_support = ["linux", "macos", "windows"]
|
|
min_disk_space_mb = 100
|
|
min_memory_mb = 256
|
|
background_service = True
|
|
config_location = "~/.config/syntaxis"
|
|
database_required = True
|
|
database_types = ["sqlite", "surrealdb"]
|
|
health_check = {
|
|
type = "http"
|
|
endpoint = "http://127.0.0.1:3000/health"
|
|
method = "GET"
|
|
expected_status = 200
|
|
interval_seconds = 10
|
|
timeout_seconds = 5
|
|
}
|
|
}
|
|
|
|
dashboard = schemas.Service {
|
|
name = "syntaxis-dashboard"
|
|
display_name = "syntaxis Dashboard"
|
|
description = "Web-based dashboard UI for project management"
|
|
type = "web"
|
|
port = 8080
|
|
enabled = False
|
|
requires = ["syntaxis-api"]
|
|
platform_support = ["linux", "macos", "windows"]
|
|
min_disk_space_mb = 50
|
|
min_memory_mb = 128
|
|
background_service = True
|
|
config_location = "~/.config/syntaxis"
|
|
database_required = False
|
|
health_check = {
|
|
type = "http"
|
|
endpoint = "http://127.0.0.1:8080"
|
|
method = "GET"
|
|
expected_status = 200
|
|
interval_seconds = 10
|
|
timeout_seconds = 5
|
|
}
|
|
}
|
|
|
|
surrealdb = schemas.Service {
|
|
name = "surrealdb"
|
|
display_name = "SurrealDB"
|
|
description = "Multi-model document database"
|
|
type = "database"
|
|
port = 8000
|
|
enabled = False
|
|
platform_support = ["linux", "macos"]
|
|
min_disk_space_mb = 100
|
|
min_memory_mb = 256
|
|
background_service = True
|
|
config_location = "~/.config/syntaxis"
|
|
database_required = False
|
|
health_check = {
|
|
type = "http"
|
|
endpoint = "http://127.0.0.1:8000"
|
|
method = "GET"
|
|
expected_status = 200
|
|
interval_seconds = 10
|
|
timeout_seconds = 5
|
|
}
|
|
}
|
|
|
|
nats = schemas.Service {
|
|
name = "nats"
|
|
display_name = "NATS"
|
|
description = "Cloud-native messaging platform"
|
|
type = "messaging"
|
|
port = 4222
|
|
enabled = False
|
|
platform_support = ["linux", "macos"]
|
|
min_disk_space_mb = 50
|
|
min_memory_mb = 256
|
|
background_service = True
|
|
config_location = "~/.config/syntaxis"
|
|
database_required = False
|
|
health_check = {
|
|
type = "http"
|
|
endpoint = "http://127.0.0.1:8222/healthz"
|
|
method = "GET"
|
|
expected_status = 200
|
|
interval_seconds = 10
|
|
timeout_seconds = 5
|
|
}
|
|
}
|
|
}
|
|
|
|
# Bases de datos por defecto
|
|
default_databases: {str: schemas.Database} = {
|
|
sqlite = schemas.Database {
|
|
type = "sqlite"
|
|
path = "/var/lib/syntaxis/db.sqlite"
|
|
}
|
|
|
|
postgres = schemas.Database {
|
|
type = "postgres"
|
|
host = "localhost"
|
|
port = 5432
|
|
user = "syntaxis"
|
|
}
|
|
|
|
surrealdb = schemas.Database {
|
|
type = "surrealdb"
|
|
host = "localhost"
|
|
port = 8000
|
|
}
|
|
}
|
|
|
|
# Caché por defecto
|
|
default_cache: schemas.Cache = schemas.Cache {
|
|
enabled = False
|
|
type = "redis"
|
|
host = "localhost"
|
|
port = 6379
|
|
}
|
|
|
|
# Presets por defecto (basados en patterns de services-catalog.toml)
|
|
base_presets: {str: schemas.Preset} = {
|
|
local = schemas.Preset {
|
|
name = "local"
|
|
description = "CLI Only - Command-line only, no services"
|
|
services_enabled = ["cli"]
|
|
manager = "manual"
|
|
}
|
|
|
|
dev = schemas.Preset {
|
|
name = "dev"
|
|
description = "Development with API - Full development stack"
|
|
services_enabled = ["cli", "tui", "api", "dashboard", "surrealdb"]
|
|
manager = "provctl"
|
|
database_type = "sqlite"
|
|
cache_enabled = False
|
|
}
|
|
|
|
staging = schemas.Preset {
|
|
name = "staging"
|
|
description = "Staging environment - Multi-machine deployment"
|
|
services_enabled = ["cli", "api", "dashboard", "surrealdb", "nats"]
|
|
manager = "provisioning"
|
|
database_type = "postgres"
|
|
cache_enabled = True
|
|
}
|
|
|
|
production = schemas.Preset {
|
|
name = "production"
|
|
description = "Production - Minimal production deployment"
|
|
services_enabled = ["api", "surrealdb", "nats"]
|
|
manager = "provisioning"
|
|
database_type = "postgres"
|
|
cache_enabled = True
|
|
}
|
|
}
|
|
```
|
|
|
|
**Checklist**:
|
|
- [ ] Archivo creado en `/Users/Akasha/Development/syntaxis/configs/defaults.k`
|
|
- [ ] KCL compila: `kcl run defaults.k` (import de schemas.k debe funcionar)
|
|
- [ ] Contiene 5 servicios, 3 BDs, 1 caché, 4 presets
|
|
|
|
---
|
|
|
|
### Paso 1.3: Crear `syntaxis/configs/services.k`
|
|
|
|
**Archivo**: `/Users/Akasha/Development/syntaxis/configs/services.k`
|
|
|
|
```kcl
|
|
# syntaxis/configs/services.k
|
|
# Definiciones de servicios (usa defaults, permite personalización)
|
|
|
|
import .schemas
|
|
import .defaults
|
|
|
|
# Servicios con defaults aplicados
|
|
services: {str: schemas.Service} = defaults.default_services
|
|
```
|
|
|
|
**Checklist**:
|
|
- [ ] Archivo creado en `/Users/Akasha/Development/syntaxis/configs/services.k`
|
|
- [ ] KCL compila sin errores
|
|
|
|
**Nota**: Este archivo permite personalizar servicios en el futuro sin afectar defaults.
|
|
|
|
---
|
|
|
|
### Paso 1.4: Crear `syntaxis/configs/presets.k`
|
|
|
|
**Archivo**: `/Users/Akasha/Development/syntaxis/configs/presets.k`
|
|
|
|
```kcl
|
|
# syntaxis/configs/presets.k
|
|
# Definiciones de presets con capacidad de override
|
|
|
|
import .schemas
|
|
import .defaults
|
|
import .services
|
|
|
|
# Presets con defaults
|
|
presets: {str: schemas.Preset} = {
|
|
local = defaults.base_presets.local
|
|
|
|
dev = defaults.base_presets.dev {
|
|
# Puede refinarse aquí si necesita overrides específicos
|
|
}
|
|
|
|
staging = defaults.base_presets.staging {
|
|
# Overrides específicos si es necesario
|
|
}
|
|
|
|
production = defaults.base_presets.production {
|
|
# Overrides específicos si es necesario
|
|
}
|
|
}
|
|
```
|
|
|
|
**Checklist**:
|
|
- [ ] Archivo creado en `/Users/Akasha/Development/syntaxis/configs/presets.k`
|
|
- [ ] KCL compila sin errores
|
|
|
|
---
|
|
|
|
### Paso 1.5: Crear `syntaxis/configs/deployment.k`
|
|
|
|
**Archivo**: `/Users/Akasha/Development/syntaxis/configs/deployment.k`
|
|
|
|
```kcl
|
|
# syntaxis/configs/deployment.k
|
|
# Declaración principal que integra todo
|
|
|
|
import .schemas
|
|
import .services
|
|
import .presets
|
|
import .defaults
|
|
|
|
# Deployment principal
|
|
deployment: schemas.Deployment = schemas.Deployment {
|
|
project = "syntaxis"
|
|
version = "1.0.0"
|
|
|
|
services = services
|
|
presets = presets
|
|
|
|
default_database = defaults.default_databases.sqlite
|
|
default_cache = defaults.default_cache
|
|
}
|
|
|
|
# Export principales para consumidores
|
|
export {
|
|
deployment
|
|
services
|
|
presets
|
|
default_databases = defaults.default_databases
|
|
default_cache = defaults.default_cache
|
|
}
|
|
```
|
|
|
|
**Checklist**:
|
|
- [ ] Archivo creado en `/Users/Akasha/Development/syntaxis/configs/deployment.k`
|
|
- [ ] KCL compila y exporta: `kcl run deployment.k`
|
|
- [ ] Export contiene deployment, services, presets, databases, cache
|
|
|
|
---
|
|
|
|
## 🔄 Validación de Módulos KCL
|
|
|
|
Después de crear los 5 archivos:
|
|
|
|
```bash
|
|
# Test 1: Compilación de cada módulo
|
|
kcl run syntaxis/configs/schemas.k
|
|
kcl run syntaxis/configs/defaults.k
|
|
kcl run syntaxis/configs/services.k
|
|
kcl run syntaxis/configs/presets.k
|
|
kcl run syntaxis/configs/deployment.k
|
|
|
|
# Test 2: Export a JSON
|
|
kcl run syntaxis/configs/deployment.k --format json > /tmp/deployment.json
|
|
|
|
# Test 3: Validar output
|
|
cat /tmp/deployment.json | jq '.deployment'
|
|
```
|
|
|
|
**Resultado esperado**:
|
|
```json
|
|
{
|
|
"deployment": {
|
|
"project": "syntaxis",
|
|
"version": "1.0.0",
|
|
"services": {
|
|
"cli": { "name": "syntaxis-cli", "type": "binary", "enabled": true },
|
|
"api": { "name": "syntaxis-api", "type": "service", "port": 3000, ... },
|
|
...
|
|
},
|
|
"presets": {
|
|
"local": { "name": "local", ... },
|
|
"dev": { "name": "dev", ... },
|
|
...
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 🔧 Fase 2: Templates Tera (3 archivos)
|
|
|
|
### Paso 2.1: Crear `syntaxis/templates/provisioning-config.j2`
|
|
|
|
**Archivo**: `/Users/Akasha/Development/syntaxis/templates/provisioning-config.j2`
|
|
|
|
```jinja2
|
|
{# syntaxis/templates/provisioning-config.j2 #}
|
|
{# Genera configuración para provisioning desde KCL #}
|
|
|
|
# Configuración Syntaxis para provisioning
|
|
# Generado desde syntaxis/configs/deployment.k
|
|
|
|
project:
|
|
name = "{{ deployment.project }}"
|
|
version = "{{ deployment.version }}"
|
|
|
|
services:
|
|
{% for name, service in deployment.services %}
|
|
{% if service.enabled %}
|
|
"{{ name }}":
|
|
name = "{{ service.name }}"
|
|
type = "{{ service.type }}"
|
|
{% if service.port %}
|
|
port = {{ service.port }}
|
|
{% endif %}
|
|
restart_policy = "{{ service.restart_policy }}"
|
|
requires = [
|
|
{% for req in service.requires %}"{{ req }}"{{ "," if not loop.last else "" }}{% endfor %}
|
|
]
|
|
{% if service.health_check %}
|
|
health_check = {
|
|
type = "{{ service.health_check.type }}"
|
|
{% if service.health_check.endpoint %}
|
|
endpoint = "{{ service.health_check.endpoint }}"
|
|
{% endif %}
|
|
interval_seconds = {{ service.health_check.interval_seconds }}
|
|
timeout_seconds = {{ service.health_check.timeout_seconds }}
|
|
}
|
|
{% endif %}
|
|
{% endif %}
|
|
{% endfor %}
|
|
|
|
database:
|
|
type = "{{ deployment.default_database.type }}"
|
|
{% if deployment.default_database.host %}
|
|
host = "{{ deployment.default_database.host }}"
|
|
{% endif %}
|
|
{% if deployment.default_database.port %}
|
|
port = {{ deployment.default_database.port }}
|
|
{% endif %}
|
|
{% if deployment.default_database.path %}
|
|
path = "{{ deployment.default_database.path }}"
|
|
{% endif %}
|
|
|
|
cache:
|
|
enabled = {{ deployment.default_cache.enabled | lower }}
|
|
{% if deployment.default_cache.enabled %}
|
|
type = "{{ deployment.default_cache.type }}"
|
|
host = "{{ deployment.default_cache.host }}"
|
|
port = {{ deployment.default_cache.port }}
|
|
{% endif %}
|
|
```
|
|
|
|
**Checklist**:
|
|
- [ ] Archivo creado en `/Users/Akasha/Development/syntaxis/templates/provisioning-config.j2`
|
|
- [ ] Contiene loop sobre servicios, databases, cache
|
|
|
|
---
|
|
|
|
### Paso 2.2: Crear `syntaxis/templates/provctl-config.j2`
|
|
|
|
**Archivo**: `/Users/Akasha/Development/syntaxis/templates/provctl-config.j2`
|
|
|
|
```jinja2
|
|
{# syntaxis/templates/provctl-config.j2 #}
|
|
{# Genera TOML para provctl #}
|
|
|
|
# Configuración Syntaxis para provctl
|
|
# Generado desde syntaxis/configs/deployment.k
|
|
|
|
{% for name, service in deployment.services %}
|
|
{% if service.enabled %}
|
|
[[services]]
|
|
name = "{{ service.name }}"
|
|
type = "{{ service.type }}"
|
|
{% if service.port %}
|
|
port = {{ service.port }}
|
|
{% endif %}
|
|
restart_policy = "{{ service.restart_policy }}"
|
|
|
|
{% if service.health_check %}
|
|
[services.health_check]
|
|
type = "{{ service.health_check.type }}"
|
|
{% if service.health_check.endpoint %}
|
|
endpoint = "{{ service.health_check.endpoint }}"
|
|
{% endif %}
|
|
interval_seconds = {{ service.health_check.interval_seconds }}
|
|
timeout_seconds = {{ service.health_check.timeout_seconds }}
|
|
{% endif %}
|
|
|
|
{% endif %}
|
|
{% endfor %}
|
|
|
|
[database]
|
|
type = "{{ deployment.default_database.type }}"
|
|
{% if deployment.default_database.host %}
|
|
host = "{{ deployment.default_database.host }}"
|
|
{% endif %}
|
|
{% if deployment.default_database.port %}
|
|
port = {{ deployment.default_database.port }}
|
|
{% endif %}
|
|
{% if deployment.default_database.path %}
|
|
path = "{{ deployment.default_database.path }}"
|
|
{% endif %}
|
|
|
|
[cache]
|
|
enabled = {{ deployment.default_cache.enabled | lower }}
|
|
{% if deployment.default_cache.enabled %}
|
|
type = "{{ deployment.default_cache.type }}"
|
|
host = "{{ deployment.default_cache.host }}"
|
|
port = {{ deployment.default_cache.port }}
|
|
{% endif %}
|
|
```
|
|
|
|
**Checklist**:
|
|
- [ ] Archivo creado en `/Users/Akasha/Development/syntaxis/templates/provctl-config.j2`
|
|
- [ ] Genera TOML válido
|
|
|
|
---
|
|
|
|
### Paso 2.3: Crear `syntaxis/templates/installer-settings.j2`
|
|
|
|
**Archivo**: `/Users/Akasha/Development/syntaxis/templates/installer-settings.j2`
|
|
|
|
```jinja2
|
|
{# syntaxis/templates/installer-settings.j2 #}
|
|
{# Genera JSON/YAML para installer interactivo #}
|
|
|
|
{
|
|
"preset": "{{ preset }}",
|
|
"description": "{{ preset_description }}",
|
|
"services": [
|
|
{% for service in services_enabled %}
|
|
"{{ service }}"{{ "," if not loop.last else "" }}
|
|
{% endfor %}
|
|
],
|
|
"database": {
|
|
"type": "{{ database_type }}"
|
|
{% if database_type == "postgres" %}
|
|
,"host": "{{ database_host | default("localhost") }}",
|
|
"port": {{ database_port | default(5432) }},
|
|
"user": "{{ database_user | default("syntaxis") }}"
|
|
{% elif database_type == "sqlite" %}
|
|
,"path": "{{ database_path | default("/var/lib/syntaxis/db.sqlite") }}"
|
|
{% elif database_type == "surrealdb" %}
|
|
,"host": "{{ database_host | default("localhost") }}",
|
|
"port": {{ database_port | default(8000) }}
|
|
{% endif %}
|
|
},
|
|
"cache": {
|
|
"enabled": {{ cache_enabled | lower }}
|
|
{% if cache_enabled %}
|
|
,"type": "{{ cache_type | default("redis") }}",
|
|
"host": "{{ cache_host | default("localhost") }}",
|
|
"port": {{ cache_port | default(6379) }}
|
|
{% endif %}
|
|
}
|
|
}
|
|
```
|
|
|
|
**Checklist**:
|
|
- [ ] Archivo creado en `/Users/Akasha/Development/syntaxis/templates/installer-settings.j2`
|
|
- [ ] Genera JSON válido
|
|
|
|
---
|
|
|
|
## 🔧 Fase 3: Script NuShell (1 archivo)
|
|
|
|
### Paso 3.1: Crear `syntaxis/scripts/export-config.nu`
|
|
|
|
**Archivo**: `/Users/Akasha/Development/syntaxis/scripts/export-config.nu`
|
|
|
|
```nushell
|
|
# syntaxis/scripts/export-config.nu
|
|
# Exporta KCL a YAML/JSON on-demand (sin guardar)
|
|
|
|
# Función principal: exportar deployment
|
|
def export-deployment [format: string = "yaml"] -> string {
|
|
"""
|
|
Exporta deployment.k a YAML o JSON
|
|
|
|
Ejemplos:
|
|
export-deployment # YAML por defecto
|
|
export-deployment --format json # Exporta como JSON
|
|
"""
|
|
|
|
# 1. Llamar kcl compile para obtener resultado
|
|
let kcl_output = (
|
|
kcl run ([$env.PWD, "configs", "deployment.k"] | path join)
|
|
--format json
|
|
| from json
|
|
)
|
|
|
|
# 2. Convertir según formato requerido
|
|
match $format {
|
|
"json" => {
|
|
$kcl_output | to json
|
|
}
|
|
"yaml" => {
|
|
# Convertir JSON a YAML
|
|
$kcl_output | to json | from json | to yaml
|
|
}
|
|
_ => {
|
|
error make {
|
|
msg: "Formato no soportado: $format (usa 'json' o 'yaml')"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
# Función: obtener preset específico
|
|
def get-preset [preset: string] -> string {
|
|
"""
|
|
Obtiene un preset específico en formato YAML
|
|
|
|
Ejemplo: get-preset dev
|
|
"""
|
|
|
|
let deployment = (export-deployment yaml | from yaml)
|
|
|
|
if ($preset not-in $deployment.deployment.presets) {
|
|
error make {
|
|
msg: "Preset '$preset' no existe"
|
|
}
|
|
}
|
|
|
|
$deployment.deployment.presets | get $preset | to yaml
|
|
}
|
|
|
|
# Función: listar servicios de preset
|
|
def get-services [preset: string] -> list {
|
|
"""
|
|
Lista servicios habilitados en un preset
|
|
|
|
Ejemplo: get-services dev
|
|
"""
|
|
|
|
let deployment = (export-deployment yaml | from yaml)
|
|
$deployment.deployment.presets | get $preset | get services_enabled
|
|
}
|
|
|
|
# Exportar comandos
|
|
export def "config export" [format: string = "yaml"] {
|
|
"""Export deployment configuration to YAML or JSON"""
|
|
export-deployment $format
|
|
}
|
|
|
|
export def "config preset" [preset: string] {
|
|
"""Get a specific preset configuration"""
|
|
get-preset $preset
|
|
}
|
|
|
|
export def "config services" [preset: string] {
|
|
"""List services enabled for a preset"""
|
|
get-services $preset
|
|
}
|
|
```
|
|
|
|
**Checklist**:
|
|
- [ ] Archivo creado en `/Users/Akasha/Development/syntaxis/scripts/export-config.nu`
|
|
- [ ] Script es ejecutable: `chmod +x syntaxis/scripts/export-config.nu`
|
|
|
|
---
|
|
|
|
## ✅ Validación Completa
|
|
|
|
### Test Suite
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
set -e
|
|
|
|
echo "=== Testing KCL Modules ==="
|
|
|
|
# Test 1: Compilación individual
|
|
echo "1. Testing schemas.k..."
|
|
kcl run syntaxis/configs/schemas.k > /dev/null
|
|
echo " ✅ schemas.k compila"
|
|
|
|
echo "2. Testing defaults.k..."
|
|
kcl run syntaxis/configs/defaults.k > /dev/null
|
|
echo " ✅ defaults.k compila"
|
|
|
|
echo "3. Testing services.k..."
|
|
kcl run syntaxis/configs/services.k > /dev/null
|
|
echo " ✅ services.k compila"
|
|
|
|
echo "4. Testing presets.k..."
|
|
kcl run syntaxis/configs/presets.k > /dev/null
|
|
echo " ✅ presets.k compila"
|
|
|
|
echo "5. Testing deployment.k..."
|
|
kcl run syntaxis/configs/deployment.k > /dev/null
|
|
echo " ✅ deployment.k compila"
|
|
|
|
# Test 2: Export
|
|
echo ""
|
|
echo "=== Testing Exports ==="
|
|
|
|
echo "6. Testing JSON export..."
|
|
kcl run syntaxis/configs/deployment.k --format json > /tmp/deployment.json
|
|
echo " ✅ JSON export successful"
|
|
|
|
echo "7. Testing YAML export..."
|
|
nu syntaxis/scripts/export-config.nu yaml > /tmp/deployment.yaml
|
|
echo " ✅ YAML export successful"
|
|
|
|
# Test 3: Validación de estructura
|
|
echo ""
|
|
echo "=== Validating Structure ==="
|
|
|
|
echo "8. Checking deployment structure..."
|
|
jq '.deployment | keys' /tmp/deployment.json | grep -q "project\|version\|services\|presets"
|
|
echo " ✅ Deployment has correct keys"
|
|
|
|
echo "9. Checking services..."
|
|
jq '.deployment.services | keys' /tmp/deployment.json | grep -q "cli\|api"
|
|
echo " ✅ Services defined"
|
|
|
|
echo "10. Checking presets..."
|
|
jq '.deployment.presets | keys' /tmp/deployment.json | grep -q "local\|dev\|staging\|production"
|
|
echo " ✅ All presets present"
|
|
|
|
echo ""
|
|
echo "=== ✅ ALL TESTS PASSED ==="
|
|
```
|
|
|
|
**Checklist**:
|
|
- [ ] Todos los .k compilan sin errores
|
|
- [ ] JSON export generado correctamente
|
|
- [ ] YAML export generado correctamente
|
|
- [ ] Estructura contiene keys esperadas
|
|
|
|
---
|
|
|
|
## 🎯 Próximos Pasos Después de Implementación
|
|
|
|
### Paso 4: Integración con syntaxis-installer
|
|
|
|
```rust
|
|
// En syntaxis-installer
|
|
|
|
fn load_deployment() -> Result<Deployment> {
|
|
// Cargar deployment.k directamente
|
|
let kcl_output = Command::new("kcl")
|
|
.arg("run")
|
|
.arg("configs/deployment.k")
|
|
.arg("--format")
|
|
.arg("json")
|
|
.output()?;
|
|
|
|
let json: Value = serde_json::from_slice(&kcl_output.stdout)?;
|
|
Ok(serde_json::from_value(json["deployment"].clone())?)
|
|
}
|
|
|
|
fn get_preset_for_user() -> Result<String> {
|
|
println!("¿Cómo deseas instalar Syntaxis?");
|
|
println!("1. local - CLI only");
|
|
println!("2. dev - Full stack + provctl");
|
|
println!("3. staging - Multi-machine");
|
|
println!("4. production - HA");
|
|
|
|
// User selecciona...
|
|
// Si dev: genera config con NuShell + Tera
|
|
// Si provisioning: guía al usuario
|
|
}
|
|
```
|
|
|
|
### Paso 5: Integración con provisioning
|
|
|
|
```kcl
|
|
// En provisioning/kcl/workspace.k
|
|
|
|
import /path/to/syntaxis/configs/deployment as sx
|
|
|
|
// Usar declaración de syntaxis
|
|
syntaxis_deployment = sx.deployment
|
|
|
|
// Validar y adaptar a provisioning
|
|
// (provisioning puede leer KCL directamente)
|
|
```
|
|
|
|
### Paso 6: Integración con provctl (via NuShell)
|
|
|
|
```bash
|
|
# Durante instalación en modo "dev":
|
|
|
|
# 1. Export KCL a YAML (temporal)
|
|
nu syntaxis/scripts/export-config.nu yaml > /tmp/deployment.yaml
|
|
|
|
# 2. Usar Tera para adaptar a provctl
|
|
tera --template syntaxis/templates/provctl-config.j2 \
|
|
--input /tmp/deployment.yaml \
|
|
> /tmp/provctl-config.toml
|
|
|
|
# 3. Aplicar con provctl
|
|
provctl config apply /tmp/provctl-config.toml
|
|
|
|
# 4. No guardar los archivos temporales
|
|
rm /tmp/deployment.yaml /tmp/provctl-config.toml
|
|
```
|
|
|
|
---
|
|
|
|
## 📊 Resumen de Archivos a Crear
|
|
|
|
| Archivo | Ubicación | Tipo | Contenido |
|
|
|---------|-----------|------|----------|
|
|
| schemas.k | `syntaxis/configs/` | KCL | 6 schemas con validación |
|
|
| defaults.k | `syntaxis/configs/` | KCL | 5 servicios, 3 BDs, 1 caché, 4 presets |
|
|
| services.k | `syntaxis/configs/` | KCL | Referencia a defaults |
|
|
| presets.k | `syntaxis/configs/` | KCL | Override-capable presets |
|
|
| deployment.k | `syntaxis/configs/` | KCL | Declaración principal + exports |
|
|
| provisioning-config.j2 | `syntaxis/templates/` | Tera | Config para provisioning |
|
|
| provctl-config.j2 | `syntaxis/templates/` | Tera | TOML para provctl |
|
|
| installer-settings.j2 | `syntaxis/templates/` | Tera | JSON para installer |
|
|
| export-config.nu | `syntaxis/scripts/` | NuShell | On-demand export a YAML/JSON |
|
|
|
|
**Total**: 9 archivos nuevos
|
|
|
|
---
|
|
|
|
## ✅ Checklist Final
|
|
|
|
- [ ] Fase 1: 5 módulos KCL creados y compilables
|
|
- [ ] Fase 2: 3 templates Tera creados
|
|
- [ ] Fase 3: 1 script NuShell creado
|
|
- [ ] Validación: Todos los tests pasan
|
|
- [ ] Integración: syntaxis-installer usa presets
|
|
- [ ] Integración: provisioning puede leer deployment.k
|
|
- [ ] Integración: provctl recibe config via NuShell + Tera
|
|
|
|
---
|
|
|
|
## 🎓 Conceptos Clave
|
|
|
|
### KCL como Fuente de Verdad
|
|
- Módulos independientes pero conectados
|
|
- Validación compile-time
|
|
- Defaults inteligentes
|
|
- Herencia de presets
|
|
- Versionado con código
|
|
|
|
### Generación On-Demand
|
|
- `kcl run deployment.k` genera JSON
|
|
- NuShell convierte a YAML si es necesario
|
|
- Tera templates adaptan al consumidor
|
|
- Archivos temporales, no almacenados
|
|
|
|
### Consumo Adaptativo
|
|
- provisioning: lee .k directamente
|
|
- provctl: recibe YAML via NuShell
|
|
- installer: parametrizado via templates
|
|
- Cada uno adapta según necesidad
|
|
|
|
---
|
|
|
|
**Siguiente paso**: Ejecutar Fase 1 (crear 5 módulos KCL) y validar compilación.
|