Procházet zdrojové kódy

refactor: completely remove schema system and sorting - v0.1.3 fully self-contained

- Remove all schema-related code: module_specs, merged_specs, _validate_schema_version()
- Delete cli/core/schema/ and library/schemas/ directories completely
- Simplify template variable collection to use only template specs directly
- Remove section sorting - preserve order from template.yaml files
- Simplify _merge_specs() and _filter_specs_to_used() methods
- Remove all @property decorators for schema-related attributes
- All 70 templates now fully self-contained with explicit variable definitions
- Templates maintain schema: "1.2" property for backwards compatibility with old clients
- No functional impact - all tests passing, all modules working correctly
xcad před 1 měsícem
rodič
revize
e64034c8f8

+ 0 - 4
cli/core/module/base_commands.py

@@ -220,9 +220,6 @@ def show_template(module_instance, id: str, var: list[str] | None = None, var_fi
         apply_var_file(template, var_file, module_instance.display)
         apply_var_file(template, var_file, module_instance.display)
         apply_cli_overrides(template, var)
         apply_cli_overrides(template, var)
 
 
-        # Re-sort sections after applying overrides (toggle values may have changed)
-        template.variables.sort_sections()
-
         # Reset disabled bool variables to False to prevent confusion
         # Reset disabled bool variables to False to prevent confusion
         reset_vars = template.variables.reset_disabled_bool_variables()
         reset_vars = template.variables.reset_disabled_bool_variables()
         if reset_vars:
         if reset_vars:
@@ -391,7 +388,6 @@ def _prepare_template(
     apply_cli_overrides(template, var)
     apply_cli_overrides(template, var)
 
 
     if template.variables:
     if template.variables:
-        template.variables.sort_sections()
         reset_vars = template.variables.reset_disabled_bool_variables()
         reset_vars = template.variables.reset_disabled_bool_variables()
         if reset_vars:
         if reset_vars:
             logger.debug(f"Reset {len(reset_vars)} disabled bool variables to False")
             logger.debug(f"Reset {len(reset_vars)} disabled bool variables to False")

+ 0 - 17
cli/core/schema/__init__.py

@@ -1,17 +0,0 @@
-"""Schema loading and management for boilerplate modules."""
-
-from .loader import (
-    SchemaLoader,
-    get_loader,
-    has_schema,
-    list_versions,
-    load_schema,
-)
-
-__all__ = [
-    "SchemaLoader",
-    "get_loader",
-    "has_schema",
-    "list_versions",
-    "load_schema",
-]

+ 0 - 15
cli/core/schema/ansible/v1.0.json

@@ -1,15 +0,0 @@
-[
-  {
-    "key": "general",
-    "title": "General",
-    "required": true,
-    "vars": [
-      {
-        "name": "target_hosts",
-        "description": "Target hosts",
-        "type": "str",
-        "required": true
-      }
-    ]
-  }
-]

+ 0 - 229
cli/core/schema/compose/v1.0.json

@@ -1,229 +0,0 @@
-[
-  {
-    "key": "general",
-    "title": "General",
-    "required": true,
-    "vars": [
-      {
-        "name": "service_name",
-        "description": "Service name",
-        "type": "str"
-      },
-      {
-        "name": "container_name",
-        "description": "Container name",
-        "type": "str"
-      },
-      {
-        "name": "container_timezone",
-        "description": "Container timezone (e.g., Europe/Berlin)",
-        "type": "str",
-        "default": "UTC"
-      },
-      {
-        "name": "user_uid",
-        "description": "User UID for container process",
-        "type": "int",
-        "default": 1000
-      },
-      {
-        "name": "user_gid",
-        "description": "User GID for container process",
-        "type": "int",
-        "default": 1000
-      },
-      {
-        "name": "restart_policy",
-        "description": "Container restart policy",
-        "type": "enum",
-        "options": ["unless-stopped", "always", "on-failure", "no"],
-        "default": "unless-stopped"
-      }
-    ]
-  },
-  {
-    "key": "network",
-    "title": "Network",
-    "toggle": "network_enabled",
-    "vars": [
-      {
-        "name": "network_enabled",
-        "description": "Enable custom network block",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "network_name",
-        "description": "Docker network name",
-        "type": "str",
-        "default": "bridge"
-      },
-      {
-        "name": "network_external",
-        "description": "Use existing Docker network",
-        "type": "bool",
-        "default": true
-      }
-    ]
-  },
-  {
-    "key": "ports",
-    "title": "Ports",
-    "toggle": "ports_enabled",
-    "vars": [
-      {
-        "name": "ports_enabled",
-        "description": "Expose ports via 'ports' mapping",
-        "type": "bool",
-        "default": true
-      }
-    ]
-  },
-  {
-    "key": "traefik",
-    "title": "Traefik",
-    "toggle": "traefik_enabled",
-    "description": "Traefik routes external traffic to your service.",
-    "vars": [
-      {
-        "name": "traefik_enabled",
-        "description": "Enable Traefik reverse proxy integration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "traefik_network",
-        "description": "Traefik network name",
-        "type": "str",
-        "default": "traefik"
-      },
-      {
-        "name": "traefik_host",
-        "description": "Domain name for your service (e.g., app.example.com)",
-        "type": "str"
-      },
-      {
-        "name": "traefik_entrypoint",
-        "description": "HTTP entrypoint (non-TLS)",
-        "type": "str",
-        "default": "web"
-      }
-    ]
-  },
-  {
-    "key": "traefik_tls",
-    "title": "Traefik TLS/SSL",
-    "toggle": "traefik_tls_enabled",
-    "needs": "traefik",
-    "description": "Enable HTTPS/TLS for Traefik with certificate management.",
-    "vars": [
-      {
-        "name": "traefik_tls_enabled",
-        "description": "Enable HTTPS/TLS",
-        "type": "bool",
-        "default": true
-      },
-      {
-        "name": "traefik_tls_entrypoint",
-        "description": "TLS entrypoint",
-        "type": "str",
-        "default": "websecure"
-      },
-      {
-        "name": "traefik_tls_certresolver",
-        "description": "Traefik certificate resolver name",
-        "type": "str",
-        "default": "cloudflare"
-      }
-    ]
-  },
-  {
-    "key": "swarm",
-    "title": "Docker Swarm",
-    "toggle": "swarm_enabled",
-    "description": "Deploy service in Docker Swarm mode with replicas.",
-    "vars": [
-      {
-        "name": "swarm_enabled",
-        "description": "Enable Docker Swarm mode",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "swarm_replicas",
-        "description": "Number of replicas in Swarm",
-        "type": "int",
-        "default": 1
-      },
-      {
-        "name": "swarm_placement_mode",
-        "description": "Swarm placement mode",
-        "type": "enum",
-        "options": ["global", "replicated"],
-        "default": "replicated"
-      },
-      {
-        "name": "swarm_placement_host",
-        "description": "Limit placement to specific node",
-        "type": "str"
-      }
-    ]
-  },
-  {
-    "key": "database",
-    "title": "Database",
-    "toggle": "database_enabled",
-    "description": "Connect to external database (PostgreSQL or MySQL)",
-    "vars": [
-      {
-        "name": "database_enabled",
-        "description": "Enable external database integration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "database_type",
-        "description": "Database type",
-        "type": "enum",
-        "options": ["postgres", "mysql"],
-        "default": "postgres"
-      },
-      {
-        "name": "database_external",
-        "description": "Use an external database server?",
-        "extra": "skips creation of internal database container",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "database_host",
-        "description": "Database host",
-        "type": "str",
-        "default": "database"
-      },
-      {
-        "name": "database_port",
-        "description": "Database port",
-        "type": "int"
-      },
-      {
-        "name": "database_name",
-        "description": "Database name",
-        "type": "str"
-      },
-      {
-        "name": "database_user",
-        "description": "Database user",
-        "type": "str"
-      },
-      {
-        "name": "database_password",
-        "description": "Database password",
-        "type": "str",
-        "default": "",
-        "sensitive": true,
-        "autogenerated": true
-      }
-    ]
-  }
-]

+ 0 - 312
cli/core/schema/compose/v1.1.json

@@ -1,312 +0,0 @@
-[
-  {
-    "key": "general",
-    "title": "General",
-    "required": true,
-    "vars": [
-      {
-        "name": "service_name",
-        "description": "Service name",
-        "type": "str"
-      },
-      {
-        "name": "container_name",
-        "description": "Container name",
-        "type": "str"
-      },
-      {
-        "name": "container_hostname",
-        "description": "Container internal hostname",
-        "type": "str"
-      },
-      {
-        "name": "container_timezone",
-        "description": "Container timezone (e.g., Europe/Berlin)",
-        "type": "str",
-        "default": "UTC"
-      },
-      {
-        "name": "user_uid",
-        "description": "User UID for container process",
-        "type": "int",
-        "default": 1000
-      },
-      {
-        "name": "user_gid",
-        "description": "User GID for container process",
-        "type": "int",
-        "default": 1000
-      },
-      {
-        "name": "container_loglevel",
-        "description": "Container log level",
-        "type": "enum",
-        "options": ["debug", "info", "warn", "error"],
-        "default": "info"
-      },
-      {
-        "name": "restart_policy",
-        "description": "Container restart policy",
-        "type": "enum",
-        "options": ["unless-stopped", "always", "on-failure", "no"],
-        "default": "unless-stopped"
-      }
-    ]
-  },
-  {
-    "key": "network",
-    "title": "Network",
-    "vars": [
-      {
-        "name": "network_mode",
-        "description": "Docker network mode",
-        "type": "enum",
-        "options": ["bridge", "host", "macvlan"],
-        "default": "bridge",
-        "extra": "bridge=default Docker networking, host=use host network stack, macvlan=dedicated MAC address on physical network"
-      },
-      {
-        "name": "network_name",
-        "description": "Docker network name",
-        "type": "str",
-        "default": "bridge",
-        "needs": "network_mode=bridge,macvlan"
-      },
-      {
-        "name": "network_external",
-        "description": "Use existing Docker network (external)",
-        "type": "bool",
-        "default": false,
-        "needs": "network_mode=bridge,macvlan"
-      },
-      {
-        "name": "network_macvlan_ipv4_address",
-        "description": "Static IP address for container",
-        "type": "str",
-        "default": "192.168.1.253",
-        "needs": "network_mode=macvlan"
-      },
-      {
-        "name": "network_macvlan_parent_interface",
-        "description": "Host network interface name",
-        "type": "str",
-        "default": "eth0",
-        "needs": "network_mode=macvlan"
-      },
-      {
-        "name": "network_macvlan_subnet",
-        "description": "Network subnet in CIDR notation",
-        "type": "str",
-        "default": "192.168.1.0/24",
-        "needs": "network_mode=macvlan"
-      },
-      {
-        "name": "network_macvlan_gateway",
-        "description": "Network gateway IP address",
-        "type": "str",
-        "default": "192.168.1.1",
-        "needs": "network_mode=macvlan"
-      }
-    ]
-  },
-  {
-    "key": "ports",
-    "title": "Ports",
-    "needs": "network_mode=bridge",
-    "vars": []
-  },
-  {
-    "key": "traefik",
-    "title": "Traefik",
-    "toggle": "traefik_enabled",
-    "needs": "network_mode=bridge",
-    "description": "Traefik routes external traffic to your service.",
-    "vars": [
-      {
-        "name": "traefik_enabled",
-        "description": "Enable Traefik reverse proxy integration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "traefik_network",
-        "description": "Traefik network name",
-        "type": "str",
-        "default": "traefik"
-      },
-      {
-        "name": "traefik_host",
-        "description": "Domain name for your service (e.g., app.example.com)",
-        "type": "str"
-      },
-      {
-        "name": "traefik_entrypoint",
-        "description": "HTTP entrypoint (non-TLS)",
-        "type": "str",
-        "default": "web"
-      }
-    ]
-  },
-  {
-    "key": "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": [
-      {
-        "name": "traefik_tls_enabled",
-        "description": "Enable HTTPS/TLS",
-        "type": "bool",
-        "default": true
-      },
-      {
-        "name": "traefik_tls_entrypoint",
-        "description": "TLS entrypoint",
-        "type": "str",
-        "default": "websecure"
-      },
-      {
-        "name": "traefik_tls_certresolver",
-        "description": "Traefik certificate resolver name",
-        "type": "str",
-        "default": "cloudflare"
-      }
-    ]
-  },
-  {
-    "key": "swarm",
-    "title": "Docker Swarm",
-    "toggle": "swarm_enabled",
-    "needs": "network_mode=bridge",
-    "description": "Deploy service in Docker Swarm mode.",
-    "vars": [
-      {
-        "name": "swarm_enabled",
-        "description": "Enable Docker Swarm mode",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "swarm_placement_mode",
-        "description": "Swarm placement mode",
-        "type": "enum",
-        "options": ["replicated", "global"],
-        "default": "replicated"
-      },
-      {
-        "name": "swarm_replicas",
-        "description": "Number of replicas",
-        "type": "int",
-        "default": 1,
-        "needs": "swarm_placement_mode=replicated"
-      },
-      {
-        "name": "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"
-      },
-      {
-        "name": "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!"
-      },
-      {
-        "name": "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"
-      },
-      {
-        "name": "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"
-      },
-      {
-        "name": "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"
-      },
-      {
-        "name": "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"
-      }
-    ]
-  },
-  {
-    "key": "database",
-    "title": "Database",
-    "toggle": "database_enabled",
-    "description": "Connect to external database (PostgreSQL or MySQL)",
-    "vars": [
-      {
-        "name": "database_enabled",
-        "description": "Enable external database integration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "database_type",
-        "description": "Database type",
-        "type": "enum",
-        "options": ["default", "sqlite", "postgres", "mysql"],
-        "default": "default"
-      },
-      {
-        "name": "database_external",
-        "description": "Use an external database server?",
-        "extra": "skips creation of internal database container",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "database_host",
-        "description": "Database host",
-        "type": "str",
-        "default": "database"
-      },
-      {
-        "name": "database_port",
-        "description": "Database port",
-        "type": "int"
-      },
-      {
-        "name": "database_name",
-        "description": "Database name",
-        "type": "str"
-      },
-      {
-        "name": "database_user",
-        "description": "Database user",
-        "type": "str"
-      },
-      {
-        "name": "database_password",
-        "description": "Database password",
-        "type": "str",
-        "default": "",
-        "sensitive": true,
-        "autogenerated": true
-      }
-    ]
-  }
-]

+ 0 - 528
cli/core/schema/compose/v1.2.json

@@ -1,528 +0,0 @@
-[
-  {
-    "key": "general",
-    "title": "General",
-    "vars": [
-      {
-        "name": "service_name",
-        "description": "Service name",
-        "type": "str",
-        "required": true
-      },
-      {
-        "name": "container_name",
-        "description": "Container name",
-        "type": "str"
-      },
-      {
-        "name": "container_hostname",
-        "description": "Container internal hostname",
-        "type": "str"
-      },
-      {
-        "name": "container_timezone",
-        "description": "Container timezone (e.g., Europe/Berlin)",
-        "type": "str"
-      },
-      {
-        "name": "user_uid",
-        "description": "User UID for container process",
-        "type": "int",
-        "default": 1000
-      },
-      {
-        "name": "user_gid",
-        "description": "User GID for container process",
-        "type": "int",
-        "default": 1000
-      },
-      {
-        "name": "container_loglevel",
-        "description": "Container log level",
-        "type": "enum",
-        "options": ["debug", "info", "warn", "error"]
-      },
-      {
-        "name": "restart_policy",
-        "description": "Container restart policy",
-        "type": "enum",
-        "options": ["unless-stopped", "always", "on-failure", "no"],
-        "default": "unless-stopped",
-        "required": true
-      }
-    ]
-  },
-  {
-    "key": "network",
-    "title": "Network",
-    "vars": [
-      {
-        "name": "network_mode",
-        "description": "Docker network mode",
-        "type": "enum",
-        "options": ["bridge", "host", "macvlan"],
-        "extra": "bridge=default Docker networking, host=use host network stack, macvlan=dedicated MAC address on physical network"
-      },
-      {
-        "name": "network_name",
-        "description": "Docker network name",
-        "type": "str",
-        "default": "bridge",
-        "needs": ["network_mode=bridge,macvlan"],
-        "required": true
-      },
-      {
-        "name": "network_external",
-        "description": "Use existing Docker network (external)",
-        "type": "bool",
-        "default": false,
-        "needs": ["network_mode=bridge,macvlan"]
-      },
-      {
-        "name": "network_macvlan_ipv4_address",
-        "description": "Static IP address for container",
-        "type": "str",
-        "default": "192.168.1.253",
-        "needs": ["network_mode=macvlan"],
-        "required": true
-      },
-      {
-        "name": "network_macvlan_parent_interface",
-        "description": "Host network interface name",
-        "type": "str",
-        "default": "eth0",
-        "needs": ["network_mode=macvlan"],
-        "required": true
-      },
-      {
-        "name": "network_macvlan_subnet",
-        "description": "Network subnet in CIDR notation",
-        "type": "str",
-        "default": "192.168.1.0/24",
-        "needs": ["network_mode=macvlan"],
-        "required": true
-      },
-      {
-        "name": "network_macvlan_gateway",
-        "description": "Network gateway IP address",
-        "type": "str",
-        "default": "192.168.1.1",
-        "needs": ["network_mode=macvlan"],
-        "required": true
-      }
-    ]
-  },
-  {
-    "key": "ports",
-    "title": "Ports",
-    "needs": ["network_mode!=host,macvlan"],
-    "description": "Expose service ports to the host.",
-    "vars": [
-      {
-        "name": "ports_http",
-        "description": "HTTP port on host",
-        "type": "int",
-        "needs": ["traefik_enabled=false"],
-        "default": 8080,
-        "required": true
-      },
-      {
-        "name": "ports_https",
-        "description": "HTTPS port on host",
-        "type": "int",
-        "needs": ["traefik_enabled=false"],
-        "default": 8443,
-        "required": true
-      },
-      {
-        "name": "ports_ssh",
-        "description": "SSH port on host",
-        "type": "int",
-        "default": 22,
-        "required": true
-      },
-      {
-        "name": "ports_dns",
-        "description": "DNS port on host",
-        "type": "int",
-        "default": 53,
-        "required": true
-      },
-      {
-        "name": "ports_dhcp",
-        "description": "DHCP port on host",
-        "type": "int",
-        "default": 67,
-        "required": true
-      },
-      {
-        "name": "ports_smtp",
-        "description": "SMTP port on host",
-        "type": "int",
-        "default": 25,
-        "required": true
-      },
-      {
-        "name": "ports_snmp",
-        "description": "SNMP trap port",
-        "type": "int",
-        "default": 162,
-        "required": true
-      }
-    ]
-  },
-  {
-    "key": "traefik",
-    "title": "Traefik",
-    "toggle": "traefik_enabled",
-    "needs": ["network_mode!=host,macvlan"],
-    "description": "Traefik routes external traffic to your service.",
-    "vars": [
-      {
-        "name": "traefik_enabled",
-        "description": "Enable Traefik reverse proxy integration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "traefik_network",
-        "description": "Traefik network name",
-        "type": "str",
-        "default": "traefik",
-        "required": true
-      },
-      {
-        "name": "traefik_host",
-        "description": "Service subdomain or full hostname (e.g., 'app' or 'app.example.com')",
-        "type": "str",
-        "required": true
-      },
-      {
-        "name": "traefik_domain",
-        "description": "Base domain (e.g., example.com)",
-        "type": "str",
-        "default": "home.arpa",
-        "required": true
-      }
-    ]
-  },
-  {
-    "key": "traefik_tls",
-    "title": "Traefik TLS/SSL",
-    "toggle": "traefik_tls_enabled",
-    "needs": ["traefik_enabled=true", "network_mode!=host,macvlan"],
-    "description": "Enable HTTPS/TLS for Traefik with certificate management.",
-    "vars": [
-      {
-        "name": "traefik_tls_enabled",
-        "description": "Enable HTTPS/TLS",
-        "type": "bool",
-        "default": true
-      },
-      {
-        "name": "traefik_tls_certresolver",
-        "description": "Traefik certificate resolver name",
-        "type": "str",
-        "default": "cloudflare",
-        "required": true
-      }
-    ]
-  },
-  {
-    "key": "volume",
-    "title": "Volume Storage",
-    "description": "Configure persistent storage for your service.",
-    "vars": [
-      {
-        "name": "volume_mode",
-        "description": "Volume storage backend",
-        "type": "enum",
-        "options": ["local", "mount", "nfs"],
-        "default": "local",
-        "required": true
-      },
-      {
-        "name": "volume_mount_path",
-        "description": "Host path for bind mounts",
-        "type": "str",
-        "default": "/mnt/storage",
-        "needs": ["volume_mode=mount"],
-        "required": true
-      },
-      {
-        "name": "volume_nfs_server",
-        "description": "NFS server address",
-        "type": "str",
-        "default": "192.168.1.1",
-        "needs": ["volume_mode=nfs"],
-        "required": true
-      },
-      {
-        "name": "volume_nfs_path",
-        "description": "NFS export path",
-        "type": "str",
-        "default": "/export",
-        "needs": ["volume_mode=nfs"],
-        "required": true
-      },
-      {
-        "name": "volume_nfs_options",
-        "description": "NFS mount options (comma-separated)",
-        "type": "str",
-        "default": "rw,nolock,soft",
-        "needs": ["volume_mode=nfs"],
-        "required": true
-      }
-    ]
-  },
-  {
-    "key": "resources",
-    "title": "Resource Limits",
-    "toggle": "resources_enabled",
-    "description": "Set CPU and memory limits for the service.",
-    "vars": [
-      {
-        "name": "resources_enabled",
-        "description": "Enable resource limits",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "resources_cpu_limit",
-        "description": "Maximum CPU cores (e.g., 0.5, 1.0, 2.0)",
-        "type": "str",
-        "default": "1.0",
-        "required": true
-      },
-      {
-        "name": "resources_cpu_reservation",
-        "description": "Reserved CPU cores",
-        "type": "str",
-        "default": "0.25",
-        "needs": ["swarm_enabled=true"],
-        "required": true
-      },
-      {
-        "name": "resources_memory_limit",
-        "description": "Maximum memory (e.g., 512M, 1G, 2G)",
-        "type": "str",
-        "default": "1G",
-        "required": true
-      },
-      {
-        "name": "resources_memory_reservation",
-        "description": "Reserved memory",
-        "type": "str",
-        "default": "512M",
-        "needs": ["swarm_enabled=true"],
-        "required": true
-      }
-    ]
-  },
-  {
-    "key": "swarm",
-    "title": "Docker Swarm",
-    "toggle": "swarm_enabled",
-    "needs": ["network_mode!=host,macvlan"],
-    "description": "Deploy service in Docker Swarm mode.",
-    "vars": [
-      {
-        "name": "swarm_enabled",
-        "description": "Enable Docker Swarm mode",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "swarm_placement_mode",
-        "description": "Swarm placement mode",
-        "type": "enum",
-        "options": ["replicated", "global"],
-        "default": "replicated",
-        "required": true
-      },
-      {
-        "name": "swarm_replicas",
-        "description": "Number of replicas",
-        "type": "int",
-        "default": 1,
-        "needs": ["swarm_placement_mode=replicated"],
-        "required": true
-      },
-      {
-        "name": "swarm_placement_host",
-        "description": "Target hostname for placement constraint",
-        "type": "str",
-        "default": "",
-        "needs": ["swarm_placement_mode=replicated"],
-        "extra": "Constrains service to run on specific node by hostname"
-      }
-    ]
-  },
-  {
-    "key": "database",
-    "title": "Database",
-    "toggle": "database_enabled",
-    "description": "Connect to external database (PostgreSQL or MySQL)",
-    "vars": [
-      {
-        "name": "database_enabled",
-        "description": "Enable external database integration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "database_type",
-        "description": "Database type",
-        "type": "enum",
-        "options": ["sqlite", "postgres", "mysql"],
-        "default": "sqlite",
-        "required": true
-      },
-      {
-        "name": "database_external",
-        "description": "Use an external database server?",
-        "extra": "skips creation of internal database container",
-        "type": "bool",
-        "needs": ["database_type=postgres,mysql"],
-        "default": false
-      },
-      {
-        "name": "database_host",
-        "description": "Database host",
-        "type": "str",
-        "needs": ["database_external=true;database_type=postgres,mysql"],
-        "required": true
-      },
-      {
-        "name": "database_port",
-        "description": "Database port",
-        "type": "int",
-        "needs": ["database_external=true;database_type=postgres,mysql"],
-        "required": true
-      },
-      {
-        "name": "database_name",
-        "description": "Database name",
-        "type": "str",
-        "needs": ["database_type=postgres,mysql"],
-        "required": true
-      },
-      {
-        "name": "database_user",
-        "description": "Database user",
-        "type": "str",
-        "needs": ["database_type=postgres,mysql"],
-        "required": true
-      },
-      {
-        "name": "database_password",
-        "description": "Database password",
-        "type": "str",
-        "needs": ["database_type=postgres,mysql"],
-        "sensitive": true,
-        "autogenerated": true,
-        "required": true
-      }
-    ]
-  },
-  {
-    "key": "email",
-    "title": "Email Server",
-    "toggle": "email_enabled",
-    "description": "Configure email server for notifications and user management.",
-    "vars": [
-      {
-        "name": "email_enabled",
-        "description": "Enable email server configuration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "email_host",
-        "description": "SMTP server hostname",
-        "type": "str",
-        "required": true
-      },
-      {
-        "name": "email_port",
-        "description": "SMTP server port",
-        "type": "int",
-        "default": 25,
-        "required": true
-      },
-      {
-        "name": "email_username",
-        "description": "SMTP username",
-        "type": "str",
-        "required": true
-      },
-      {
-        "name": "email_password",
-        "description": "SMTP password",
-        "type": "str",
-        "sensitive": true,
-        "required": true
-      },
-      {
-        "name": "email_from",
-        "description": "From email address",
-        "type": "str",
-        "required": true
-      },
-      {
-        "name": "email_encryption",
-        "description": "Email encryption method to use",
-        "type": "enum",
-        "options": ["none", "starttls", "ssl"]
-      }
-    ]
-  },
-  {
-    "key": "authentik",
-    "title": "Authentik SSO",
-    "toggle": "authentik_enabled",
-    "description": "Integrate with Authentik for Single Sign-On authentication.",
-    "vars": [
-      {
-        "name": "authentik_enabled",
-        "description": "Enable Authentik SSO integration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "authentik_url",
-        "description": "Authentik base URL (e.g., https://auth.example.com)",
-        "type": "url",
-        "required": true
-      },
-      {
-        "name": "authentik_slug",
-        "description": "Authentik application slug",
-        "type": "str",
-        "required": true
-      },
-      {
-        "name": "authentik_traefik_middleware",
-        "description": "Traefik middleware name for Authentik authentication",
-        "type": "str",
-        "default": "authentik-middleware@file",
-        "needs": ["traefik_enabled=true"],
-        "required": true
-      },
-      {
-        "name": "authentik_client_id",
-        "description": "Authentik OAuth2 client ID",
-        "type": "str",
-        "sensitive": true,
-        "required": true
-      },
-      {
-        "name": "authentik_client_secret",
-        "description": "Authentik OAuth2 client secret",
-        "type": "str",
-        "sensitive": true,
-        "required": true
-      }
-    ]
-  }
-]

+ 0 - 202
cli/core/schema/helm/v1.0.json

@@ -1,202 +0,0 @@
-[
-  {
-    "key": "general",
-    "title": "General",
-    "required": true,
-    "vars": [
-      {
-        "name": "release_name",
-        "description": "Helm release name",
-        "type": "str",
-        "required": true
-      },
-      {
-        "name": "namespace",
-        "description": "Kubernetes namespace",
-        "type": "str"
-      }
-    ]
-  },
-  {
-    "key": "networking",
-    "title": "Networking",
-    "vars": [
-      {
-        "name": "network_mode",
-        "description": "Kubernetes service type",
-        "type": "enum",
-        "options": ["ClusterIP", "NodePort", "LoadBalancer"],
-        "default": "ClusterIP"
-      }
-    ]
-  },
-  {
-    "key": "database",
-    "title": "Database Configuration",
-    "toggle": "database_enabled",
-    "vars": [
-      {
-        "name": "database_enabled",
-        "description": "Enable external database configuration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "database_type",
-        "description": "Database type",
-        "type": "enum",
-        "options": ["postgres", "mysql", "mariadb"],
-        "default": "postgres"
-      },
-      {
-        "name": "database_host",
-        "description": "Database hostname",
-        "type": "hostname"
-      },
-      {
-        "name": "database_port",
-        "description": "Database port",
-        "type": "int",
-        "default": 5432
-      },
-      {
-        "name": "database_name",
-        "description": "Database name",
-        "type": "str"
-      },
-      {
-        "name": "database_user",
-        "description": "Database username",
-        "type": "str"
-      },
-      {
-        "name": "database_password",
-        "description": "Database password",
-        "type": "str",
-        "sensitive": true
-      }
-    ]
-  },
-  {
-    "key": "email",
-    "title": "Email Configuration",
-    "toggle": "email_enabled",
-    "vars": [
-      {
-        "name": "email_enabled",
-        "description": "Enable email configuration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "email_host",
-        "description": "SMTP server hostname",
-        "type": "hostname"
-      },
-      {
-        "name": "email_port",
-        "description": "SMTP server port",
-        "type": "int",
-        "default": 587
-      },
-      {
-        "name": "email_username",
-        "description": "SMTP username",
-        "type": "str"
-      },
-      {
-        "name": "email_password",
-        "description": "SMTP password",
-        "type": "str",
-        "sensitive": true
-      },
-      {
-        "name": "email_from",
-        "description": "From email address",
-        "type": "email"
-      },
-      {
-        "name": "email_use_tls",
-        "description": "Use TLS encryption",
-        "type": "bool",
-        "default": true
-      },
-      {
-        "name": "email_use_ssl",
-        "description": "Use SSL encryption",
-        "type": "bool",
-        "default": false
-      }
-    ]
-  },
-  {
-    "key": "traefik",
-    "title": "Traefik Ingress",
-    "toggle": "traefik_enabled",
-    "vars": [
-      {
-        "name": "traefik_enabled",
-        "description": "Enable Traefik ingress",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "traefik_host",
-        "description": "Ingress hostname (FQDN)",
-        "type": "hostname"
-      }
-    ]
-  },
-  {
-    "key": "traefik_tls",
-    "title": "Traefik TLS/SSL",
-    "needs": "traefik",
-    "toggle": "traefik_tls_enabled",
-    "vars": [
-      {
-        "name": "traefik_tls_enabled",
-        "description": "Enable TLS for ingress",
-        "type": "bool",
-        "default": true
-      },
-      {
-        "name": "traefik_tls_certmanager",
-        "description": "Use cert-manager for TLS certificates",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "certmanager_issuer",
-        "description": "Cert-manager cluster issuer name",
-        "type": "str",
-        "needs": "traefik_tls_certmanager=true",
-        "default": "letsencrypt-prod"
-      },
-      {
-        "name": "traefik_tls_secret",
-        "description": "TLS secret name",
-        "type": "str"
-      }
-    ]
-  },
-  {
-    "key": "volumes",
-    "title": "Persistent Volumes",
-    "vars": [
-      {
-        "name": "volumes_mode",
-        "description": "Volume configuration mode",
-        "type": "enum",
-        "options": ["dynamic-pvc", "existing-pvc"],
-        "default": "dynamic-pvc",
-        "extra": "dynamic-pvc=auto-provision storage, existing-pvc=use existing PVC"
-      },
-      {
-        "name": "volumes_pvc_name",
-        "description": "Existing PVC name",
-        "type": "str",
-        "needs": "volumes_mode=existing-pvc"
-      }
-    ]
-  }
-]

+ 0 - 247
cli/core/schema/kubernetes/v1.0.json

@@ -1,247 +0,0 @@
-[
-  {
-    "key": "general",
-    "title": "General",
-    "required": true,
-    "vars": [
-      {
-        "name": "resource_name",
-        "description": "Kubernetes resource name",
-        "type": "str",
-        "required": true
-      },
-      {
-        "name": "namespace",
-        "description": "Kubernetes namespace",
-        "type": "str",
-        "default": "default",
-        "required": true
-      }
-    ]
-  },
-  {
-    "key": "resources",
-    "title": "Resource Limits",
-    "toggle": "resources_enabled",
-    "description": "Set CPU and memory limits for the resource.",
-    "vars": [
-      {
-        "name": "resources_enabled",
-        "description": "Enable resource limits",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "resources_cpu_limit",
-        "description": "Maximum CPU cores (e.g., 100m, 500m, 1, 2)",
-        "type": "str",
-        "default": "1",
-        "required": true
-      },
-      {
-        "name": "resources_cpu_request",
-        "description": "Requested CPU cores",
-        "type": "str",
-        "default": "250m",
-        "required": true
-      },
-      {
-        "name": "resources_memory_limit",
-        "description": "Maximum memory (e.g., 512Mi, 1Gi, 2Gi)",
-        "type": "str",
-        "default": "1Gi",
-        "required": true
-      },
-      {
-        "name": "resources_memory_request",
-        "description": "Requested memory",
-        "type": "str",
-        "default": "512Mi",
-        "required": true
-      }
-    ]
-  },
-  {
-    "key": "traefik",
-    "title": "Traefik",
-    "toggle": "traefik_enabled",
-    "description": "Traefik routes external traffic to your service.",
-    "vars": [
-      {
-        "name": "traefik_enabled",
-        "description": "Enable Traefik ingress configuration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "traefik_host",
-        "description": "Service subdomain or full hostname (e.g., 'app' or 'app.example.com')",
-        "type": "str",
-        "required": true
-      },
-      {
-        "name": "traefik_domain",
-        "description": "Base domain (e.g., example.com)",
-        "type": "str",
-        "default": "home.arpa",
-        "required": true
-      }
-    ]
-  },
-  {
-    "key": "traefik_tls",
-    "title": "Traefik TLS/SSL",
-    "toggle": "traefik_tls_enabled",
-    "needs": ["traefik"],
-    "description": "Enable HTTPS/TLS for Traefik with certificate management.",
-    "vars": [
-      {
-        "name": "traefik_tls_enabled",
-        "description": "Enable HTTPS/TLS",
-        "type": "bool",
-        "default": true
-      },
-      {
-        "name": "traefik_tls_certresolver",
-        "description": "Traefik certificate resolver name",
-        "type": "str",
-        "default": "cloudflare",
-        "required": true
-      }
-    ]
-  },
-  {
-    "key": "database",
-    "title": "Database",
-    "toggle": "database_enabled",
-    "description": "Connect to external database (PostgreSQL or MySQL)",
-    "vars": [
-      {
-        "name": "database_enabled",
-        "description": "Enable external database integration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "database_type",
-        "description": "Database type",
-        "type": "enum",
-        "options": ["sqlite", "postgres", "mysql", "mariadb"],
-        "default": "postgres",
-        "required": true
-      },
-      {
-        "name": "database_host",
-        "description": "Database host",
-        "type": "str",
-        "default": "database",
-        "required": true
-      },
-      {
-        "name": "database_port",
-        "description": "Database port",
-        "type": "int",
-        "required": true
-      },
-      {
-        "name": "database_name",
-        "description": "Database name",
-        "type": "str",
-        "required": true
-      },
-      {
-        "name": "database_user",
-        "description": "Database user",
-        "type": "str",
-        "required": true
-      },
-      {
-        "name": "database_password",
-        "description": "Database password",
-        "type": "str",
-        "default": "",
-        "sensitive": true,
-        "autogenerated": true,
-        "required": true
-      }
-    ]
-  },
-  {
-    "key": "email",
-    "title": "Email Server",
-    "toggle": "email_enabled",
-    "description": "Configure email server for notifications and user management.",
-    "vars": [
-      {
-        "name": "email_enabled",
-        "description": "Enable email server configuration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "email_host",
-        "description": "SMTP server hostname",
-        "type": "str",
-        "required": true
-      },
-      {
-        "name": "email_port",
-        "description": "SMTP server port",
-        "type": "int",
-        "default": 25,
-        "required": true
-      },
-      {
-        "name": "email_username",
-        "description": "SMTP username",
-        "type": "str",
-        "required": true
-      },
-      {
-        "name": "email_password",
-        "description": "SMTP password",
-        "type": "str",
-        "sensitive": true,
-        "required": true
-      },
-      {
-        "name": "email_from",
-        "description": "From email address",
-        "type": "str",
-        "required": true
-      },
-      {
-        "name": "email_encryption",
-        "description": "Email encryption method to use",
-        "type": "enum",
-        "options": ["none", "starttls", "ssl"]
-      }
-    ]
-  },
-  {
-    "key": "authentik",
-    "title": "Authentik SSO",
-    "toggle": "authentik_enabled",
-    "description": "Integrate with Authentik for Single Sign-On authentication.",
-    "vars": [
-      {
-        "name": "authentik_enabled",
-        "description": "Enable Authentik SSO integration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "authentik_url",
-        "description": "Authentik base URL (e.g., https://auth.example.com)",
-        "type": "url",
-        "required": true
-      },
-      {
-        "name": "authentik_slug",
-        "description": "Authentik application slug",
-        "type": "str",
-        "required": true
-      }
-    ]
-  }
-]

+ 0 - 220
cli/core/schema/loader.py

@@ -1,220 +0,0 @@
-"""JSON Schema Loading and Validation.
-
-This module provides functionality to load, cache, and validate JSON schemas
-for boilerplate modules. Schemas are stored in cli/core/schema/<module>/v*.json files.
-"""
-
-import json
-from pathlib import Path
-from typing import Any
-
-from cli.core.exceptions import SchemaError
-
-
-class SchemaLoader:
-    """Loads and validates JSON schemas for modules."""
-
-    def __init__(self, schema_dir: Path | None = None):
-        """Initialize schema loader.
-
-        Args:
-            schema_dir: Directory containing schema files. If None, uses cli/core/schema/
-        """
-        if schema_dir is None:
-            # Use path relative to this file (in cli/core/schema/)
-            # __file__ is cli/core/schema/loader.py, parent is cli/core/schema/
-            self.schema_dir = Path(__file__).parent
-        else:
-            self.schema_dir = schema_dir
-
-    def load_schema(self, module: str, version: str) -> list[dict[str, Any]]:
-        """Load a JSON schema from file.
-
-        Args:
-            module: Module name (e.g., 'compose', 'ansible')
-            version: Schema version (e.g., '1.0', '1.2')
-
-        Returns:
-            Schema as list of section specifications
-
-        Raises:
-            SchemaError: If schema file not found or invalid JSON
-        """
-        schema_file = self.schema_dir / module / f"v{version}.json"
-
-        if not schema_file.exists():
-            raise SchemaError(
-                f"Schema file not found: {schema_file}",
-                details=f"Module: {module}, Version: {version}",
-            )
-
-        try:
-            with schema_file.open(encoding="utf-8") as f:
-                schema = json.load(f)
-        except json.JSONDecodeError as e:
-            raise SchemaError(
-                f"Invalid JSON in schema file: {schema_file}",
-                details=f"Error: {e}",
-            ) from e
-        except Exception as e:
-            raise SchemaError(
-                f"Failed to read schema file: {schema_file}",
-                details=f"Error: {e}",
-            ) from e
-
-        # Validate schema structure
-        self._validate_schema_structure(schema, module, version)
-
-        return schema
-
-    def _validate_schema_structure(self, schema: Any, module: str, version: str) -> None:
-        """Validate that schema has correct structure.
-
-        Args:
-            schema: Schema to validate
-            module: Module name for error messages
-            version: Version for error messages
-
-        Raises:
-            SchemaError: If schema structure is invalid
-        """
-        if not isinstance(schema, list):
-            raise SchemaError(
-                f"Schema must be a list, got {type(schema).__name__}",
-                details=f"Module: {module}, Version: {version}",
-            )
-
-        for idx, section in enumerate(schema):
-            if not isinstance(section, dict):
-                raise SchemaError(
-                    f"Section {idx} must be a dict, got {type(section).__name__}",
-                    details=f"Module: {module}, Version: {version}",
-                )
-
-            # Check required fields
-            if "key" not in section:
-                raise SchemaError(
-                    f"Section {idx} missing required field 'key'",
-                    details=f"Module: {module}, Version: {version}",
-                )
-
-            if "vars" not in section:
-                raise SchemaError(
-                    f"Section '{section.get('key')}' missing required field 'vars'",
-                    details=f"Module: {module}, Version: {version}",
-                )
-
-            if not isinstance(section["vars"], list):
-                raise SchemaError(
-                    f"Section '{section['key']}' vars must be a list",
-                    details=f"Module: {module}, Version: {version}",
-                )
-
-            # Validate variables
-            for var_idx, var in enumerate(section["vars"]):
-                if not isinstance(var, dict):
-                    raise SchemaError(
-                        f"Variable {var_idx} in section '{section['key']}' must be a dict",
-                        details=f"Module: {module}, Version: {version}",
-                    )
-
-                if "name" not in var:
-                    raise SchemaError(
-                        f"Variable {var_idx} in section '{section['key']}' missing 'name'",
-                        details=f"Module: {module}, Version: {version}",
-                    )
-
-                if "type" not in var:
-                    raise SchemaError(
-                        f"Variable '{var.get('name')}' in section '{section['key']}' missing 'type'",
-                        details=f"Module: {module}, Version: {version}",
-                    )
-
-    def list_versions(self, module: str) -> list[str]:
-        """List available schema versions for a module.
-
-        Args:
-            module: Module name
-
-        Returns:
-            List of version strings (e.g., ['1.0', '1.1', '1.2'])
-        """
-        module_dir = self.schema_dir / module
-
-        if not module_dir.exists():
-            return []
-
-        versions = []
-        for file in module_dir.glob("v*.json"):
-            # Extract version from filename (v1.0.json -> 1.0)
-            version = file.stem[1:]  # Remove 'v' prefix
-            versions.append(version)
-
-        return sorted(versions)
-
-    def has_schema(self, module: str, version: str) -> bool:
-        """Check if a schema exists.
-
-        Args:
-            module: Module name
-            version: Schema version
-
-        Returns:
-            True if schema exists
-        """
-        schema_file = self.schema_dir / module / f"v{version}.json"
-        return schema_file.exists()
-
-
-# Global schema loader instance
-_loader: SchemaLoader | None = None
-
-
-def get_loader() -> SchemaLoader:
-    """Get global schema loader instance.
-
-    Returns:
-        SchemaLoader instance
-    """
-    global _loader  # noqa: PLW0603
-    if _loader is None:
-        _loader = SchemaLoader()
-    return _loader
-
-
-def load_schema(module: str, version: str) -> list[dict[str, Any]]:
-    """Load a schema using the global loader.
-
-    Args:
-        module: Module name
-        version: Schema version
-
-    Returns:
-        Schema as list of section specifications
-    """
-    return get_loader().load_schema(module, version)
-
-
-def list_versions(module: str) -> list[str]:
-    """List available versions for a module.
-
-    Args:
-        module: Module name
-
-    Returns:
-        List of version strings
-    """
-    return get_loader().list_versions(module)
-
-
-def has_schema(module: str, version: str) -> bool:
-    """Check if a schema exists.
-
-    Args:
-        module: Module name
-        version: Schema version
-
-    Returns:
-        True if schema exists
-    """
-    return get_loader().has_schema(module, version)

+ 0 - 14
cli/core/schema/packer/v1.0.json

@@ -1,14 +0,0 @@
-[
-  {
-    "key": "general",
-    "title": "General",
-    "required": true,
-    "vars": [
-      {
-        "name": "playbook_name",
-        "description": "Ansible playbook name",
-        "type": "str"
-      }
-    ]
-  }
-]

+ 0 - 87
cli/core/schema/terraform/v1.0.json

@@ -1,87 +0,0 @@
-[
-  {
-    "key": "general",
-    "title": "General",
-    "required": true,
-    "vars": [
-      {
-        "name": "resource_name",
-        "description": "Terraform resource name (alphanumeric and underscores only)",
-        "type": "str",
-        "default": "resource"
-      }
-    ]
-  },
-  {
-    "key": "depends_on",
-    "title": "Dependencies",
-    "toggle": "depends_on_enabled",
-    "required": false,
-    "vars": [
-      {
-        "name": "depends_on_enabled",
-        "description": "Enable resource dependencies",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "dependencies",
-        "description": "Comma-separated list of resource dependencies",
-        "type": "str",
-        "default": ""
-      }
-    ]
-  },
-  {
-    "key": "lifecycle",
-    "title": "Lifecycle",
-    "toggle": "lifecycle_enabled",
-    "required": false,
-    "vars": [
-      {
-        "name": "lifecycle_enabled",
-        "description": "Enable lifecycle rules",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "prevent_destroy",
-        "description": "Prevent resource destruction",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "create_before_destroy",
-        "description": "Create replacement before destroying",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "ignore_changes",
-        "description": "Comma-separated list of attributes to ignore changes for",
-        "type": "str",
-        "default": ""
-      }
-    ]
-  },
-  {
-    "key": "tags",
-    "title": "Tags",
-    "toggle": "tags_enabled",
-    "required": false,
-    "vars": [
-      {
-        "name": "tags_enabled",
-        "description": "Enable resource tags",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "tags_json",
-        "description": "Resource tags in JSON format (e.g., {\"Environment\": \"Production\"})",
-        "type": "str",
-        "default": "{}"
-      }
-    ]
-  }
-]

+ 22 - 151
cli/core/template/template.py

@@ -1,14 +1,11 @@
 from __future__ import annotations
 from __future__ import annotations
 
 
-import base64
-import importlib
 import logging
 import logging
 import os
 import os
 import re
 import re
 import secrets
 import secrets
 import string
 import string
 from dataclasses import dataclass, field
 from dataclasses import dataclass, field
-from functools import lru_cache
 from pathlib import Path
 from pathlib import Path
 from typing import Any, Literal
 from typing import Any, Literal
 
 
@@ -29,7 +26,6 @@ from jinja2.exceptions import (
 from jinja2.sandbox import SandboxedEnvironment
 from jinja2.sandbox import SandboxedEnvironment
 
 
 from ..exceptions import (
 from ..exceptions import (
-    IncompatibleSchemaVersionError,
     RenderErrorContext,
     RenderErrorContext,
     TemplateLoadError,
     TemplateLoadError,
     TemplateRenderError,
     TemplateRenderError,
@@ -37,7 +33,6 @@ from ..exceptions import (
     TemplateValidationError,
     TemplateValidationError,
     YAMLParseError,
     YAMLParseError,
 )
 )
-from ..version import is_compatible
 from .variable_collection import VariableCollection
 from .variable_collection import VariableCollection
 
 
 logger = logging.getLogger(__name__)
 logger = logging.getLogger(__name__)
@@ -319,13 +314,10 @@ class Template:
         self.library_type = library_type
         self.library_type = library_type
 
 
         # Initialize caches for lazy loading
         # Initialize caches for lazy loading
-        self.__module_specs: dict | None = None
-        self.__merged_specs: dict | None = None
         self.__jinja_env: Environment | None = None
         self.__jinja_env: Environment | None = None
         self.__used_variables: set[str] | None = None
         self.__used_variables: set[str] | None = None
         self.__variables: VariableCollection | None = None
         self.__variables: VariableCollection | None = None
         self.__template_files: list[TemplateFile] | None = None  # New attribute
         self.__template_files: list[TemplateFile] | None = None  # New attribute
-        self._schema_deprecation_warned: bool = False  # Track if deprecation warning shown
 
 
         try:
         try:
             # Find and parse the main template file (template.yaml or template.yml)
             # Find and parse the main template file (template.yaml or template.yml)
@@ -356,14 +348,6 @@ class Template:
             # Validate 'kind' field (always needed)
             # Validate 'kind' field (always needed)
             self._validate_kind(self._template_data)
             self._validate_kind(self._template_data)
 
 
-            # DEPRECATION (v0.1.3): Schema property is ignored for backwards compatibility
-            # Templates are now self-contained and never use schemas
-            # The schema property may still exist in template.yaml for older client compatibility
-            self.schema_version = None
-            logger.debug("Template is self-contained (schemas are no longer used)")
-
-            # Note: Schema loading and validation removed in v0.1.3
-
             # NOTE: File collection is now lazy-loaded via the template_files property
             # NOTE: File collection is now lazy-loaded via the template_files property
             # This significantly improves performance when listing many templates
             # This significantly improves performance when listing many templates
 
 
@@ -397,81 +381,24 @@ class Template:
                 return path
                 return path
         raise FileNotFoundError(f"Main template file (template.yaml or template.yml) not found in {self.template_dir}")
         raise FileNotFoundError(f"Main template file (template.yaml or template.yml) not found in {self.template_dir}")
 
 
-    @staticmethod
-    @lru_cache(maxsize=32)
-    def _load_module_specs_for_schema(kind: str, schema_version: str) -> dict:
-        """Load specifications from the corresponding module for a specific schema version.
-
-        DEPRECATION NOTICE (v0.1.3): Module schemas are being deprecated. Templates should define
-        all variables in their template.yaml spec section. In future versions, this method will
-        return an empty dict and templates will need to be self-contained.
-
-        Uses LRU cache to avoid re-loading the same module spec multiple times.
-        This significantly improves performance when listing many templates of the same kind.
-
-        Args:
-            kind: The module kind (e.g., 'compose', 'terraform')
-            schema_version: The schema version to load (e.g., '1.0', '1.1')
-
-        Returns:
-            Dictionary containing the module's spec for the requested schema version,
-            or empty dict if kind is empty
-
-        Raises:
-            ValueError: If module cannot be loaded or spec is invalid
+    def _merge_specs(self) -> dict:
+        """Process template specs into merged format.
+        
+        Since schemas are no longer used, this just uses the template specs directly
+        and warns about unused variables.
         """
         """
-        if not kind:
+        if not self.template_specs:
             return {}
             return {}
-
-        # Log cache statistics for performance monitoring
-        cache_info = Template._load_module_specs_for_schema.cache_info()
-        logger.debug(
-            f"Loading module spec: kind='{kind}', schema={schema_version} "
-            f"(cache: hits={cache_info.hits}, misses={cache_info.misses}, size={cache_info.currsize})"
-        )
-
-        try:
-            module = importlib.import_module(f"cli.modules.{kind}")
-
-            # Check if module has schema-specific specs (multi-schema support)
-            # Try SCHEMAS constant first (uppercase), then schemas attribute
-            schemas = getattr(module, "SCHEMAS", None) or getattr(module, "schemas", None)
-            if schemas and schema_version in schemas:
-                spec = schemas[schema_version]
-                logger.debug(f"Loaded and cached module spec for kind '{kind}' schema {schema_version}")
-            else:
-                # Fallback to default spec if schema mapping not available
-                spec = getattr(module, "spec", {})
-                logger.debug(f"Loaded and cached module spec for kind '{kind}' (default/no schema mapping)")
-
-            return spec
-        except Exception as e:
-            raise ValueError(f"Error loading module specifications for kind '{kind}': {e}") from e
-
-    def _merge_specs(self, module_specs: dict, template_specs: dict) -> dict:
-        """Deep merge template specs with module specs using VariableCollection.
-
-        Uses VariableCollection's native merge() method for consistent merging logic.
-        Module specs are base, template specs override with origin tracking.
-        """
-        # Create VariableCollection from module specs (base)
-        module_collection = VariableCollection(module_specs) if module_specs else VariableCollection({})
-
-        # Set origin for module variables
-        for section in module_collection.get_sections().values():
-            for variable in section.variables.values():
-                if not variable.origin:
-                    variable.origin = "module"
-
-        # Merge template specs into module specs (template overrides)
-        if template_specs:
-            merged_collection = module_collection.merge(template_specs, origin="template")
-        else:
-            merged_collection = module_collection
-
+        
+        # Warn about unused variables in spec
+        self._warn_about_unused_variables(self.template_specs)
+        
+        # Create VariableCollection from template specs
+        collection = VariableCollection(self.template_specs)
+        
         # Convert back to dict format
         # Convert back to dict format
         merged_spec = {}
         merged_spec = {}
-        for section_key, section in merged_collection.get_sections().items():
+        for section_key, section in collection.get_sections().items():
             merged_spec[section_key] = section.to_dict()
             merged_spec[section_key] = section.to_dict()
 
 
         return merged_spec
         return merged_spec
@@ -580,8 +507,6 @@ class Template:
     def _filter_specs_to_used(
     def _filter_specs_to_used(
         self,
         self,
         used_variables: set,
         used_variables: set,
-        merged_specs: dict,
-        _module_specs: dict,
         template_specs: dict,
         template_specs: dict,
     ) -> dict:
     ) -> dict:
         """Filter specs to only include variables used in templates using VariableCollection.
         """Filter specs to only include variables used in templates using VariableCollection.
@@ -595,15 +520,15 @@ class Template:
             if isinstance(section_data, dict) and "vars" in section_data:
             if isinstance(section_data, dict) and "vars" in section_data:
                 template_defined_vars.update(section_data["vars"].keys())
                 template_defined_vars.update(section_data["vars"].keys())
 
 
-        # Create VariableCollection from merged specs
-        merged_collection = VariableCollection(merged_specs)
+        # Create VariableCollection from template specs
+        template_collection = VariableCollection(template_specs)
 
 
         # Filter to only used variables (and sensitive ones that are template-defined)
         # Filter to only used variables (and sensitive ones that are template-defined)
         # We keep sensitive variables that are either:
         # We keep sensitive variables that are either:
         # 1. Actually used in template files, OR
         # 1. Actually used in template files, OR
         # 2. Explicitly defined in the template spec (even if not yet used)
         # 2. Explicitly defined in the template spec (even if not yet used)
         variables_to_keep = used_variables | template_defined_vars
         variables_to_keep = used_variables | template_defined_vars
-        filtered_collection = merged_collection.filter_to_used(variables_to_keep, keep_sensitive=False)
+        filtered_collection = template_collection.filter_to_used(variables_to_keep, keep_sensitive=False)
 
 
         # Convert back to dict format
         # Convert back to dict format
         filtered_specs = {}
         filtered_specs = {}
@@ -612,43 +537,6 @@ class Template:
 
 
         return filtered_specs
         return filtered_specs
 
 
-    def _validate_schema_version(self, module_schema: str, module_name: str) -> None:
-        """Validate that template schema version is supported by the module.
-
-        Self-contained templates (with schema=None) don't require validation.
-
-        Args:
-            module_schema: Schema version supported by the module
-            module_name: Name of the module (for error messages)
-
-        Raises:
-            IncompatibleSchemaVersionError: If template schema > module schema
-        """
-        template_schema = self.schema_version
-
-        # Self-contained templates (no schema property) don't need validation
-        if template_schema is None:
-            logger.debug(f"Template '{self.id}' is self-contained (no schema inheritance)")
-            return
-
-        # Compare schema versions
-        if not is_compatible(module_schema, template_schema):
-            logger.error(
-                f"Template '{self.id}' uses schema version {template_schema}, "
-                f"but module '{module_name}' only supports up to {module_schema}"
-            )
-            raise IncompatibleSchemaVersionError(
-                template_id=self.id,
-                template_schema=template_schema,
-                module_schema=module_schema,
-                module_name=module_name,
-            )
-
-        logger.debug(
-            f"Template '{self.id}' schema version compatible: "
-            f"template uses {template_schema}, module supports {module_schema}"
-        )
-
     @staticmethod
     @staticmethod
     def _validate_kind(template_data: dict) -> None:
     def _validate_kind(template_data: dict) -> None:
         """Validate that template has required 'kind' field.
         """Validate that template has required 'kind' field.
@@ -915,23 +803,6 @@ class Template:
         """Get the spec section from template YAML data."""
         """Get the spec section from template YAML data."""
         return self._template_data.get("spec", {})
         return self._template_data.get("spec", {})
 
 
-    @property
-    def module_specs(self) -> dict:
-        """Get the spec from the module (always empty in v0.1.3+).
-        
-        Schemas are no longer used. All templates are self-contained.
-        This property returns empty dict for backwards compatibility.
-        """
-        if self.__module_specs is None:
-            self.__module_specs = {}
-    @property
-    def merged_specs(self) -> dict:
-        if self.__merged_specs is None:
-            # Warn about unused variables in spec
-            self._warn_about_unused_variables(self.template_specs)
-            self.__merged_specs = self._merge_specs(self.module_specs, self.template_specs)
-        return self.__merged_specs
-
     @property
     @property
     def jinja_env(self) -> Environment:
     def jinja_env(self) -> Environment:
         if self.__jinja_env is None:
         if self.__jinja_env is None:
@@ -947,19 +818,19 @@ class Template:
     @property
     @property
     def variables(self) -> VariableCollection:
     def variables(self) -> VariableCollection:
         if self.__variables is None:
         if self.__variables is None:
+            # Process template specs (merge and warn about unused variables)
+            merged_specs = self._merge_specs()
+            
             # Validate that all used variables are defined
             # Validate that all used variables are defined
-            self._validate_variable_definitions(self.used_variables, self.merged_specs)
+            self._validate_variable_definitions(self.used_variables, merged_specs)
+            
             # Filter specs to only used variables
             # Filter specs to only used variables
             filtered_specs = self._filter_specs_to_used(
             filtered_specs = self._filter_specs_to_used(
                 self.used_variables,
                 self.used_variables,
-                self.merged_specs,
-                self.module_specs,
                 self.template_specs,
                 self.template_specs,
             )
             )
 
 
             self.__variables = VariableCollection(filtered_specs)
             self.__variables = VariableCollection(filtered_specs)
-            # Sort sections: required first, then enabled, then disabled
-            self.__variables.sort_sections()
         return self.__variables
         return self.__variables
 
 
     @property
     @property

+ 0 - 14
library/schemas/ansible/v1.0.json

@@ -1,14 +0,0 @@
-[
-  {
-    "key": "general",
-    "title": "General",
-    "required": true,
-    "vars": [
-      {
-        "name": "playbook_name",
-        "description": "Ansible playbook name",
-        "type": "str"
-      }
-    ]
-  }
-]

+ 0 - 229
library/schemas/compose/v1.0.json

@@ -1,229 +0,0 @@
-[
-  {
-    "key": "general",
-    "title": "General",
-    "required": true,
-    "vars": [
-      {
-        "name": "service_name",
-        "description": "Service name",
-        "type": "str"
-      },
-      {
-        "name": "container_name",
-        "description": "Container name",
-        "type": "str"
-      },
-      {
-        "name": "container_timezone",
-        "description": "Container timezone (e.g., Europe/Berlin)",
-        "type": "str",
-        "default": "UTC"
-      },
-      {
-        "name": "user_uid",
-        "description": "User UID for container process",
-        "type": "int",
-        "default": 1000
-      },
-      {
-        "name": "user_gid",
-        "description": "User GID for container process",
-        "type": "int",
-        "default": 1000
-      },
-      {
-        "name": "restart_policy",
-        "description": "Container restart policy",
-        "type": "enum",
-        "options": ["unless-stopped", "always", "on-failure", "no"],
-        "default": "unless-stopped"
-      }
-    ]
-  },
-  {
-    "key": "network",
-    "title": "Network",
-    "toggle": "network_enabled",
-    "vars": [
-      {
-        "name": "network_enabled",
-        "description": "Enable custom network block",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "network_name",
-        "description": "Docker network name",
-        "type": "str",
-        "default": "bridge"
-      },
-      {
-        "name": "network_external",
-        "description": "Use existing Docker network",
-        "type": "bool",
-        "default": true
-      }
-    ]
-  },
-  {
-    "key": "ports",
-    "title": "Ports",
-    "toggle": "ports_enabled",
-    "vars": [
-      {
-        "name": "ports_enabled",
-        "description": "Expose ports via 'ports' mapping",
-        "type": "bool",
-        "default": true
-      }
-    ]
-  },
-  {
-    "key": "traefik",
-    "title": "Traefik",
-    "toggle": "traefik_enabled",
-    "description": "Traefik routes external traffic to your service.",
-    "vars": [
-      {
-        "name": "traefik_enabled",
-        "description": "Enable Traefik reverse proxy integration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "traefik_network",
-        "description": "Traefik network name",
-        "type": "str",
-        "default": "traefik"
-      },
-      {
-        "name": "traefik_host",
-        "description": "Domain name for your service (e.g., app.example.com)",
-        "type": "str"
-      },
-      {
-        "name": "traefik_entrypoint",
-        "description": "HTTP entrypoint (non-TLS)",
-        "type": "str",
-        "default": "web"
-      }
-    ]
-  },
-  {
-    "key": "traefik_tls",
-    "title": "Traefik TLS/SSL",
-    "toggle": "traefik_tls_enabled",
-    "needs": ["traefik"],
-    "description": "Enable HTTPS/TLS for Traefik with certificate management.",
-    "vars": [
-      {
-        "name": "traefik_tls_enabled",
-        "description": "Enable HTTPS/TLS",
-        "type": "bool",
-        "default": true
-      },
-      {
-        "name": "traefik_tls_entrypoint",
-        "description": "TLS entrypoint",
-        "type": "str",
-        "default": "websecure"
-      },
-      {
-        "name": "traefik_tls_certresolver",
-        "description": "Traefik certificate resolver name",
-        "type": "str",
-        "default": "cloudflare"
-      }
-    ]
-  },
-  {
-    "key": "swarm",
-    "title": "Docker Swarm",
-    "toggle": "swarm_enabled",
-    "description": "Deploy service in Docker Swarm mode with replicas.",
-    "vars": [
-      {
-        "name": "swarm_enabled",
-        "description": "Enable Docker Swarm mode",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "swarm_replicas",
-        "description": "Number of replicas in Swarm",
-        "type": "int",
-        "default": 1
-      },
-      {
-        "name": "swarm_placement_mode",
-        "description": "Swarm placement mode",
-        "type": "enum",
-        "options": ["global", "replicated"],
-        "default": "replicated"
-      },
-      {
-        "name": "swarm_placement_host",
-        "description": "Limit placement to specific node",
-        "type": "str"
-      }
-    ]
-  },
-  {
-    "key": "database",
-    "title": "Database",
-    "toggle": "database_enabled",
-    "description": "Connect to external database (PostgreSQL or MySQL)",
-    "vars": [
-      {
-        "name": "database_enabled",
-        "description": "Enable external database integration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "database_type",
-        "description": "Database type",
-        "type": "enum",
-        "options": ["postgres", "mysql"],
-        "default": "postgres"
-      },
-      {
-        "name": "database_external",
-        "description": "Use an external database server?",
-        "extra": "skips creation of internal database container",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "database_host",
-        "description": "Database host",
-        "type": "str",
-        "default": "database"
-      },
-      {
-        "name": "database_port",
-        "description": "Database port",
-        "type": "int"
-      },
-      {
-        "name": "database_name",
-        "description": "Database name",
-        "type": "str"
-      },
-      {
-        "name": "database_user",
-        "description": "Database user",
-        "type": "str"
-      },
-      {
-        "name": "database_password",
-        "description": "Database password",
-        "type": "str",
-        "default": "",
-        "sensitive": true,
-        "autogenerated": true
-      }
-    ]
-  }
-]

+ 0 - 312
library/schemas/compose/v1.1.json

@@ -1,312 +0,0 @@
-[
-  {
-    "key": "general",
-    "title": "General",
-    "required": true,
-    "vars": [
-      {
-        "name": "service_name",
-        "description": "Service name",
-        "type": "str"
-      },
-      {
-        "name": "container_name",
-        "description": "Container name",
-        "type": "str"
-      },
-      {
-        "name": "container_hostname",
-        "description": "Container internal hostname",
-        "type": "str"
-      },
-      {
-        "name": "container_timezone",
-        "description": "Container timezone (e.g., Europe/Berlin)",
-        "type": "str",
-        "default": "UTC"
-      },
-      {
-        "name": "user_uid",
-        "description": "User UID for container process",
-        "type": "int",
-        "default": 1000
-      },
-      {
-        "name": "user_gid",
-        "description": "User GID for container process",
-        "type": "int",
-        "default": 1000
-      },
-      {
-        "name": "container_loglevel",
-        "description": "Container log level",
-        "type": "enum",
-        "options": ["debug", "info", "warn", "error"],
-        "default": "info"
-      },
-      {
-        "name": "restart_policy",
-        "description": "Container restart policy",
-        "type": "enum",
-        "options": ["unless-stopped", "always", "on-failure", "no"],
-        "default": "unless-stopped"
-      }
-    ]
-  },
-  {
-    "key": "network",
-    "title": "Network",
-    "vars": [
-      {
-        "name": "network_mode",
-        "description": "Docker network mode",
-        "type": "enum",
-        "options": ["bridge", "host", "macvlan"],
-        "default": "bridge",
-        "extra": "bridge=default Docker networking, host=use host network stack, macvlan=dedicated MAC address on physical network"
-      },
-      {
-        "name": "network_name",
-        "description": "Docker network name",
-        "type": "str",
-        "default": "bridge",
-        "needs": ["network_mode=bridge,macvlan"]
-      },
-      {
-        "name": "network_external",
-        "description": "Use existing Docker network (external)",
-        "type": "bool",
-        "default": false,
-        "needs": ["network_mode=bridge,macvlan"]
-      },
-      {
-        "name": "network_macvlan_ipv4_address",
-        "description": "Static IP address for container",
-        "type": "str",
-        "default": "192.168.1.253",
-        "needs": ["network_mode=macvlan"]
-      },
-      {
-        "name": "network_macvlan_parent_interface",
-        "description": "Host network interface name",
-        "type": "str",
-        "default": "eth0",
-        "needs": ["network_mode=macvlan"]
-      },
-      {
-        "name": "network_macvlan_subnet",
-        "description": "Network subnet in CIDR notation",
-        "type": "str",
-        "default": "192.168.1.0/24",
-        "needs": ["network_mode=macvlan"]
-      },
-      {
-        "name": "network_macvlan_gateway",
-        "description": "Network gateway IP address",
-        "type": "str",
-        "default": "192.168.1.1",
-        "needs": ["network_mode=macvlan"]
-      }
-    ]
-  },
-  {
-    "key": "ports",
-    "title": "Ports",
-    "needs": ["network_mode=bridge"],
-    "vars": []
-  },
-  {
-    "key": "traefik",
-    "title": "Traefik",
-    "toggle": "traefik_enabled",
-    "needs": ["network_mode=bridge"],
-    "description": "Traefik routes external traffic to your service.",
-    "vars": [
-      {
-        "name": "traefik_enabled",
-        "description": "Enable Traefik reverse proxy integration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "traefik_network",
-        "description": "Traefik network name",
-        "type": "str",
-        "default": "traefik"
-      },
-      {
-        "name": "traefik_host",
-        "description": "Domain name for your service (e.g., app.example.com)",
-        "type": "str"
-      },
-      {
-        "name": "traefik_entrypoint",
-        "description": "HTTP entrypoint (non-TLS)",
-        "type": "str",
-        "default": "web"
-      }
-    ]
-  },
-  {
-    "key": "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": [
-      {
-        "name": "traefik_tls_enabled",
-        "description": "Enable HTTPS/TLS",
-        "type": "bool",
-        "default": true
-      },
-      {
-        "name": "traefik_tls_entrypoint",
-        "description": "TLS entrypoint",
-        "type": "str",
-        "default": "websecure"
-      },
-      {
-        "name": "traefik_tls_certresolver",
-        "description": "Traefik certificate resolver name",
-        "type": "str",
-        "default": "cloudflare"
-      }
-    ]
-  },
-  {
-    "key": "swarm",
-    "title": "Docker Swarm",
-    "toggle": "swarm_enabled",
-    "needs": ["network_mode=bridge"],
-    "description": "Deploy service in Docker Swarm mode.",
-    "vars": [
-      {
-        "name": "swarm_enabled",
-        "description": "Enable Docker Swarm mode",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "swarm_placement_mode",
-        "description": "Swarm placement mode",
-        "type": "enum",
-        "options": ["replicated", "global"],
-        "default": "replicated"
-      },
-      {
-        "name": "swarm_replicas",
-        "description": "Number of replicas",
-        "type": "int",
-        "default": 1,
-        "needs": ["swarm_placement_mode=replicated"]
-      },
-      {
-        "name": "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"
-      },
-      {
-        "name": "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!"
-      },
-      {
-        "name": "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"
-      },
-      {
-        "name": "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"
-      },
-      {
-        "name": "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"
-      },
-      {
-        "name": "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"
-      }
-    ]
-  },
-  {
-    "key": "database",
-    "title": "Database",
-    "toggle": "database_enabled",
-    "description": "Connect to external database (PostgreSQL or MySQL)",
-    "vars": [
-      {
-        "name": "database_enabled",
-        "description": "Enable external database integration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "database_type",
-        "description": "Database type",
-        "type": "enum",
-        "options": ["default", "sqlite", "postgres", "mysql"],
-        "default": "default"
-      },
-      {
-        "name": "database_external",
-        "description": "Use an external database server?",
-        "extra": "skips creation of internal database container",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "database_host",
-        "description": "Database host",
-        "type": "str",
-        "default": "database"
-      },
-      {
-        "name": "database_port",
-        "description": "Database port",
-        "type": "int"
-      },
-      {
-        "name": "database_name",
-        "description": "Database name",
-        "type": "str"
-      },
-      {
-        "name": "database_user",
-        "description": "Database user",
-        "type": "str"
-      },
-      {
-        "name": "database_password",
-        "description": "Database password",
-        "type": "str",
-        "default": "",
-        "sensitive": true,
-        "autogenerated": true
-      }
-    ]
-  }
-]

+ 0 - 512
library/schemas/compose/v1.2.json

@@ -1,512 +0,0 @@
-[
-  {
-    "key": "general",
-    "title": "General",
-    "vars": [
-      {
-        "name": "service_name",
-        "description": "Service name",
-        "type": "str",
-        "required": true
-      },
-      {
-        "name": "container_name",
-        "description": "Container name",
-        "type": "str"
-      },
-      {
-        "name": "container_hostname",
-        "description": "Container internal hostname",
-        "type": "str"
-      },
-      {
-        "name": "container_timezone",
-        "description": "Container timezone (e.g., Europe/Berlin)",
-        "type": "str"
-      },
-      {
-        "name": "user_uid",
-        "description": "User UID for container process",
-        "type": "int",
-        "default": 1000
-      },
-      {
-        "name": "user_gid",
-        "description": "User GID for container process",
-        "type": "int",
-        "default": 1000
-      },
-      {
-        "name": "container_loglevel",
-        "description": "Container log level",
-        "type": "enum",
-        "options": ["debug", "info", "warn", "error"]
-      },
-      {
-        "name": "restart_policy",
-        "description": "Container restart policy",
-        "type": "enum",
-        "options": ["unless-stopped", "always", "on-failure", "no"],
-        "default": "unless-stopped",
-        "required": true
-      }
-    ]
-  },
-  {
-    "key": "network",
-    "title": "Network",
-    "vars": [
-      {
-        "name": "network_mode",
-        "description": "Docker network mode",
-        "type": "enum",
-        "options": ["bridge", "host", "macvlan"],
-        "extra": "bridge=default Docker networking, host=use host network stack, macvlan=dedicated MAC address on physical network"
-      },
-      {
-        "name": "network_name",
-        "description": "Docker network name",
-        "type": "str",
-        "default": "bridge",
-        "needs": ["network_mode=bridge,macvlan"],
-        "required": true
-      },
-      {
-        "name": "network_external",
-        "description": "Use existing Docker network (external)",
-        "type": "bool",
-        "default": false,
-        "needs": ["network_mode=bridge,macvlan"]
-      },
-      {
-        "name": "network_macvlan_ipv4_address",
-        "description": "Static IP address for container",
-        "type": "str",
-        "default": "192.168.1.253",
-        "needs": ["network_mode=macvlan"],
-        "required": true
-      },
-      {
-        "name": "network_macvlan_parent_interface",
-        "description": "Host network interface name",
-        "type": "str",
-        "default": "eth0",
-        "needs": ["network_mode=macvlan"],
-        "required": true
-      },
-      {
-        "name": "network_macvlan_subnet",
-        "description": "Network subnet in CIDR notation",
-        "type": "str",
-        "default": "192.168.1.0/24",
-        "needs": ["network_mode=macvlan"],
-        "required": true
-      },
-      {
-        "name": "network_macvlan_gateway",
-        "description": "Network gateway IP address",
-        "type": "str",
-        "default": "192.168.1.1",
-        "needs": ["network_mode=macvlan"],
-        "required": true
-      }
-    ]
-  },
-  {
-    "key": "ports",
-    "title": "Ports",
-    "needs": ["network_mode!=host,macvlan"],
-    "description": "Expose service ports to the host.",
-    "vars": [
-      {
-        "name": "ports_http",
-        "description": "HTTP port on host",
-        "type": "int",
-        "needs": ["traefik_enabled=false"],
-        "default": 8080,
-        "required": true
-      },
-      {
-        "name": "ports_https",
-        "description": "HTTPS port on host",
-        "type": "int",
-        "needs": ["traefik_enabled=false"],
-        "default": 8443,
-        "required": true
-      },
-      {
-        "name": "ports_ssh",
-        "description": "SSH port on host",
-        "type": "int",
-        "default": 22,
-        "required": true
-      },
-      {
-        "name": "ports_dns",
-        "description": "DNS port on host",
-        "type": "int",
-        "default": 53,
-        "required": true
-      },
-      {
-        "name": "ports_dhcp",
-        "description": "DHCP port on host",
-        "type": "int",
-        "default": 67,
-        "required": true
-      },
-      {
-        "name": "ports_smtp",
-        "description": "SMTP port on host",
-        "type": "int",
-        "default": 25,
-        "required": true
-      },
-      {
-        "name": "ports_snmp",
-        "description": "SNMP trap port",
-        "type": "int",
-        "default": 162,
-        "required": true
-      }
-    ]
-  },
-  {
-    "key": "traefik",
-    "title": "Traefik",
-    "toggle": "traefik_enabled",
-    "needs": ["network_mode!=host,macvlan"],
-    "description": "Traefik routes external traffic to your service.",
-    "vars": [
-      {
-        "name": "traefik_enabled",
-        "description": "Enable Traefik reverse proxy integration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "traefik_network",
-        "description": "Traefik network name",
-        "type": "str",
-        "default": "traefik",
-        "required": true
-      },
-      {
-        "name": "traefik_host",
-        "description": "Service subdomain or full hostname (e.g., 'app' or 'app.example.com')",
-        "type": "str",
-        "required": true
-      },
-      {
-        "name": "traefik_domain",
-        "description": "Base domain (e.g., example.com)",
-        "type": "str",
-        "default": "home.arpa",
-        "required": true
-      }
-    ]
-  },
-  {
-    "key": "traefik_tls",
-    "title": "Traefik TLS/SSL",
-    "toggle": "traefik_tls_enabled",
-    "needs": ["traefik_enabled=true", "network_mode!=host,macvlan"],
-    "description": "Enable HTTPS/TLS for Traefik with certificate management.",
-    "vars": [
-      {
-        "name": "traefik_tls_enabled",
-        "description": "Enable HTTPS/TLS",
-        "type": "bool",
-        "default": true
-      },
-      {
-        "name": "traefik_tls_certresolver",
-        "description": "Traefik certificate resolver name",
-        "type": "str",
-        "default": "cloudflare",
-        "required": true
-      }
-    ]
-  },
-  {
-    "key": "volume",
-    "title": "Volume Storage",
-    "description": "Configure persistent storage for your service.",
-    "vars": [
-      {
-        "name": "volume_mode",
-        "description": "Volume storage backend",
-        "type": "enum",
-        "options": ["local", "mount", "nfs"],
-        "default": "local",
-        "required": true
-      },
-      {
-        "name": "volume_mount_path",
-        "description": "Host path for bind mounts",
-        "type": "str",
-        "default": "/mnt/storage",
-        "needs": ["volume_mode=mount"],
-        "required": true
-      },
-      {
-        "name": "volume_nfs_server",
-        "description": "NFS server address",
-        "type": "str",
-        "default": "192.168.1.1",
-        "needs": ["volume_mode=nfs"],
-        "required": true
-      },
-      {
-        "name": "volume_nfs_path",
-        "description": "NFS export path",
-        "type": "str",
-        "default": "/export",
-        "needs": ["volume_mode=nfs"],
-        "required": true
-      },
-      {
-        "name": "volume_nfs_options",
-        "description": "NFS mount options (comma-separated)",
-        "type": "str",
-        "default": "rw,nolock,soft",
-        "needs": ["volume_mode=nfs"],
-        "required": true
-      }
-    ]
-  },
-  {
-    "key": "resources",
-    "title": "Resource Limits",
-    "toggle": "resources_enabled",
-    "description": "Set CPU and memory limits for the service.",
-    "vars": [
-      {
-        "name": "resources_enabled",
-        "description": "Enable resource limits",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "resources_cpu_limit",
-        "description": "Maximum CPU cores (e.g., 0.5, 1.0, 2.0)",
-        "type": "str",
-        "default": "1.0",
-        "required": true
-      },
-      {
-        "name": "resources_cpu_reservation",
-        "description": "Reserved CPU cores",
-        "type": "str",
-        "default": "0.25",
-        "needs": ["swarm_enabled=true"],
-        "required": true
-      },
-      {
-        "name": "resources_memory_limit",
-        "description": "Maximum memory (e.g., 512M, 1G, 2G)",
-        "type": "str",
-        "default": "1G",
-        "required": true
-      },
-      {
-        "name": "resources_memory_reservation",
-        "description": "Reserved memory",
-        "type": "str",
-        "default": "512M",
-        "needs": ["swarm_enabled=true"],
-        "required": true
-      }
-    ]
-  },
-  {
-    "key": "swarm",
-    "title": "Docker Swarm",
-    "toggle": "swarm_enabled",
-    "needs": ["network_mode!=host,macvlan"],
-    "description": "Deploy service in Docker Swarm mode.",
-    "vars": [
-      {
-        "name": "swarm_enabled",
-        "description": "Enable Docker Swarm mode",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "swarm_placement_mode",
-        "description": "Swarm placement mode",
-        "type": "enum",
-        "options": ["replicated", "global"],
-        "default": "replicated",
-        "required": true
-      },
-      {
-        "name": "swarm_replicas",
-        "description": "Number of replicas",
-        "type": "int",
-        "default": 1,
-        "needs": ["swarm_placement_mode=replicated"],
-        "required": true
-      },
-      {
-        "name": "swarm_placement_host",
-        "description": "Target hostname for placement constraint",
-        "type": "str",
-        "default": "",
-        "needs": ["swarm_placement_mode=replicated"],
-        "extra": "Constrains service to run on specific node by hostname"
-      }
-    ]
-  },
-  {
-    "key": "database",
-    "title": "Database",
-    "toggle": "database_enabled",
-    "description": "Connect to external database (PostgreSQL or MySQL)",
-    "vars": [
-      {
-        "name": "database_enabled",
-        "description": "Enable external database integration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "database_type",
-        "description": "Database type",
-        "type": "enum",
-        "options": ["sqlite", "postgres", "mysql"],
-        "default": "sqlite",
-        "required": true
-      },
-      {
-        "name": "database_external",
-        "description": "Use an external database server?",
-        "extra": "skips creation of internal database container",
-        "type": "bool",
-        "needs": ["database_type=postgres,mysql"],
-        "default": false
-      },
-      {
-        "name": "database_host",
-        "description": "Database host",
-        "type": "str",
-        "needs": ["database_external=true"],
-        "default": "database",
-        "required": true
-      },
-      {
-        "name": "database_port",
-        "description": "Database port",
-        "type": "int",
-        "required": true
-      },
-      {
-        "name": "database_name",
-        "description": "Database name",
-        "type": "str",
-        "required": true
-      },
-      {
-        "name": "database_user",
-        "description": "Database user",
-        "type": "str",
-        "required": true
-      },
-      {
-        "name": "database_password",
-        "description": "Database password",
-        "type": "str",
-        "default": "",
-        "sensitive": true,
-        "autogenerated": true,
-        "required": true
-      }
-    ]
-  },
-  {
-    "key": "email",
-    "title": "Email Server",
-    "toggle": "email_enabled",
-    "description": "Configure email server for notifications and user management.",
-    "vars": [
-      {
-        "name": "email_enabled",
-        "description": "Enable email server configuration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "email_host",
-        "description": "SMTP server hostname",
-        "type": "str",
-        "required": true
-      },
-      {
-        "name": "email_port",
-        "description": "SMTP server port",
-        "type": "int",
-        "default": 25,
-        "required": true
-      },
-      {
-        "name": "email_username",
-        "description": "SMTP username",
-        "type": "str",
-        "required": true
-      },
-      {
-        "name": "email_password",
-        "description": "SMTP password",
-        "type": "str",
-        "sensitive": true,
-        "required": true
-      },
-      {
-        "name": "email_from",
-        "description": "From email address",
-        "type": "email",
-        "required": true
-      },
-      {
-        "name": "email_encryption",
-        "description": "Email encryption method to use",
-        "type": "enum",
-        "options": ["none", "starttls", "ssl"]
-      }
-    ]
-  },
-  {
-    "key": "authentik",
-    "title": "Authentik SSO",
-    "toggle": "authentik_enabled",
-    "description": "Integrate with Authentik for Single Sign-On authentication.",
-    "vars": [
-      {
-        "name": "authentik_enabled",
-        "description": "Enable Authentik SSO integration",
-        "type": "bool",
-        "default": false
-      },
-      {
-        "name": "authentik_url",
-        "description": "Authentik base URL (e.g., https://auth.example.com)",
-        "type": "url",
-        "required": true
-      },
-      {
-        "name": "authentik_slug",
-        "description": "Authentik application slug",
-        "type": "str",
-        "required": true
-      },
-      {
-        "name": "authentik_traefik_middleware",
-        "description": "Traefik middleware name for Authentik authentication",
-        "type": "str",
-        "default": "authentik-middleware@file",
-        "needs": ["traefik_enabled=true"],
-        "required": true
-      }
-    ]
-  }
-]

+ 0 - 14
library/schemas/helm/v1.0.json

@@ -1,14 +0,0 @@
-[
-  {
-    "key": "general",
-    "title": "General",
-    "required": true,
-    "vars": [
-      {
-        "name": "playbook_name",
-        "description": "Ansible playbook name",
-        "type": "str"
-      }
-    ]
-  }
-]

+ 0 - 14
library/schemas/kubernetes/v1.0.json

@@ -1,14 +0,0 @@
-[
-  {
-    "key": "general",
-    "title": "General",
-    "required": true,
-    "vars": [
-      {
-        "name": "playbook_name",
-        "description": "Ansible playbook name",
-        "type": "str"
-      }
-    ]
-  }
-]

+ 0 - 14
library/schemas/packer/v1.0.json

@@ -1,14 +0,0 @@
-[
-  {
-    "key": "general",
-    "title": "General",
-    "required": true,
-    "vars": [
-      {
-        "name": "playbook_name",
-        "description": "Ansible playbook name",
-        "type": "str"
-      }
-    ]
-  }
-]

+ 0 - 28
library/schemas/script/v1.0.json

@@ -1,28 +0,0 @@
-[
-  {
-    "key": "general",
-    "title": "General",
-    "required": true,
-    "vars": [
-      {
-        "name": "script_name",
-        "description": "Script name",
-        "type": "str",
-        "required": true
-      },
-      {
-        "name": "script_type",
-        "description": "Script type/runtime",
-        "type": "enum",
-        "options": ["bash", "python"],
-        "default": "bash",
-        "required": true
-      },
-      {
-        "name": "description",
-        "description": "Script description",
-        "type": "str"
-      }
-    ]
-  }
-]

+ 0 - 36
library/schemas/terraform/v1.0.json

@@ -1,36 +0,0 @@
-[
-  {
-    "key": "general",
-    "title": "General",
-    "required": true,
-    "vars": [
-      {
-        "name": "project_name",
-        "description": "Terraform project name",
-        "type": "str",
-        "required": true
-      },
-      {
-        "name": "description",
-        "description": "Project description",
-        "type": "str"
-      }
-    ]
-  },
-  {
-    "key": "providers",
-    "title": "Providers",
-    "description": "Terraform provider configuration",
-    "required": true,
-    "vars": [
-      {
-        "name": "providers",
-        "description": "Required Terraform providers (JSON array of {name, version})",
-        "type": "str",
-        "required": true,
-        "default": "[]",
-        "extra": "JSON array of provider objects, e.g., [{\"name\":\"aws\",\"version\":\"~> 5.0\"}]"
-      }
-    ]
-  }
-]