From a327f59bf739f040b313f3b4b6b7d89972335b60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesu=CC=81s=20Pe=CC=81rez?= Date: Thu, 8 Jan 2026 21:19:01 +0000 Subject: [PATCH] chore: update items --- forminquire/README.md | 239 -------- forminquire/nulib/forminquire.nu | 540 ------------------ .../templates/server-delete-confirm.form.j2 | 50 -- forminquire/templates/settings-update.form.j2 | 73 --- forminquire/templates/setup-wizard.form.j2 | 180 ------ forminquire/templates/workspace-init.form.j2 | 121 ---- forminquire/wrappers/form.sh | 30 - plugins/.gitkeep | 0 plugins/install-and-register.nu | 65 --- plugins/install-plugins.nu | 321 ----------- plugins/register-plugins.nu | 93 --- plugins/test-plugins.nu | 264 --------- versions.k | 101 ---- 13 files changed, 2077 deletions(-) delete mode 100644 forminquire/README.md delete mode 100644 forminquire/nulib/forminquire.nu delete mode 100644 forminquire/templates/server-delete-confirm.form.j2 delete mode 100644 forminquire/templates/settings-update.form.j2 delete mode 100644 forminquire/templates/setup-wizard.form.j2 delete mode 100644 forminquire/templates/workspace-init.form.j2 delete mode 100755 forminquire/wrappers/form.sh delete mode 100644 plugins/.gitkeep delete mode 100644 plugins/install-and-register.nu delete mode 100644 plugins/install-plugins.nu delete mode 100644 plugins/register-plugins.nu delete mode 100644 plugins/test-plugins.nu delete mode 100644 versions.k diff --git a/forminquire/README.md b/forminquire/README.md deleted file mode 100644 index 7285019..0000000 --- a/forminquire/README.md +++ /dev/null @@ -1,239 +0,0 @@ -# FormInquire Integration System - -Dynamic form generation using Jinja2 templates rendered with `nu_plugin_tera`. - -## Architecture - -``` -provisioning/core/forminquire/ -├── templates/ # Jinja2 form templates (.j2) -│ ├── setup-wizard.form.j2 -│ ├── workspace-init.form.j2 -│ ├── settings-update.form.j2 -│ ├── server-delete-confirm.form.j2 -│ └── ...more templates -├── nulib/ -│ └── forminquire.nu # Nushell integration functions -└── wrappers/ - └── form.sh # Bash wrapper for FormInquire -``` - -## How It Works - -1. **Template Rendering**: Jinja2 templates are rendered with data from config files -2. **Form Generation**: Rendered templates are saved as TOML forms in cache -3. **User Interaction**: FormInquire binary presents the form to user -4. **Result Processing**: JSON output from FormInquire is returned to calling code - -``` -Config Data → Template Rendering → Form Generation → FormInquire → JSON Output - (nu_plugin_tera) (cache: ~/.cache/) (interactive) -``` - -## Quick Examples - -### Settings Update with Current Values as Defaults - -```nushell -use provisioning/core/forminquire/nulib/forminquire.nu * - -# Load current settings and show form with them as defaults -let result = (settings-update-form) - -if $result.success { - # Process updated settings - print $"Updated: ($result.values | to json)" -} -``` - -### Setup Wizard - -```nushell -let result = (setup-wizard-form) - -if $result.success { - print "Setup configuration:" - print ($result.values | to json) -} -``` - -### Workspace Initialization - -```nushell -let result = (workspace-init-form "my-workspace") - -if $result.success { - print "Workspace created with settings:" - print ($result.values | to json) -} -``` - -### Server Delete Confirmation - -```nushell -let confirm = (server-delete-confirm-form "web-01" "192.168.1.10" "running") - -if $confirm.success { - let confirmation_text = $confirm.values.confirmation_text - let final_confirm = $confirm.values.final_confirm - - if ($confirmation_text == "web-01" and $final_confirm) { - print "Deleting server..." - } -} -``` - -## Template Variables - -All templates have access to: - -### Automatic Variables (always available) -- `now_iso`: Current timestamp in ISO 8601 format -- `home_dir`: User's home directory -- `username`: Current username -- `provisioning_root`: Provisioning root directory - -### Custom Variables (passed per form) -- Settings from `config.defaults.toml` -- User preferences from `~/.config/provisioning/user_config.yaml` -- Workspace configuration from workspace `config.toml` -- Any custom data passed to the form function - -## Cache Management - -Forms are cached at: `~/.cache/provisioning/forms/` - -### Cleanup Old Forms - -```nushell -let cleanup_result = (cleanup-form-cache) -print $"Cleaned up ($cleanup_result.cleaned) old form files" -``` - -### List Generated Forms - -```nushell -list-cached-forms -``` - -## Template Syntax - -Templates use Jinja2 syntax with macros for common form elements: - -```jinja2 -[items.my_field] -type = "text" -prompt = "Enter value" -default = "{{ my_variable }}" -help = "Help text here" -required = true -``` - -### Available Form Types - -- `text`: Text input -- `select`: Dropdown selection -- `confirm`: Yes/No confirmation -- `password`: Masked password input -- `multiselect`: Multiple selection - -## Available Functions - -### Form Execution - -- `interactive-form [name] [template] [data]` - Complete form flow -- `render-template [template_name] [data]` - Render template only -- `generate-form [form_name] [template_name] [data]` - Generate TOML form -- `run-form [form_path]` - Execute FormInquire with form - -### Config Loading - -- `load-user-preferences` - Load user preferences from config -- `load-workspace-config [workspace_name]` - Load workspace settings -- `load-system-defaults` - Load system defaults -- `get-form-context [workspace_name] [custom_data]` - Merged config context - -### Convenience Functions - -- `settings-update-form` - Update system settings -- `setup-wizard-form` - Run setup wizard -- `workspace-init-form [name]` - Initialize workspace -- `server-delete-confirm-form [name] [ip] [status]` - Delete confirmation - -### Utilities - -- `list-templates` - List available templates -- `list-cached-forms` - List generated forms in cache -- `cleanup-form-cache` - Remove old cached forms - -## Shell Integration - -Use the bash wrapper for shell scripts: - -```bash -#!/bin/bash - -# Generate form with Nushell -nu -c "use forminquire *; interactive-form 'my-form' 'my-template' {foo: 'bar'}" > /tmp/form.toml - -# Or use form.sh wrapper directly -./provisioning/core/forminquire/wrappers/form.sh /path/to/form.toml json -``` - -## Performance Notes - -- **First form**: ~200ms (template rendering + form generation) -- **Subsequent forms**: ~50ms (cached config loading) -- **User interaction**: Depends on FormInquire response time -- **Form cache**: Automatically cleaned after 1+ days - -## Dependencies - -- `forminquire` - FormInquire binary (in PATH) -- `nu_plugin_tera` - Nushell Jinja2 template plugin -- `Nushell 0.109.0+` - Core scripting language - -## Error Handling - -All functions return structured results: - -```nushell -{ - success: bool # Operation succeeded - error: string # Error message (empty if success) - form_path: string # Generated form path (if applicable) - values: record # FormInquire output values -} -``` - -## Adding New Forms - -1. Create template in `templates/` with `.form.j2` extension -2. Create convenience function in `forminquire.nu` like `my-form-function` -3. Use in scripts: `my-form-function [args...]` - -Example: - -```jinja2 -# templates/my-form.form.j2 -[meta] -title = "My Custom Form" -[items.field1] -type = "text" -prompt = "Enter value" -default = "{{ default_value }}" -``` - -```nushell -# In forminquire.nu -export def my-form-function [default_value: string = ""] { - interactive-form "my-form" "my-form" {default_value: $default_value} -} -``` - -## Limitations - -- Template rendering uses Jinja2 syntax only -- FormInquire must be in PATH -- `nu_plugin_tera` must be installed for template rendering -- Form output limited to FormInquire-supported types diff --git a/forminquire/nulib/forminquire.nu b/forminquire/nulib/forminquire.nu deleted file mode 100644 index a7edf18..0000000 --- a/forminquire/nulib/forminquire.nu +++ /dev/null @@ -1,540 +0,0 @@ -#!/usr/bin/env nu -# [command] -# name = "forminquire integration" -# group = "infrastructure" -# tags = ["forminquire", "forms", "interactive", "templates"] -# version = "1.0.0" -# requires = ["nu_plugin_tera", "forminquire:1.0.0"] -# note = "Dynamic form generation using Jinja2 templates rendered with nu_plugin_tera" - -# ============================================================================ -# FormInquire Integration System -# Version: 1.0.0 -# Purpose: Generate interactive forms dynamically from templates and config data -# ============================================================================ - -# Get form cache directory -def get-form-cache-dir [] : nothing -> string { - let cache_dir = ( - if ($env.XDG_CACHE_HOME? | is-empty) { - $"($env.HOME)/.cache/provisioning/forms" - } else { - $"($env.XDG_CACHE_HOME)/provisioning/forms" - } - ) - $cache_dir -} - -# Ensure cache directory exists -def ensure-form-cache-dir [] : nothing -> string { - let cache_dir = (get-form-cache-dir) - let _mkdir_result = (do { - if not (($cache_dir | path exists)) { - ^mkdir -p $cache_dir - } - } | complete) - $cache_dir -} - -# Get template directory -def get-template-dir [] : nothing -> string { - let proj_root = ( - if (($env.PROVISIONING_ROOT? | is-empty)) { - $"($env.HOME)/project-provisioning" - } else { - $env.PROVISIONING_ROOT - } - ) - $"($proj_root)/provisioning/core/forminquire/templates" -} - -# Load TOML configuration file -def load-toml-config [path: string] : nothing -> record { - let result = (do { open $path | from toml } | complete) - if ($result.exit_code == 0) { - $result.stdout - } else { - {} - } -} - -# Load YAML configuration file -def load-yaml-config [path: string] : nothing -> record { - let result = (do { open $path | from yaml } | complete) - if ($result.exit_code == 0) { - $result.stdout - } else { - {} - } -} - -# Render Jinja2 template with data -export def render-template [ - template_name: string - data: record = {} -] : nothing -> record { - let template_dir = (get-template-dir) - let template_path = $"($template_dir)/($template_name).j2" - - if not (($template_path | path exists)) { - return { - error: $"Template not found: ($template_path)" - content: "" - } - } - - let template_content_result = (do { ^cat $template_path } | complete) - if ($template_content_result.exit_code != 0) { - return { - error: "Failed to read template file" - content: "" - } - } - - let template_content = $template_content_result.stdout - - let enriched_data = ( - $data - | merge { - now_iso: (date now | format date "%Y-%m-%dT%H:%M:%SZ") - home_dir: $env.HOME - username: (whoami) - provisioning_root: ( - if (($env.PROVISIONING_ROOT? | is-empty)) { - $"($env.HOME)/project-provisioning" - } else { - $env.PROVISIONING_ROOT - } - ) - } - ) - - let render_result = (do { - tera -t $template_content --data ($enriched_data | to json) - } | complete) - - if ($render_result.exit_code == 0) { - { - error: "" - content: $render_result.stdout - } - } else { - { - error: "Template rendering failed" - content: "" - } - } -} - -# Generate form from template and save to cache -export def generate-form [ - form_name: string - template_name: string - data: record = {} -] : nothing -> record { - let cache_dir = (ensure-form-cache-dir) - let form_path = $"($cache_dir)/($form_name).toml" - - let render_result = (render-template $template_name $data) - - if not (($render_result.error | is-empty)) { - return { - success: false - error: $render_result.error - form_path: "" - } - } - - let write_result = (do { - $render_result.content | ^tee $form_path > /dev/null - } | complete) - - if ($write_result.exit_code == 0) { - { - success: true - error: "" - form_path: $form_path - } - } else { - { - success: false - error: "Failed to write form file" - form_path: "" - } - } -} - -# Execute FormInquire with generated form -export def run-form [form_path: string] : nothing -> record { - if not (($form_path | path exists)) { - return { - success: false - error: $"Form file not found: ($form_path)" - values: {} - } - } - - let forminquire_result = (do { - ^forminquire --from-file $form_path --output json - } | complete) - - if ($forminquire_result.exit_code != 0) { - return { - success: false - error: "FormInquire execution failed" - values: {} - } - } - - let parse_result = (do { - $forminquire_result.stdout | from json - } | complete) - - if ($parse_result.exit_code == 0) { - { - success: true - error: "" - values: $parse_result.stdout - } - } else { - { - success: false - error: "Failed to parse FormInquire output" - values: {} - } - } -} - -# Complete flow: generate form from template and run it -export def interactive-form [ - form_name: string - template_name: string - data: record = {} -] : nothing -> record { - let generate_result = (generate-form $form_name $template_name $data) - - if not $generate_result.success { - return { - success: false - error: $generate_result.error - form_path: "" - values: {} - } - } - - let run_result = (run-form $generate_result.form_path) - - { - success: $run_result.success - error: $run_result.error - form_path: $generate_result.form_path - values: $run_result.values - } -} - -# Load user preferences from config -export def load-user-preferences [] : nothing -> record { - let config_path = $"($env.HOME)/.config/provisioning/user_config.yaml" - load-yaml-config $config_path -} - -# Load workspace config -export def load-workspace-config [workspace_name: string] : nothing -> record { - let workspace_dir = ( - if (($env.PROVISIONING_WORKSPACE? | is-empty)) { - $"($env.HOME)/workspaces/($workspace_name)" - } else { - $env.PROVISIONING_WORKSPACE - } - ) - - let config_file = $"($workspace_dir)/config.toml" - load-toml-config $config_file -} - -# Load system defaults -export def load-system-defaults [] : nothing -> record { - let proj_root = ( - if (($env.PROVISIONING_ROOT? | is-empty)) { - $"($env.HOME)/project-provisioning" - } else { - $env.PROVISIONING_ROOT - } - ) - - let defaults_file = $"($proj_root)/provisioning/config/config.defaults.toml" - load-toml-config $defaults_file -} - -# Merge multiple config sources with priority -export def merge-config-sources [ - defaults: record = {} - workspace: record = {} - user: record = {} - overrides: record = {} -] : nothing -> record { - $defaults | merge $workspace | merge $user | merge $overrides -} - -# Get form context with all available data -export def get-form-context [ - workspace_name: string = "" - custom_data: record = {} -] : nothing -> record { - let defaults = (load-system-defaults) - let user_prefs = (load-user-preferences) - - let workspace_config = ( - if (($workspace_name | is-empty)) { - {} - } else { - load-workspace-config $workspace_name - } - ) - - let merged = (merge-config-sources $defaults $workspace_config $user_prefs $custom_data) - $merged -} - -# Settings update form - loads current settings as defaults -export def settings-update-form [] : nothing -> record { - let context = (get-form-context) - - let data = { - config_source: "system defaults + user preferences" - editor: ($context.preferences.editor? // "vim") - output_format: ($context.preferences.output_format? // "yaml") - default_log_level: ($context.preferences.default_log_level? // "info") - preferred_provider: ($context.preferences.preferred_provider? // "upcloud") - confirm_delete: ($context.preferences.confirm_delete? // true) - confirm_deploy: ($context.preferences.confirm_deploy? // true) - } - - interactive-form "settings-update" "settings-update" $data -} - -# Setup wizard form -export def setup-wizard-form [] : nothing -> record { - let context = (get-form-context) - - let data = { - system_name: ($context.system_name? // "provisioning") - admin_email: ($context.admin_email? // "") - deployment_mode: ($context.deployment_mode? // "solo") - infrastructure_provider: ($context.infrastructure_provider? // "upcloud") - cpu_cores: ($context.resources.cpu_cores? // "4") - memory_gb: ($context.resources.memory_gb? // "8") - disk_gb: ($context.resources.disk_gb? // "50") - workspace_path: ($context.workspace_path? // $"($env.HOME)/provisioning-workspace") - } - - interactive-form "setup-wizard" "setup-wizard" $data -} - -# Workspace init form -export def workspace-init-form [workspace_name: string = ""] : nothing -> record { - let context = (get-form-context $workspace_name) - - let data = { - workspace_name: ( - if (($workspace_name | is-empty)) { - "default" - } else { - $workspace_name - } - ) - workspace_description: ($context.description? // "") - workspace_path: ($context.path? // $"($env.HOME)/workspaces/($workspace_name)") - default_provider: ($context.default_provider? // "upcloud") - default_region: ($context.default_region? // "") - init_git: ($context.init_git? // true) - create_example_configs: ($context.create_example_configs? // true) - setup_secrets: ($context.setup_secrets? // true) - enable_testing: ($context.enable_testing? // true) - enable_monitoring: ($context.enable_monitoring? // false) - enable_orchestrator: ($context.enable_orchestrator? // true) - } - - interactive-form "workspace-init" "workspace-init" $data -} - -# Server delete confirmation form -export def server-delete-confirm-form [ - server_name: string - server_ip: string = "" - server_status: string = "" -] : nothing -> record { - let data = { - server_name: $server_name - server_ip: $server_ip - server_status: $server_status - } - - interactive-form "server-delete-confirm" "server-delete-confirm" $data -} - -# Clean up old form files from cache (older than 1 day) -export def cleanup-form-cache [] : nothing -> record { - let cache_dir = (get-form-cache-dir) - - if not (($cache_dir | path exists)) { - return {cleaned: 0, error: ""} - } - - let find_result = (do { - ^find $cache_dir -name "*.toml" -type f -mtime +1 -delete - } | complete) - - {cleaned: 0, error: ""} -} - -# List available templates -export def list-templates [] : nothing -> list { - let template_dir = (get-template-dir) - - if not (($template_dir | path exists)) { - return [] - } - - let find_result = (do { - ^find $template_dir -name "*.j2" -type f - } | complete) - - if ($find_result.exit_code == 0) { - $find_result.stdout - | lines - | each {|path| - let name = ($path | path basename | str replace ".j2" "") - { - name: $name - path: $path - template_file: ($path | path basename) - } - } - } else { - [] - } -} - -# List generated forms in cache -export def list-cached-forms [] : nothing -> list { - let cache_dir = (ensure-form-cache-dir) - - let find_result = (do { - ^find $cache_dir -name "*.toml" -type f - } | complete) - - if ($find_result.exit_code == 0) { - $find_result.stdout - | lines - | each {|path| - { - name: ($path | path basename) - path: $path - } - } - } else { - [] - } -} - -# ============================================================================ -# DELETE CONFIRMATION HELPERS -# ============================================================================ - -# Run server delete confirmation -export def server-delete-confirm [ - server_name: string - server_ip?: string - server_status?: string -] : nothing -> record { - let context = { - server_name: $server_name - server_ip: (if ($server_ip | is-empty) { "" } else { $server_ip }) - server_status: (if ($server_status | is-empty) { "running" } else { $server_status }) - } - - run-forminquire-form "provisioning/core/shlib/forms/infrastructure/server_delete_confirm.toml" $context -} - -# Run taskserv delete confirmation -export def taskserv-delete-confirm [ - taskserv_name: string - taskserv_type?: string - taskserv_server?: string - taskserv_status?: string - dependent_services?: string -] : nothing -> record { - let context = { - taskserv_name: $taskserv_name - taskserv_type: (if ($taskserv_type | is-empty) { "" } else { $taskserv_type }) - taskserv_server: (if ($taskserv_server | is-empty) { "" } else { $taskserv_server }) - taskserv_status: (if ($taskserv_status | is-empty) { "unknown" } else { $taskserv_status }) - dependent_services: (if ($dependent_services | is-empty) { "none" } else { $dependent_services }) - } - - run-forminquire-form "provisioning/core/shlib/forms/infrastructure/taskserv_delete_confirm.toml" $context -} - -# Run cluster delete confirmation -export def cluster-delete-confirm [ - cluster_name: string - cluster_type?: string - node_count?: string - total_resources?: string - deployments_count?: string - services_count?: string - volumes_count?: string -] : nothing -> record { - let context = { - cluster_name: $cluster_name - cluster_type: (if ($cluster_type | is-empty) { "" } else { $cluster_type }) - node_count: (if ($node_count | is-empty) { "unknown" } else { $node_count }) - total_resources: (if ($total_resources | is-empty) { "" } else { $total_resources }) - deployments_count: (if ($deployments_count | is-empty) { "0" } else { $deployments_count }) - services_count: (if ($services_count | is-empty) { "0" } else { $services_count }) - volumes_count: (if ($volumes_count | is-empty) { "0" } else { $volumes_count }) - } - - run-forminquire-form "provisioning/core/shlib/forms/infrastructure/cluster_delete_confirm.toml" $context -} - -# Generic delete confirmation -export def generic-delete-confirm [ - resource_type: string - resource_name: string - resource_id?: string - resource_status?: string -] : nothing -> record { - let context = { - resource_type: $resource_type - resource_name: $resource_name - resource_id: (if ($resource_id | is-empty) { "" } else { $resource_id }) - resource_status: (if ($resource_status | is-empty) { "unknown" } else { $resource_status }) - } - - run-forminquire-form "provisioning/core/shlib/forms/infrastructure/generic_delete_confirm.toml" $context -} - -# Validate delete confirmation result -export def validate-delete-confirmation [result: record] : nothing -> bool { - # Must have success = true - let success = ($result.success // false) - if not $success { - return false - } - - let values = ($result.values // {}) - - # Must have typed "DELETE" or "DELETE CLUSTER" - let confirm_text = ($values.confirmation_text // "") - let is_confirmed = (($confirm_text == "DELETE") or ($confirm_text == "DELETE CLUSTER")) - - # Must have checked final confirmation checkbox - let final_checked = ($values.final_confirm // false) - - # Must have checked proceed checkbox - let proceed_checked = ($values.proceed // false) - - ($is_confirmed and $final_checked and $proceed_checked) -} diff --git a/forminquire/templates/server-delete-confirm.form.j2 b/forminquire/templates/server-delete-confirm.form.j2 deleted file mode 100644 index 251bd21..0000000 --- a/forminquire/templates/server-delete-confirm.form.j2 +++ /dev/null @@ -1,50 +0,0 @@ -# Auto-generated delete confirmation form -# Generated: {{ now_iso }} -# Server: {{ server_name }} - -[meta] -title = "Confirm Server Deletion" -description = "WARNING: This operation cannot be reversed. Please confirm carefully." -allow_cancel = true - -[items.server_display] -type = "text" -prompt = "Server to Delete" -default = "{{ server_name }}" -help = "Server name (read-only for confirmation)" -read_only = true - -{% if server_ip %} -[items.server_ip] -type = "text" -prompt = "Server IP Address" -default = "{{ server_ip }}" -help = "IP address (read-only for confirmation)" -read_only = true -{% endif %} - -{% if server_status %} -[items.server_status] -type = "text" -prompt = "Current Status" -default = "{{ server_status }}" -help = "Current server status (read-only)" -read_only = true -{% endif %} - -[items.confirmation_text] -type = "text" -prompt = "Type server name to confirm deletion" -default = "" -help = "You must type the exact server name '{{ server_name }}' to proceed" -required = true - -[items.final_confirm] -type = "confirm" -prompt = "I understand this action is irreversible. Delete server?" -help = "This will permanently delete the server and all its data" - -[items.backup_before_delete] -type = "confirm" -prompt = "Create backup before deletion?" -help = "Optionally create a backup of the server configuration" diff --git a/forminquire/templates/settings-update.form.j2 b/forminquire/templates/settings-update.form.j2 deleted file mode 100644 index bb5037c..0000000 --- a/forminquire/templates/settings-update.form.j2 +++ /dev/null @@ -1,73 +0,0 @@ -{%- macro form_input(name, label, value="", required=false, help="") -%} -[items."{{ name }}"] -type = "text" -prompt = "{{ label }}" -default = "{{ value }}" -{% if help %}help = "{{ help }}" -{% endif %}{% if required %}required = true -{% endif %} -{%- endmacro -%} - -{%- macro form_select(name, label, options=[], value="", help="") -%} -[items."{{ name }}"] -type = "select" -prompt = "{{ label }}" -options = [{% for opt in options %}"{{ opt }}"{{ "," if not loop.last }}{% endfor %}] -default = "{{ value }}" -{% if help %}help = "{{ help }}" -{% endif %} -{%- endmacro -%} - -{%- macro form_confirm(name, label, help="") -%} -[items."{{ name }}"] -type = "confirm" -prompt = "{{ label }}" -{% if help %}help = "{{ help }}" -{% endif %} -{%- endmacro -%} - -# Auto-generated form for settings update -# Generated: {{ now_iso }} -# Config source: {{ config_source }} - -[meta] -title = "Provisioning Settings Update" -description = "Update provisioning configuration settings" -allow_cancel = true - -[items.editor] -type = "text" -prompt = "Preferred Editor" -default = "{{ editor | default('vim') }}" -help = "Editor to use for file editing (vim, nano, emacs)" - -[items.output_format] -type = "select" -prompt = "Default Output Format" -options = ["json", "yaml", "text", "table"] -default = "{{ output_format | default('yaml') }}" -help = "Default output format for commands" - -[items.confirm_delete] -type = "confirm" -prompt = "Confirm Destructive Operations?" -help = "Require confirmation before deleting resources" - -[items.confirm_deploy] -type = "confirm" -prompt = "Confirm Deployments?" -help = "Require confirmation before deploying" - -[items.default_log_level] -type = "select" -prompt = "Default Log Level" -options = ["debug", "info", "warning", "error"] -default = "{{ default_log_level | default('info') }}" -help = "Default logging level" - -[items.preferred_provider] -type = "select" -prompt = "Preferred Cloud Provider" -options = ["upcloud", "aws", "local"] -default = "{{ preferred_provider | default('upcloud') }}" -help = "Preferred infrastructure provider" diff --git a/forminquire/templates/setup-wizard.form.j2 b/forminquire/templates/setup-wizard.form.j2 deleted file mode 100644 index 126d484..0000000 --- a/forminquire/templates/setup-wizard.form.j2 +++ /dev/null @@ -1,180 +0,0 @@ -# Auto-generated form for setup wizard -# Generated: {{ now_iso }} -# This is a comprehensive 7-step setup wizard - -[meta] -title = "Provisioning System Setup Wizard" -description = "Step-by-step configuration for your infrastructure provisioning system" -allow_cancel = true - -# ============================================================================ -# STEP 1: SYSTEM CONFIGURATION -# ============================================================================ - -[items.step1_header] -type = "text" -prompt = "STEP 1/7: System Configuration" -display_only = true - -[items.config_path] -type = "text" -prompt = "Configuration Base Path" -default = "{{ config_path | default('/etc/provisioning') }}" -help = "Where provisioning configuration will be stored" -required = true - -[items.use_defaults_path] -type = "confirm" -prompt = "Use recommended paths for your OS?" -help = "Use OS-specific default paths (recommended)" - -# ============================================================================ -# STEP 2: DEPLOYMENT MODE -# ============================================================================ - -[items.step2_header] -type = "text" -prompt = "STEP 2/7: Deployment Mode Selection" -display_only = true - -[items.deployment_mode] -type = "select" -prompt = "How should platform services be deployed?" -options = ["docker-compose", "kubernetes", "systemd", "remote-ssh"] -default = "{{ deployment_mode | default('docker-compose') }}" -help = "Choose based on your infrastructure type" -required = true - -# ============================================================================ -# STEP 3: PROVIDER SELECTION -# ============================================================================ - -[items.step3_header] -type = "text" -prompt = "STEP 3/7: Infrastructure Providers" -display_only = true - -[items.provider_upcloud] -type = "confirm" -prompt = "Use UpCloud as provider?" -help = "UpCloud offers affordable cloud VMs in European regions" - -[items.provider_aws] -type = "confirm" -prompt = "Use AWS as provider?" -help = "Amazon Web Services - global infrastructure" - -[items.provider_hetzner] -type = "confirm" -prompt = "Use Hetzner as provider?" -help = "Hetzner - German cloud provider with good pricing" - -[items.provider_local] -type = "confirm" -prompt = "Use Local provider?" -help = "Local deployment - useful for development and testing" - -# ============================================================================ -# STEP 4: RESOURCE ALLOCATION -# ============================================================================ - -[items.step4_header] -type = "text" -prompt = "STEP 4/7: Resource Allocation" -display_only = true - -[items.cpu_count] -type = "text" -prompt = "Number of CPUs to allocate" -default = "{{ cpu_count | default('4') }}" -help = "For cloud VMs (1-16, or more for dedicated hardware)" -required = true - -[items.memory_gb] -type = "text" -prompt = "Memory in GB to allocate" -default = "{{ memory_gb | default('8') }}" -help = "RAM for provisioning system and services" -required = true - -[items.disk_gb] -type = "text" -prompt = "Disk space in GB" -default = "{{ disk_gb | default('100') }}" -help = "Primary disk size for VMs or containers" -required = true - -# ============================================================================ -# STEP 5: SECURITY CONFIGURATION -# ============================================================================ - -[items.step5_header] -type = "text" -prompt = "STEP 5/7: Security Configuration" -display_only = true - -[items.enable_mfa] -type = "confirm" -prompt = "Enable Multi-Factor Authentication (MFA)?" -help = "Requires TOTP or WebAuthn for sensitive operations" - -[items.enable_audit_logging] -type = "confirm" -prompt = "Enable audit logging?" -help = "Log all operations for compliance and debugging" - -[items.require_approval] -type = "confirm" -prompt = "Require approval for destructive operations?" -help = "Prevents accidental deletion or modification" - -[items.enable_tls] -type = "confirm" -prompt = "Enable TLS encryption?" -help = "Use HTTPS for all API communications" - -# ============================================================================ -# STEP 6: WORKSPACE CONFIGURATION -# ============================================================================ - -[items.step6_header] -type = "text" -prompt = "STEP 6/7: Workspace Setup" -display_only = true - -[items.create_workspace] -type = "confirm" -prompt = "Create initial workspace now?" -help = "Create a workspace for managing your infrastructure" - -[items.workspace_name] -type = "text" -prompt = "Workspace name" -default = "{{ workspace_name | default('default') }}" -help = "Name for your infrastructure workspace" - -[items.workspace_description] -type = "text" -prompt = "Workspace description (optional)" -default = "{{ workspace_description | default('') }}" -help = "Brief description of what this workspace manages" - -# ============================================================================ -# STEP 7: REVIEW & CONFIRM -# ============================================================================ - -[items.step7_header] -type = "text" -prompt = "STEP 7/7: Review Configuration" -display_only = true - -[items.review_config] -type = "confirm" -prompt = "Review the configuration summary above and confirm?" -help = "Verify all settings before applying" -required = true - -[items.final_confirm] -type = "confirm" -prompt = "I understand this is a major configuration change. Proceed?" -help = "This will create/update system configuration files" diff --git a/forminquire/templates/workspace-init.form.j2 b/forminquire/templates/workspace-init.form.j2 deleted file mode 100644 index b7a73aa..0000000 --- a/forminquire/templates/workspace-init.form.j2 +++ /dev/null @@ -1,121 +0,0 @@ -# Auto-generated form for workspace initialization -# Generated: {{ now_iso }} - -[meta] -title = "Initialize New Workspace" -description = "Create and configure a new provisioning workspace for managing your infrastructure" -allow_cancel = true - -# ============================================================================ -# WORKSPACE BASIC INFORMATION -# ============================================================================ - -[items.workspace_info_header] -type = "text" -prompt = "Workspace Basic Information" -display_only = true - -[items.workspace_name] -type = "text" -prompt = "Workspace Name" -default = "{{ workspace_name | default('default') }}" -help = "Name for this workspace (lowercase, alphanumeric and hyphens)" -required = true - -[items.workspace_description] -type = "text" -prompt = "Workspace Description" -default = "{{ workspace_description | default('') }}" -help = "Brief description of what this workspace manages" - -[items.workspace_path] -type = "text" -prompt = "Workspace Directory Path" -default = "{{ workspace_path | default(home_dir + '/workspaces/default') }}" -help = "Where workspace files and configurations will be stored" -required = true - -# ============================================================================ -# INFRASTRUCTURE DEFAULTS -# ============================================================================ - -[items.infra_header] -type = "text" -prompt = "Infrastructure Configuration" -display_only = true - -[items.default_provider] -type = "select" -prompt = "Default Infrastructure Provider" -options = ["upcloud", "aws", "hetzner", "local"] -default = "{{ default_provider | default('upcloud') }}" -help = "Default cloud provider for servers created in this workspace" - -[items.default_region] -type = "text" -prompt = "Default Region/Zone" -default = "{{ default_region | default('') }}" -help = "Default deployment region (e.g., us-nyc1, eu-de-fra1, none for local)" - -# ============================================================================ -# INITIALIZATION OPTIONS -# ============================================================================ - -[items.init_header] -type = "text" -prompt = "Initialization Options" -display_only = true - -[items.init_git] -type = "confirm" -prompt = "Initialize Git Repository?" -help = "Create git repository for infrastructure as code version control" - -[items.create_example_configs] -type = "confirm" -prompt = "Create Example Configuration Files?" -help = "Generate sample server and infrastructure config files" - -[items.setup_secrets] -type = "confirm" -prompt = "Setup Secrets Management?" -help = "Configure KMS encryption and secrets storage" - -# ============================================================================ -# WORKSPACE FEATURES -# ============================================================================ - -[items.features_header] -type = "text" -prompt = "Workspace Features" -display_only = true - -[items.enable_testing] -type = "confirm" -prompt = "Enable Test Environment Service?" -help = "Enable Docker-based test environments for validating configurations" - -[items.enable_monitoring] -type = "confirm" -prompt = "Setup Monitoring?" -help = "Configure monitoring and observability for your infrastructure" - -[items.enable_orchestrator] -type = "confirm" -prompt = "Start Orchestrator Service?" -help = "Enable the orchestrator for workflow management and automation" - -# ============================================================================ -# CONFIRMATION -# ============================================================================ - -[items.confirm_header] -type = "text" -prompt = "Review and Confirm" -display_only = true - -[items.confirm_creation] -type = "confirm" -prompt = "Create workspace with these settings?" -help = "This will initialize the workspace directory and apply configurations" -required = true diff --git a/forminquire/wrappers/form.sh b/forminquire/wrappers/form.sh deleted file mode 100755 index 0d5ddfd..0000000 --- a/forminquire/wrappers/form.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash -# FormInquire wrapper for shell scripts -# Simple wrapper to execute FormInquire forms from bash/sh - -set -e - -FORM_FILE="${1:-}" -OUTPUT_FORMAT="${2:-json}" - -# Check if form file provided -if [ -z "$FORM_FILE" ]; then - echo "Error: Form file required" >&2 - echo "Usage: form.sh [output_format]" >&2 - exit 1 -fi - -# Check if form file exists -if [ ! -f "$FORM_FILE" ]; then - echo "Error: Form file not found: $FORM_FILE" >&2 - exit 1 -fi - -# Check if forminquire is available -if ! command -v forminquire &> /dev/null; then - echo "Error: forminquire not found in PATH" >&2 - exit 1 -fi - -# Execute forminquire -forminquire --from-file "$FORM_FILE" --output "$OUTPUT_FORMAT" diff --git a/plugins/.gitkeep b/plugins/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/plugins/install-and-register.nu b/plugins/install-and-register.nu deleted file mode 100644 index 103da21..0000000 --- a/plugins/install-and-register.nu +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env nu -# Complete installation and registration of provisioning plugins -# Run this in a fresh Nushell session - -print "Provisioning Plugins - Installation & Registration" -print "==================================================" -print "" - -# Copy plugins to Nushell plugin directory -print "Step 1: Installing plugin binaries..." -print "" - -let plugin_dir = ($env.HOME + "/.local/share/nushell/plugins") - -# Run the registration script -let nu_path = ($env.HOME + "/.local/bin/nu" | path expand) -let register_script = ($env.PWD | path join "provisioning" "core" "plugins" "register-plugins.nu") -^$nu_path $register_script - -print "" -print "Step 2: Registering plugins with Nushell..." -print "" - -# Register plugins -let auth_plugin = ($env.HOME | path join ".local/share/nushell/plugins/nu_plugin_auth" | path expand) -let kms_plugin = ($env.HOME | path join ".local/share/nushell/plugins/nu_plugin_kms" | path expand) -let orch_plugin = ($env.HOME | path join ".local/share/nushell/plugins/nu_plugin_orchestrator" | path expand) - -plugin add $auth_plugin -plugin add $kms_plugin -plugin add $orch_plugin - -sleep 1 - -print "" -print "Step 3: Verifying plugin installation..." -print "" - -# Verify plugins are loaded -let plugins = plugin list | where name =~ "nu_plugin_(auth|kms|orchestrator)" - -if ($plugins | length) == 3 { - print "✓ All 3 plugins registered successfully!" - print "" - print "Installed plugins:" - for plugin in $plugins { - print $" ✓ ($plugin.name)" - } -} else { - print $"⚠ Expected 3 plugins, found ($plugins | length)" - print "Please run the following commands manually:" - print "" - print $"plugin add ($auth_plugin)" - print $"plugin add ($kms_plugin)" - print $"plugin add ($orch_plugin)" -} - -print "" -print "✓ Installation complete!" -print "" -print "You can now use the provisioning CLI with plugin support:" -print "" -print " provisioning auth login " -print " provisioning kms encrypt " -print " provisioning orch status" diff --git a/plugins/install-plugins.nu b/plugins/install-plugins.nu deleted file mode 100644 index c97a138..0000000 --- a/plugins/install-plugins.nu +++ /dev/null @@ -1,321 +0,0 @@ -#!/usr/bin/env nu -# Install and register provisioning critical plugins -# -# This is the main user-facing script for installing the three critical -# provisioning plugins (auth, kms, orchestrator) that provide: -# - 10-50x performance improvement over HTTP API -# - OS-native keyring integration -# - Local file-based operations (no network required) -# -# Usage: -# nu install-plugins.nu # Build and install all plugins -# nu install-plugins.nu --skip-build # Register pre-built plugins only -# nu install-plugins.nu --release # Build release mode (default) -# nu install-plugins.nu --debug # Build debug mode -# nu install-plugins.nu --plugin auth # Install specific plugin only -# nu install-plugins.nu --verify # Verify after installation - -const PLUGIN_DIR = "nushell-plugins" - -const PROVISIONING_PLUGINS = [ - "nu_plugin_auth" - "nu_plugin_kms" - "nu_plugin_orchestrator" -] - -# Build a single plugin -def build-plugin [ - plugin_name: string - base_dir: path - --release -]: nothing -> record { - let plugin_path = ($base_dir | path join $PLUGIN_DIR $plugin_name) - - if not ($plugin_path | path exists) { - return { - name: $plugin_name - status: "not_found" - message: $"Plugin directory not found: ($plugin_path)" - } - } - - let build_mode = if $release { "--release" } else { "" } - let target_dir = if $release { "release" } else { "debug" } - - print $" Building ($plugin_name) \(($target_dir) mode\)..." - - let start_time = (date now) - - # Build the plugin - try { - cd $plugin_path - if $release { - cargo build --release - } else { - cargo build - } - cd - - - let duration = ((date now) - $start_time) | into int | $in / 1_000_000_000 - let binary_path = ($plugin_path | path join "target" $target_dir $plugin_name) - - if ($binary_path | path exists) { - return { - name: $plugin_name - status: "built" - message: $"Build successful \(($duration | math round --precision 1)s\)" - path: $binary_path - } - } else { - return { - name: $plugin_name - status: "error" - message: "Build completed but binary not found" - } - } - } catch { |err| - cd - - return { - name: $plugin_name - status: "error" - message: $"Build failed: ($err.msg)" - } - } -} - -# Register a plugin with Nushell -def register-plugin-binary [ - plugin_name: string - binary_path: path -]: nothing -> record { - if not ($binary_path | path exists) { - return { - name: $plugin_name - status: "not_found" - message: $"Binary not found: ($binary_path)" - } - } - - try { - plugin add $binary_path - - return { - name: $plugin_name - status: "registered" - message: "Registered successfully" - path: $binary_path - } - } catch { |err| - return { - name: $plugin_name - status: "error" - message: $"Registration failed: ($err.msg)" - } - } -} - -# Get binary path for a plugin -def get-binary-path [ - plugin_name: string - base_dir: path - --release -]: nothing -> path { - let target_dir = if ($release) { "release" } else { "debug" } - $base_dir | path join $PLUGIN_DIR $plugin_name "target" $target_dir $plugin_name -} - -# Print banner -def print-banner [] { - print "" - print "+======================================================+" - print "| Provisioning Platform - Plugin Installation |" - print "+======================================================+" - print "" - print "Installing critical plugins for optimal performance:" - print " - nu_plugin_auth: JWT auth with keyring (10x faster)" - print " - nu_plugin_kms: Multi-backend encryption (10x faster)" - print " - nu_plugin_orchestrator: Local operations (30x faster)" - print "" -} - -# Print summary -def print-summary [results: list] { - let built = ($results | where status == "built" | length) - let registered = ($results | where status == "registered" | length) - let errors = ($results | where status == "error" | length) - let skipped = ($results | where status in ["not_found" "already_registered"] | length) - - print "" - print "+------------------------------------------------------+" - print "| Installation Summary |" - print "+------------------------------------------------------+" - print "" - print $" Built: ($built)" - print $" Registered: ($registered)" - print $" Errors: ($errors)" - print $" Skipped: ($skipped)" - print "" - - if $errors > 0 { - print "Some plugins failed to install. Check errors above." - print "" - } -} - -# Main entry point -def main [ - --skip-build (-s) # Skip building, only register pre-built plugins - --release (-r) # Build in release mode (default) - --debug (-d) # Build in debug mode - --plugin (-p): string # Install specific plugin only - --verify (-v) # Verify installation after completion - --quiet (-q) # Suppress output -]: nothing -> nothing { - let base_dir = ($env.PWD | path dirname) # Go up from plugins/ to core/ - let use_release = not $debug - - # Determine which plugins to install - let plugins_to_install = if ($plugin != null) { - if $plugin in $PROVISIONING_PLUGINS { - [$plugin] - } else if $"nu_plugin_($plugin)" in $PROVISIONING_PLUGINS { - [$"nu_plugin_($plugin)"] - } else { - print $"Error: Unknown plugin '($plugin)'" - print $"Available: ($PROVISIONING_PLUGINS | str join ', ')" - exit 1 - } - } else { - $PROVISIONING_PLUGINS - } - - if not $quiet { - print-banner - } - - mut all_results = [] - - # Phase 1: Build (unless --skip-build) - if not $skip_build { - if not $quiet { - let mode = if $use_release { "release" } else { "debug" } - print $"Phase 1: Building plugins \(($mode) mode\)..." - print "" - } - - for plugin_name in $plugins_to_install { - let result = (build-plugin $plugin_name $base_dir --release=$use_release) - $all_results = ($all_results | append $result) - - if not $quiet { - match $result.status { - "built" => { - print $" [OK] ($result.message)" - } - "not_found" => { - print $" [SKIP] ($result.message)" - } - "error" => { - print $" [ERROR] ($result.message)" - } - _ => {} - } - } - } - - if not $quiet { - print "" - } - } - - # Phase 2: Register - if not $quiet { - print "Phase 2: Registering plugins with Nushell..." - print "" - } - - for plugin_name in $plugins_to_install { - let binary_path = (get-binary-path $plugin_name $base_dir --release=$use_release) - - if not $quiet { - print $" Registering ($plugin_name)..." - } - - let result = (register-plugin-binary $plugin_name $binary_path) - $all_results = ($all_results | append $result) - - if not $quiet { - match $result.status { - "registered" => { - print $" [OK] ($result.message)" - } - "not_found" => { - print $" [SKIP] ($result.message)" - } - "error" => { - print $" [ERROR] ($result.message)" - } - _ => {} - } - } - } - - if not $quiet { - print-summary $all_results - } - - # Phase 3: Verify (if requested) - if $verify { - if not $quiet { - print "Phase 3: Verifying installation..." - print "" - } - - let registered_plugins = (plugin list) - - for plugin_name in $plugins_to_install { - let is_registered = ($registered_plugins | where name == $plugin_name | length) > 0 - - if not $quiet { - if $is_registered { - print $" [OK] ($plugin_name) is registered" - } else { - print $" [FAIL] ($plugin_name) not found in plugin list" - } - } - } - - if not $quiet { - print "" - } - } - - if not $quiet { - print "Plugin commands now available:" - print "" - print " Authentication:" - print " auth login [password] # Login with JWT" - print " auth logout # End session" - print " auth verify # Check token" - print " auth sessions # List sessions" - print " auth mfa enroll totp # Setup MFA" - print " auth mfa verify --code 123456 # Verify MFA" - print "" - print " Encryption (KMS):" - print " kms encrypt \"data\" --backend age # Encrypt with Age" - print " kms decrypt \$encrypted # Decrypt data" - print " kms generate-key --spec AES256 # Generate key" - print " kms status # Check KMS status" - print " kms list-backends # Available backends" - print "" - print " Orchestrator:" - print " orch status # Local status (fast)" - print " orch tasks # List tasks" - print " orch validate workflow.k # Validate KCL" - print " orch submit workflow.k # Submit workflow" - print " orch monitor # Monitor task" - print "" - print "Verify installation with: plugin list" - print "" - } -} diff --git a/plugins/register-plugins.nu b/plugins/register-plugins.nu deleted file mode 100644 index 36e13aa..0000000 --- a/plugins/register-plugins.nu +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/bin/env nu -# Register provisioning plugins with Nushell - -# Detect plugin directory -let plugin_dir = ($env.HOME + "/.local/share/nushell/plugins") - -print $"Using plugin directory: ($plugin_dir)" - -# Create plugin directory if it doesn't exist -if not ($plugin_dir | path exists) { - mkdir $plugin_dir -} - -# Define plugins to register -let plugins = [ - { - name: "nu_plugin_auth" - src: "provisioning/core/plugins/nushell-plugins/nu_plugin_auth/target/release/nu_plugin_auth" - description: "JWT authentication with system keyring" - } - { - name: "nu_plugin_kms" - src: "provisioning/core/plugins/nushell-plugins/nu_plugin_kms/target/release/nu_plugin_kms" - description: "Multi-backend KMS encryption" - } - { - name: "nu_plugin_orchestrator" - src: "provisioning/core/plugins/nushell-plugins/nu_plugin_orchestrator/target/release/nu_plugin_orchestrator" - description: "Local orchestrator operations (30x faster)" - } -] - -# Copy plugins -print "" -print "Installing plugins..." -print "====================" - -let result = ( - $plugins - | each { |plugin| - let src = $plugin.src - let dst = ($plugin_dir + "/" + $plugin.name) - - if not ($src | path exists) { - { - name: $plugin.name - success: false - message: $"Source not found at ($src)" - } - } else { - cp $src $dst - chmod +x $dst - if ($dst | path exists) { - { - name: $plugin.name - success: true - message: $"Installed to ($dst)" - } - } else { - { - name: $plugin.name - success: false - message: "Failed to copy" - } - } - } - } -) - -# Print results -for item in $result { - let icon = if $item.success { "✓" } else { "✗" } - print $"($icon) ($item.name): ($item.message)" -} - -let installed = ($result | where success == true | length) -let failed = ($result | where success == false | length) - -print "" -print $"Results: ($installed) installed, ($failed) failed" - -# Suggest next steps -if $installed > 0 { - print "" - print "Next steps:" - print "===========" - print "Run the following command in a new Nushell session:" - print "" - for plugin in $plugins { - let dst = ($plugin_dir + "/" + $plugin.name) - print $" plugin add ($dst)" - } -} diff --git a/plugins/test-plugins.nu b/plugins/test-plugins.nu deleted file mode 100644 index 259ceec..0000000 --- a/plugins/test-plugins.nu +++ /dev/null @@ -1,264 +0,0 @@ -#!/usr/bin/env nu -# Test provisioning plugins are installed and working -# -# This script verifies that the three critical provisioning plugins -# are properly installed, registered, and functional. -# -# Usage: -# nu test-plugins.nu # Run all tests -# nu test-plugins.nu --quick # Quick registration check only -# nu test-plugins.nu --verbose # Detailed output -# nu test-plugins.nu --json # Output as JSON - -const PROVISIONING_PLUGINS = [ - { - name: "nu_plugin_auth" - test_command: "auth verify --local" - expected_fields: ["valid"] - description: "JWT authentication with system keyring" - } - { - name: "nu_plugin_kms" - test_command: "kms status" - expected_fields: ["backend", "available"] - description: "Multi-backend KMS encryption" - } - { - name: "nu_plugin_orchestrator" - test_command: "orch status" - expected_fields: ["running", "tasks_pending"] - description: "Local orchestrator operations" - } -] - -# Check if plugin is registered -def check-registration [plugin_name: string]: nothing -> record { - let registered_plugins = (plugin list | get name?) - - if ($registered_plugins == null) { - return { - name: $plugin_name - registered: false - message: "Could not query plugin list" - } - } - - let is_registered = $plugin_name in $registered_plugins - - { - name: $plugin_name - registered: $is_registered - message: (if $is_registered { "Registered" } else { "Not registered" }) - } -} - -# Test plugin functionality -def test-plugin-function [ - plugin_name: string - test_command: string - expected_fields: list -]: nothing -> record { - let start_time = (date now) - - try { - # Execute the test command - let result = (nu -c $test_command | from json) - let duration = ((date now) - $start_time) | into int | $in / 1_000_000 - - # Check if expected fields exist - let missing_fields = ($expected_fields | where { |field| - not ($field in ($result | columns)) - }) - - if ($missing_fields | length) > 0 { - return { - name: $plugin_name - functional: false - message: $"Missing fields: ($missing_fields | str join ', ')" - duration_ms: $duration - } - } - - { - name: $plugin_name - functional: true - message: "Commands working" - duration_ms: $duration - result: $result - } - } catch { |err| - let duration = ((date now) - $start_time) | into int | $in / 1_000_000 - - # Some commands might return errors but still work (e.g., no token) - # This is expected behavior, not a failure - if ($err.msg | str contains "not logged in") or - ($err.msg | str contains "token not found") or - ($err.msg | str contains "No sessions") { - return { - name: $plugin_name - functional: true - message: "Commands working (expected auth state)" - duration_ms: $duration - } - } - - { - name: $plugin_name - functional: false - message: $"Error: ($err.msg)" - duration_ms: $duration - } - } -} - -# Run all tests -def run-tests [ - --quick: bool = false - --verbose: bool = false -]: nothing -> list { - mut results = [] - - for plugin in $PROVISIONING_PLUGINS { - # Registration check - let reg_result = (check-registration $plugin.name) - $results = ($results | append { - plugin: $plugin.name - test: "registration" - passed: $reg_result.registered - message: $reg_result.message - duration_ms: 0 - }) - - if $verbose { - let status = if $reg_result.registered { "[PASS]" } else { "[FAIL]" } - print $"($status) ($plugin.name) - Registration: ($reg_result.message)" - } - - # Skip functional tests if quick mode or not registered - if $quick or (not $reg_result.registered) { - continue - } - - # Functional test - let func_result = (test-plugin-function $plugin.name $plugin.test_command $plugin.expected_fields) - $results = ($results | append { - plugin: $plugin.name - test: "functional" - passed: $func_result.functional - message: $func_result.message - duration_ms: $func_result.duration_ms - }) - - if $verbose { - let status = if $func_result.functional { "[PASS]" } else { "[FAIL]" } - print $"($status) ($plugin.name) - Functional: ($func_result.message) \(($func_result.duration_ms)ms\)" - } - } - - $results -} - -# Main entry point -def main [ - --quick (-q) # Quick registration check only - --verbose (-v) # Detailed output - --json (-j) # Output as JSON -]: nothing -> nothing { - if not $json { - print "" - print "======================================================" - print " Provisioning Plugins Test Suite" - print "======================================================" - print "" - } - - let results = (run-tests --quick=$quick --verbose=$verbose) - - # Calculate summary - let total_tests = ($results | length) - let passed_tests = ($results | where passed == true | length) - let failed_tests = ($results | where passed == false | length) - - # Registration summary - let reg_results = ($results | where test == "registration") - let reg_passed = ($reg_results | where passed == true | length) - let reg_total = ($reg_results | length) - - # Functional summary - let func_results = ($results | where test == "functional") - let func_passed = ($func_results | where passed == true | length) - let func_total = ($func_results | length) - - if $json { - # JSON output - { - total: $total_tests - passed: $passed_tests - failed: $failed_tests - registration: { - total: $reg_total - passed: $reg_passed - } - functional: { - total: $func_total - passed: $func_passed - } - results: $results - all_passed: ($failed_tests == 0) - } | to json - } else { - # Human-readable output - if not $verbose { - # Print results table - print "Test Results:" - print "" - - for result in $results { - let status = if $result.passed { "[OK] " } else { "[FAIL]" } - let test_type = if $result.test == "registration" { "reg" } else { "func" } - let duration = if $result.duration_ms > 0 { - $" \(($result.duration_ms)ms\)" - } else { - "" - } - print $" ($status) ($result.plugin | fill -w 25) ($test_type | fill -w 5) ($result.message)($duration)" - } - } - - print "" - print "------------------------------------------------------" - print "Summary:" - print $" Registration: ($reg_passed)/($reg_total) passed" - - if not $quick { - print $" Functional: ($func_passed)/($func_total) passed" - } - - print $" Total: ($passed_tests)/($total_tests) passed" - print "------------------------------------------------------" - print "" - - if $failed_tests == 0 { - print "All tests passed! Plugins are ready to use." - } else { - print $"($failed_tests) test\(s\) failed. Some plugins may need attention." - print "" - print "Troubleshooting:" - print " 1. Build plugins: nu install-plugins.nu" - print " 2. Register only: nu install-plugins.nu --skip-build" - print " 3. Check plugin list: plugin list" - } - - print "" - } - - # Exit with error code if tests failed - if $failed_tests > 0 { - exit 1 - } -} - -# Export for module usage -export def "provisioning-plugins test" [--quick (-q), --verbose (-v), --json (-j)] { - main --quick=$quick --verbose=$verbose --json=$json -} diff --git a/versions.k b/versions.k deleted file mode 100644 index 2cf628f..0000000 --- a/versions.k +++ /dev/null @@ -1,101 +0,0 @@ -import provisioning.version as prv_schema - -# Core tools versions for provisioning system as array -# Converted from individual declarations to array of TaskservVersion items -core_versions: [prv_schema.TaskservVersion] = [ - prv_schema.TaskservVersion { - name = "nushell" - version = prv_schema.Version { - current = "0.109.1" - source = "https://github.com/nushell/nushell/releases" - tags = "https://github.com/nushell/nushell/tags" - site = "https://www.nushell.sh/" - # Pinned for system stability - check_latest = False - grace_period = 86400 - } - dependencies = [] - detector = { - method = "command" - command = "nu -v" - pattern = r"(?P[\d.]+\.[\d.]+)" - capture = "capture0" - } - } - prv_schema.TaskservVersion { - name = "kcl" - version = prv_schema.Version { - current = "0.11.3" - source = "https://github.com/kcl-lang/cli/releases" - tags = "https://github.com/kcl-lang/cli/tags" - site = "https://kcl-lang.io" - # Pinned for system stability - check_latest = False - grace_period = 86400 - } - dependencies = [] - detector = { - method = "command" - command = "kcl -v" - pattern = r"kcl\s+version\s+(?P[\d.]+)" - capture = "capture0" - } - } - prv_schema.TaskservVersion { - name = "sops" - version = prv_schema.Version { - current = "3.10.2" - source = "https://github.com/getsops/sops/releases" - tags = "https://github.com/getsops/sops/tags" - site = "https://github.com/getsops/sops" - # Pinned for encryption compatibility - check_latest = False - grace_period = 86400 - } - dependencies = ["age"] - detector = { - method = "command" - command = "sops -v" - pattern = r"sops\s+(?P[\d.]+)" - capture = "capture0" - } - } - prv_schema.TaskservVersion { - name = "age" - version = prv_schema.Version { - current = "1.2.1" - source = "https://github.com/FiloSottile/age/releases" - tags = "https://github.com/FiloSottile/age/tags" - site = "https://github.com/FiloSottile/age" - # Pinned for encryption compatibility - check_latest = False - grace_period = 86400 - } - dependencies = [] - detector = { - method = "command" - command = "age --version" - pattern = r"v(?P[\d.]+)" - capture = "capture0" - } - } - prv_schema.TaskservVersion { - name = "k9s" - version = prv_schema.Version { - current = "0.50.6" - source = "https://github.com/derailed/k9s/releases" - tags = "https://github.com/derailed/k9s/tags" - site = "https://k9scli.io/" - # Can auto-update for CLI tools - check_latest = True - grace_period = 86400 - } - dependencies = [] - detector = { - method = "command" - command = "k9s version" - pattern = r"Version\s+v(?P[\d.]+)" - capture = "capture0" - } - } -]