ソースを参照

feat: Add schema 1.2 with dedicated volume and resources sections

- Add spec_v1_2.py with new volume and resources sections
- Volume section: Replaces swarm_volume_* vars, works universally
- Resources section: CPU/memory limits for production deployments
- Ports section: Add ports_http and ports_https variables
- Update compose module to support schema 1.2
- Create new v2 archetypes:
  - service-volumes-v2.j2: Uses volume_mode
  - volumes-v2.j2: Top-level volumes with new section
  - service-resources-v1.j2: Resource limits

Related: #1519
xcad 4 ヶ月 前
コミット
cc714f78e0

+ 28 - 0
archetypes/compose/service-resources-v1.j2

@@ -0,0 +1,28 @@
+{#
+  Archetype: service-resources-v1
+  
+  Description:
+    Resource limits (CPU/memory) for production deployments (schema 1.2+).
+  
+  Approach:
+    - Standalone mode: Uses deploy.resources (Compose spec v3+)
+    - Swarm mode: Includes reservations for resource guarantees
+    - CPU limits specified as decimal (0.5, 1.0, 2.0)
+    - Memory limits with units (512M, 1G, 2G)
+  
+  Usage:
+    Use for production services that need resource constraints.
+    Prevents resource exhaustion and enables better capacity planning.
+#}
+    {% if resources_enabled %}
+    deploy:
+      resources:
+        limits:
+          cpus: '{{ resources_cpu_limit }}'
+          memory: {{ resources_memory_limit }}
+        {% if swarm_enabled %}
+        reservations:
+          cpus: '{{ resources_cpu_reservation }}'
+          memory: {{ resources_memory_reservation }}
+        {% endif %}
+    {% endif %}

+ 22 - 0
archetypes/compose/service-volumes-v2.j2

@@ -0,0 +1,22 @@
+{#
+  Archetype: service-volumes-v2
+  
+  Description:
+    Service volume mounts using dedicated volume section (schema 1.2+).
+  
+  Approach:
+    - Uses volume_mode instead of swarm_volume_mode
+    - Standalone mode: Uses named volumes
+    - Mount mode: Uses bind mounts from volume_mount_path
+    - NFS mode: Uses named volumes with NFS driver
+  
+  Usage:
+    Use for schema 1.2+ templates that need persistent storage.
+    The volume section works for both standalone and swarm modes.
+#}
+    volumes:
+      {% if volume_mode == 'mount' %}
+      - {{ volume_mount_path }}/data:/data:rw
+      {% else %}
+      - {{ volume_name }}:/data
+      {% endif %}

+ 29 - 0
archetypes/compose/volumes-v2.j2

@@ -0,0 +1,29 @@
+{#
+  Archetype: volumes-v2
+  
+  Description:
+    Top-level volumes section using dedicated volume section (schema 1.2+).
+  
+  Approach:
+    - Uses volume_mode instead of swarm_volume_mode
+    - Mount mode: No volume definition (uses bind mounts)
+    - Local mode: Simple local volumes
+    - NFS mode: Network filesystem with driver options
+  
+  Usage:
+    Use for schema 1.2+ templates with the new volume section.
+    Works universally for both standalone and swarm modes.
+#}
+{% if volume_mode == 'local' %}
+volumes:
+  {{ volume_name }}:
+    driver: local
+{% elif volume_mode == 'nfs' %}
+volumes:
+  {{ volume_name }}:
+    driver: local
+    driver_opts:
+      type: nfs
+      o: addr={{ volume_nfs_server }},{{ volume_nfs_options }}
+      device: ":{{ volume_nfs_path }}"
+{% endif %}

+ 4 - 2
cli/modules/compose/__init__.py

@@ -6,15 +6,17 @@ from ...core.registry import registry
 # Import schema specifications
 from .spec_v1_0 import spec as spec_1_0
 from .spec_v1_1 import spec as spec_1_1
+from .spec_v1_2 import spec as spec_1_2
 
 # Schema version mapping
 SCHEMAS = {
     "1.0": spec_1_0,
     "1.1": spec_1_1,
+    "1.2": spec_1_2,
 }
 
 # Default spec points to latest version
-spec = spec_1_1
+spec = spec_1_2
 
 
 class ComposeModule(Module):
@@ -22,7 +24,7 @@ class ComposeModule(Module):
 
     name = "compose"
     description = "Manage Docker Compose configurations"
-    schema_version = "1.1"  # Current schema version supported by this module
+    schema_version = "1.2"  # Current schema version supported by this module
     schemas = SCHEMAS  # Available schema versions
 
 

+ 420 - 0
cli/modules/compose/spec_v1_2.py

@@ -0,0 +1,420 @@
+"""Compose module schema version 1.2 - Dedicated Volume and Resources sections.
+
+Changes from 1.1:
+- volume: New dedicated section for volume configuration (replaces swarm_volume_* vars)
+- resources: New section for CPU/memory limits
+- ports: Added port configuration variables
+- Backward compatible: Old swarm_volume_* variables still work
+"""
+
+from collections import OrderedDict
+
+spec = OrderedDict(
+    {
+        "general": {
+            "title": "General",
+            "vars": {
+                "service_name": {
+                    "description": "Service name",
+                    "type": "str",
+                },
+                "container_name": {
+                    "description": "Container name",
+                    "type": "str",
+                },
+                "container_hostname": {
+                    "description": "Container internal hostname",
+                    "type": "str",
+                },
+                "container_timezone": {
+                    "description": "Container timezone (e.g., Europe/Berlin)",
+                    "type": "str",
+                    "default": "UTC",
+                },
+                "user_uid": {
+                    "description": "User UID for container process",
+                    "type": "int",
+                    "default": 1000,
+                },
+                "user_gid": {
+                    "description": "User GID for container process",
+                    "type": "int",
+                    "default": 1000,
+                },
+                "container_loglevel": {
+                    "description": "Container log level",
+                    "type": "enum",
+                    "options": ["debug", "info", "warn", "error"],
+                    "default": "info",
+                },
+                "restart_policy": {
+                    "description": "Container restart policy",
+                    "type": "enum",
+                    "options": ["unless-stopped", "always", "on-failure", "no"],
+                    "default": "unless-stopped",
+                },
+            },
+        },
+        "network": {
+            "title": "Network",
+            "vars": {
+                "network_mode": {
+                    "description": "Docker network mode",
+                    "type": "enum",
+                    "options": ["bridge", "host", "macvlan"],
+                    "default": "bridge",
+                },
+                "network_name": {
+                    "description": "Docker network name",
+                    "type": "str",
+                    "default": "bridge",
+                    "needs": "network_mode=bridge,macvlan",
+                },
+                "network_external": {
+                    "description": "Use existing Docker network (external)",
+                    "type": "bool",
+                    "default": False,
+                    "needs": "network_mode=bridge,macvlan",
+                },
+                "network_macvlan_ipv4_address": {
+                    "description": "Static IP address for container",
+                    "type": "str",
+                    "default": "192.168.1.253",
+                    "needs": "network_mode=macvlan",
+                },
+                "network_macvlan_parent_interface": {
+                    "description": "Host network interface name",
+                    "type": "str",
+                    "default": "eth0",
+                    "needs": "network_mode=macvlan",
+                },
+                "network_macvlan_subnet": {
+                    "description": "Network subnet in CIDR notation",
+                    "type": "str",
+                    "default": "192.168.1.0/24",
+                    "needs": "network_mode=macvlan",
+                },
+                "network_macvlan_gateway": {
+                    "description": "Network gateway IP address",
+                    "type": "str",
+                    "default": "192.168.1.1",
+                    "needs": "network_mode=macvlan",
+                },
+            },
+        },
+        "ports": {
+            "title": "Ports",
+            "toggle": "ports_enabled",
+            "needs": "network_mode=bridge",
+            "description": "Expose service ports to the host.",
+            "vars": {
+                "ports_http": {
+                    "description": "HTTP port on host",
+                    "type": "int",
+                    "default": 8080,
+                },
+                "ports_https": {
+                    "description": "HTTPS port on host",
+                    "type": "int",
+                    "default": 8443,
+                },
+            },
+        },
+        "traefik": {
+            "title": "Traefik",
+            "toggle": "traefik_enabled",
+            "needs": "network_mode=bridge",
+            "description": "Traefik routes external traffic to your service.",
+            "vars": {
+                "traefik_enabled": {
+                    "description": "Enable Traefik reverse proxy integration",
+                    "type": "bool",
+                    "default": False,
+                },
+                "traefik_network": {
+                    "description": "Traefik network name",
+                    "type": "str",
+                    "default": "traefik",
+                },
+                "traefik_host": {
+                    "description": "Domain name for your service (e.g., app.example.com)",
+                    "type": "str",
+                },
+                "traefik_entrypoint": {
+                    "description": "HTTP entrypoint (non-TLS)",
+                    "type": "str",
+                    "default": "web",
+                },
+            },
+        },
+        "traefik_tls": {
+            "title": "Traefik TLS/SSL",
+            "toggle": "traefik_tls_enabled",
+            "needs": "traefik_enabled=true;network_mode=bridge",
+            "description": "Enable HTTPS/TLS for Traefik with certificate management.",
+            "vars": {
+                "traefik_tls_enabled": {
+                    "description": "Enable HTTPS/TLS",
+                    "type": "bool",
+                    "default": True,
+                },
+                "traefik_tls_entrypoint": {
+                    "description": "TLS entrypoint",
+                    "type": "str",
+                    "default": "websecure",
+                },
+                "traefik_tls_certresolver": {
+                    "description": "Traefik certificate resolver name",
+                    "type": "str",
+                    "default": "cloudflare",
+                },
+            },
+        },
+        "volume": {
+            "title": "Volume Storage",
+            "description": "Configure persistent storage for your service.",
+            "vars": {
+                "volume_mode": {
+                    "description": "Volume storage backend",
+                    "type": "enum",
+                    "options": ["local", "mount", "nfs"],
+                    "default": "local",
+                    "extra": "local: Docker-managed volumes | mount: Bind mount from host | nfs: Network filesystem",
+                },
+                "volume_mount_path": {
+                    "description": "Host path for bind mounts",
+                    "type": "str",
+                    "default": "/mnt/storage",
+                    "needs": "volume_mode=mount",
+                },
+                "volume_nfs_server": {
+                    "description": "NFS server address",
+                    "type": "str",
+                    "default": "192.168.1.1",
+                    "needs": "volume_mode=nfs",
+                },
+                "volume_nfs_path": {
+                    "description": "NFS export path",
+                    "type": "str",
+                    "default": "/export",
+                    "needs": "volume_mode=nfs",
+                },
+                "volume_nfs_options": {
+                    "description": "NFS mount options (comma-separated)",
+                    "type": "str",
+                    "default": "rw,nolock,soft",
+                    "needs": "volume_mode=nfs",
+                },
+            },
+        },
+        "resources": {
+            "title": "Resource Limits",
+            "toggle": "resources_enabled",
+            "description": "Set CPU and memory limits for the service.",
+            "vars": {
+                "resources_cpu_limit": {
+                    "description": "Maximum CPU cores (e.g., 0.5, 1.0, 2.0)",
+                    "type": "str",
+                    "default": "1.0",
+                },
+                "resources_cpu_reservation": {
+                    "description": "Reserved CPU cores",
+                    "type": "str",
+                    "default": "0.25",
+                    "needs": "swarm_enabled=true",
+                },
+                "resources_memory_limit": {
+                    "description": "Maximum memory (e.g., 512M, 1G, 2G)",
+                    "type": "str",
+                    "default": "1G",
+                },
+                "resources_memory_reservation": {
+                    "description": "Reserved memory",
+                    "type": "str",
+                    "default": "512M",
+                    "needs": "swarm_enabled=true",
+                },
+            },
+        },
+        "swarm": {
+            "title": "Docker Swarm",
+            "needs": "network_mode=bridge",
+            "toggle": "swarm_enabled",
+            "description": "Deploy service in Docker Swarm mode.",
+            "vars": {
+                "swarm_enabled": {
+                    "description": "Enable Docker Swarm mode",
+                    "type": "bool",
+                    "default": False,
+                },
+                "swarm_placement_mode": {
+                    "description": "Swarm placement mode",
+                    "type": "enum",
+                    "options": ["replicated", "global"],
+                    "default": "replicated",
+                },
+                "swarm_replicas": {
+                    "description": "Number of replicas",
+                    "type": "int",
+                    "default": 1,
+                    "needs": "swarm_placement_mode=replicated",
+                },
+                "swarm_placement_host": {
+                    "description": "Target hostname for placement constraint",
+                    "type": "str",
+                    "default": "",
+                    "optional": True,
+                    "needs": "swarm_placement_mode=replicated",
+                    "extra": "Constrains service to run on specific node by hostname",
+                },
+                "swarm_volume_mode": {
+                    "description": "Swarm volume storage backend",
+                    "type": "enum",
+                    "options": ["local", "mount", "nfs"],
+                    "default": "local",
+                    "extra": "WARNING: 'local' only works on single-node deployments!",
+                },
+                "swarm_volume_mount_path": {
+                    "description": "Host path for bind mount",
+                    "type": "str",
+                    "default": "/mnt/storage",
+                    "needs": "swarm_volume_mode=mount",
+                    "extra": "Useful for shared/replicated storage",
+                },
+                "swarm_volume_nfs_server": {
+                    "description": "NFS server address",
+                    "type": "str",
+                    "default": "192.168.1.1",
+                    "needs": "swarm_volume_mode=nfs",
+                    "extra": "IP address or hostname of NFS server",
+                },
+                "swarm_volume_nfs_path": {
+                    "description": "NFS export path",
+                    "type": "str",
+                    "default": "/export",
+                    "needs": "swarm_volume_mode=nfs",
+                    "extra": "Path to NFS export on the server",
+                },
+                "swarm_volume_nfs_options": {
+                    "description": "NFS mount options",
+                    "type": "str",
+                    "default": "rw,nolock,soft",
+                    "needs": "swarm_volume_mode=nfs",
+                    "extra": "Comma-separated NFS mount options",
+                },
+            },
+        },
+        "database": {
+            "title": "Database",
+            "toggle": "database_enabled",
+            "vars": {
+                "database_type": {
+                    "description": "Database type",
+                    "type": "enum",
+                    "options": ["default", "sqlite", "postgres", "mysql"],
+                    "default": "default",
+                },
+                "database_external": {
+                    "description": "Use an external database server?",
+                    "extra": "skips creation of internal database container",
+                    "type": "bool",
+                    "default": False,
+                },
+                "database_host": {
+                    "description": "Database host",
+                    "type": "str",
+                    "default": "database",
+                },
+                "database_port": {"description": "Database port", "type": "int"},
+                "database_name": {
+                    "description": "Database name",
+                    "type": "str",
+                },
+                "database_user": {
+                    "description": "Database user",
+                    "type": "str",
+                },
+                "database_password": {
+                    "description": "Database password",
+                    "type": "str",
+                    "default": "",
+                    "sensitive": True,
+                    "autogenerated": True,
+                },
+            },
+        },
+        "email": {
+            "title": "Email Server",
+            "toggle": "email_enabled",
+            "description": "Configure email server for notifications and user management.",
+            "vars": {
+                "email_enabled": {
+                    "description": "Enable email server configuration",
+                    "type": "bool",
+                    "default": False,
+                },
+                "email_host": {
+                    "description": "SMTP server hostname",
+                    "type": "str",
+                },
+                "email_port": {
+                    "description": "SMTP server port",
+                    "type": "int",
+                    "default": 587,
+                },
+                "email_username": {
+                    "description": "SMTP username",
+                    "type": "str",
+                },
+                "email_password": {
+                    "description": "SMTP password",
+                    "type": "str",
+                    "sensitive": True,
+                },
+                "email_from": {
+                    "description": "From email address",
+                    "type": "str",
+                },
+                "email_use_tls": {
+                    "description": "Use TLS encryption",
+                    "type": "bool",
+                    "default": True,
+                },
+                "email_use_ssl": {
+                    "description": "Use SSL encryption",
+                    "type": "bool",
+                    "default": False,
+                },
+            },
+        },
+        "authentik": {
+            "title": "Authentik SSO",
+            "toggle": "authentik_enabled",
+            "description": "Integrate with Authentik for Single Sign-On authentication.",
+            "vars": {
+                "authentik_enabled": {
+                    "description": "Enable Authentik SSO integration",
+                    "type": "bool",
+                    "default": False,
+                },
+                "authentik_url": {
+                    "description": "Authentik base URL (e.g., https://auth.example.com)",
+                    "type": "str",
+                },
+                "authentik_slug": {
+                    "description": "Authentik application slug",
+                    "type": "str",
+                },
+                "authentik_client_id": {
+                    "description": "OAuth client ID from Authentik provider",
+                    "type": "str",
+                },
+                "authentik_client_secret": {
+                    "description": "OAuth client secret from Authentik provider",
+                    "type": "str",
+                    "sensitive": True,
+                },
+            },
+        },
+    }
+)