pvectl 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.claude/rules/branch-before-changes.md +52 -0
- data/.claude/rules/documentation-updates.md +104 -0
- data/.claude/rules/git-workflow.md +84 -0
- data/.claude/rules/proxmox-api-docs.md +58 -0
- data/.claude/rules/rbs-signatures.md +80 -0
- data/.claude/rules/refactoring-as-design-option.md +35 -0
- data/.claude/scheduled_tasks.lock +1 -0
- data/.claude/settings.json +51 -0
- data/.mcp.json +8 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +138 -0
- data/CLAUDE.md +211 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/LICENSE.txt +21 -0
- data/README.md +143 -0
- data/Rakefile +8 -0
- data/docs/proxmox-api-update.sh +96 -0
- data/exe/pvectl +5 -0
- data/lib/pvectl/argv_preprocessor.rb +334 -0
- data/lib/pvectl/cli.rb +102 -0
- data/lib/pvectl/commands/apt.rb +389 -0
- data/lib/pvectl/commands/clone_container.rb +230 -0
- data/lib/pvectl/commands/clone_vm.rb +331 -0
- data/lib/pvectl/commands/cloudinit/command.rb +122 -0
- data/lib/pvectl/commands/cloudinit/dump.rb +94 -0
- data/lib/pvectl/commands/cloudinit/pending.rb +137 -0
- data/lib/pvectl/commands/cloudinit/regenerate.rb +79 -0
- data/lib/pvectl/commands/config/command.rb +65 -0
- data/lib/pvectl/commands/config/get_contexts.rb +68 -0
- data/lib/pvectl/commands/config/set_cluster.rb +103 -0
- data/lib/pvectl/commands/config/set_context.rb +136 -0
- data/lib/pvectl/commands/config/set_credentials.rb +181 -0
- data/lib/pvectl/commands/config/use_context.rb +69 -0
- data/lib/pvectl/commands/config/view.rb +67 -0
- data/lib/pvectl/commands/console.rb +93 -0
- data/lib/pvectl/commands/console_ct.rb +187 -0
- data/lib/pvectl/commands/console_vm.rb +187 -0
- data/lib/pvectl/commands/container_lifecycle_command.rb +77 -0
- data/lib/pvectl/commands/create_backup.rb +173 -0
- data/lib/pvectl/commands/create_container.rb +141 -0
- data/lib/pvectl/commands/create_resource_command.rb +244 -0
- data/lib/pvectl/commands/create_snapshot.rb +242 -0
- data/lib/pvectl/commands/create_vm.rb +267 -0
- data/lib/pvectl/commands/delete_backup.rb +139 -0
- data/lib/pvectl/commands/delete_command.rb +119 -0
- data/lib/pvectl/commands/delete_container.rb +30 -0
- data/lib/pvectl/commands/delete_snapshot.rb +248 -0
- data/lib/pvectl/commands/delete_vm.rb +127 -0
- data/lib/pvectl/commands/describe/command.rb +251 -0
- data/lib/pvectl/commands/edit_container.rb +56 -0
- data/lib/pvectl/commands/edit_dns.rb +149 -0
- data/lib/pvectl/commands/edit_hosts.rb +135 -0
- data/lib/pvectl/commands/edit_node.rb +54 -0
- data/lib/pvectl/commands/edit_resource_command.rb +180 -0
- data/lib/pvectl/commands/edit_vm.rb +154 -0
- data/lib/pvectl/commands/edit_volume.rb +189 -0
- data/lib/pvectl/commands/feature_command.rb +230 -0
- data/lib/pvectl/commands/feature_container.rb +21 -0
- data/lib/pvectl/commands/feature_vm.rb +94 -0
- data/lib/pvectl/commands/get/command.rb +360 -0
- data/lib/pvectl/commands/get/handlers/backups.rb +76 -0
- data/lib/pvectl/commands/get/handlers/capabilities.rb +107 -0
- data/lib/pvectl/commands/get/handlers/containers.rb +148 -0
- data/lib/pvectl/commands/get/handlers/disks.rb +107 -0
- data/lib/pvectl/commands/get/handlers/dns.rb +94 -0
- data/lib/pvectl/commands/get/handlers/hosts.rb +94 -0
- data/lib/pvectl/commands/get/handlers/nodes.rb +162 -0
- data/lib/pvectl/commands/get/handlers/services.rb +81 -0
- data/lib/pvectl/commands/get/handlers/snapshots.rb +97 -0
- data/lib/pvectl/commands/get/handlers/storage.rb +118 -0
- data/lib/pvectl/commands/get/handlers/subscription.rb +69 -0
- data/lib/pvectl/commands/get/handlers/tasks.rb +89 -0
- data/lib/pvectl/commands/get/handlers/templates.rb +175 -0
- data/lib/pvectl/commands/get/handlers/time.rb +118 -0
- data/lib/pvectl/commands/get/handlers/vms.rb +145 -0
- data/lib/pvectl/commands/get/handlers/volume.rb +134 -0
- data/lib/pvectl/commands/get/resource_handler.rb +63 -0
- data/lib/pvectl/commands/get/resource_registry.rb +18 -0
- data/lib/pvectl/commands/get/watch_loop.rb +129 -0
- data/lib/pvectl/commands/irreversible_command.rb +265 -0
- data/lib/pvectl/commands/logs/command.rb +275 -0
- data/lib/pvectl/commands/logs/handlers/journal.rb +46 -0
- data/lib/pvectl/commands/logs/handlers/syslog.rb +53 -0
- data/lib/pvectl/commands/logs/handlers/task_detail.rb +52 -0
- data/lib/pvectl/commands/logs/handlers/task_logs.rb +115 -0
- data/lib/pvectl/commands/logs/resource_handler.rb +46 -0
- data/lib/pvectl/commands/logs/resource_registry.rb +22 -0
- data/lib/pvectl/commands/migrate_command.rb +282 -0
- data/lib/pvectl/commands/migrate_container.rb +23 -0
- data/lib/pvectl/commands/migrate_vm.rb +122 -0
- data/lib/pvectl/commands/move_disk_command.rb +239 -0
- data/lib/pvectl/commands/move_disk_container.rb +21 -0
- data/lib/pvectl/commands/move_disk_vm.rb +127 -0
- data/lib/pvectl/commands/ping.rb +249 -0
- data/lib/pvectl/commands/pull.rb +342 -0
- data/lib/pvectl/commands/push.rb +352 -0
- data/lib/pvectl/commands/reset.rb +64 -0
- data/lib/pvectl/commands/resource_lifecycle_command.rb +277 -0
- data/lib/pvectl/commands/resource_registry.rb +73 -0
- data/lib/pvectl/commands/restart.rb +70 -0
- data/lib/pvectl/commands/restart_container.rb +18 -0
- data/lib/pvectl/commands/restore_backup.rb +236 -0
- data/lib/pvectl/commands/resume.rb +57 -0
- data/lib/pvectl/commands/rollback_snapshot.rb +228 -0
- data/lib/pvectl/commands/sendkey_vm.rb +205 -0
- data/lib/pvectl/commands/service.rb +293 -0
- data/lib/pvectl/commands/set_container.rb +50 -0
- data/lib/pvectl/commands/set_node.rb +52 -0
- data/lib/pvectl/commands/set_resource_command.rb +185 -0
- data/lib/pvectl/commands/set_vm.rb +136 -0
- data/lib/pvectl/commands/set_volume.rb +212 -0
- data/lib/pvectl/commands/shared_config_parsers.rb +126 -0
- data/lib/pvectl/commands/shared_flags.rb +155 -0
- data/lib/pvectl/commands/shutdown.rb +73 -0
- data/lib/pvectl/commands/shutdown_container.rb +18 -0
- data/lib/pvectl/commands/start.rb +79 -0
- data/lib/pvectl/commands/start_container.rb +18 -0
- data/lib/pvectl/commands/stop.rb +75 -0
- data/lib/pvectl/commands/stop_container.rb +18 -0
- data/lib/pvectl/commands/suspend.rb +64 -0
- data/lib/pvectl/commands/template_command.rb +205 -0
- data/lib/pvectl/commands/template_container.rb +27 -0
- data/lib/pvectl/commands/template_vm.rb +106 -0
- data/lib/pvectl/commands/top/command.rb +206 -0
- data/lib/pvectl/commands/top/handlers/containers.rb +61 -0
- data/lib/pvectl/commands/top/handlers/nodes.rb +61 -0
- data/lib/pvectl/commands/top/handlers/vms.rb +61 -0
- data/lib/pvectl/commands/top/resource_handler.rb +46 -0
- data/lib/pvectl/commands/top/resource_registry.rb +22 -0
- data/lib/pvectl/commands/unlink_disk_vm.rb +232 -0
- data/lib/pvectl/commands/vm_lifecycle_command.rb +77 -0
- data/lib/pvectl/commands/wakeonlan_node.rb +153 -0
- data/lib/pvectl/config/errors.rb +62 -0
- data/lib/pvectl/config/models/cluster.rb +180 -0
- data/lib/pvectl/config/models/context.rb +100 -0
- data/lib/pvectl/config/models/resolved_config.rb +171 -0
- data/lib/pvectl/config/models/user.rb +133 -0
- data/lib/pvectl/config/provider.rb +297 -0
- data/lib/pvectl/config/service.rb +300 -0
- data/lib/pvectl/config/store.rb +161 -0
- data/lib/pvectl/config/wizard.rb +309 -0
- data/lib/pvectl/config_serializer.rb +1034 -0
- data/lib/pvectl/connection/retry_handler.rb +161 -0
- data/lib/pvectl/connection.rb +157 -0
- data/lib/pvectl/console/terminal_session.rb +449 -0
- data/lib/pvectl/editor_session.rb +157 -0
- data/lib/pvectl/exit_codes.rb +43 -0
- data/lib/pvectl/formatters/base.rb +55 -0
- data/lib/pvectl/formatters/color_support.rb +90 -0
- data/lib/pvectl/formatters/json.rb +45 -0
- data/lib/pvectl/formatters/output_helper.rb +77 -0
- data/lib/pvectl/formatters/registry.rb +72 -0
- data/lib/pvectl/formatters/table.rb +235 -0
- data/lib/pvectl/formatters/wide.rb +93 -0
- data/lib/pvectl/formatters/yaml.rb +49 -0
- data/lib/pvectl/manifest_serializer.rb +142 -0
- data/lib/pvectl/models/apt_package.rb +107 -0
- data/lib/pvectl/models/backup.rb +173 -0
- data/lib/pvectl/models/base.rb +49 -0
- data/lib/pvectl/models/capability.rb +62 -0
- data/lib/pvectl/models/container.rb +205 -0
- data/lib/pvectl/models/container_operation_result.rb +27 -0
- data/lib/pvectl/models/dns_config.rb +54 -0
- data/lib/pvectl/models/hosts_file.rb +47 -0
- data/lib/pvectl/models/journal_entry.rb +16 -0
- data/lib/pvectl/models/network_interface.rb +85 -0
- data/lib/pvectl/models/node.rb +195 -0
- data/lib/pvectl/models/node_operation_result.rb +45 -0
- data/lib/pvectl/models/operation_result.rb +110 -0
- data/lib/pvectl/models/physical_disk.rb +193 -0
- data/lib/pvectl/models/service.rb +80 -0
- data/lib/pvectl/models/snapshot.rb +101 -0
- data/lib/pvectl/models/snapshot_description.rb +39 -0
- data/lib/pvectl/models/storage.rb +180 -0
- data/lib/pvectl/models/subscription.rb +87 -0
- data/lib/pvectl/models/syslog_entry.rb +17 -0
- data/lib/pvectl/models/task.rb +95 -0
- data/lib/pvectl/models/task_entry.rb +52 -0
- data/lib/pvectl/models/task_log_line.rb +17 -0
- data/lib/pvectl/models/time_config.rb +47 -0
- data/lib/pvectl/models/vm.rb +137 -0
- data/lib/pvectl/models/vm_operation_result.rb +27 -0
- data/lib/pvectl/models/volume.rb +133 -0
- data/lib/pvectl/models/volume_operation_result.rb +26 -0
- data/lib/pvectl/parsers/cloud_init_config.rb +92 -0
- data/lib/pvectl/parsers/disk_config.rb +97 -0
- data/lib/pvectl/parsers/lxc_mount_config.rb +98 -0
- data/lib/pvectl/parsers/lxc_net_config.rb +97 -0
- data/lib/pvectl/parsers/net_config.rb +95 -0
- data/lib/pvectl/parsers/smart_text.rb +42 -0
- data/lib/pvectl/plugin_loader.rb +157 -0
- data/lib/pvectl/presenters/apt_package.rb +99 -0
- data/lib/pvectl/presenters/backup.rb +128 -0
- data/lib/pvectl/presenters/base.rb +283 -0
- data/lib/pvectl/presenters/capability.rb +104 -0
- data/lib/pvectl/presenters/config/context.rb +80 -0
- data/lib/pvectl/presenters/container.rb +574 -0
- data/lib/pvectl/presenters/container_operation_result.rb +109 -0
- data/lib/pvectl/presenters/disk.rb +184 -0
- data/lib/pvectl/presenters/dns_config.rb +68 -0
- data/lib/pvectl/presenters/hosts_file.rb +61 -0
- data/lib/pvectl/presenters/journal_entry.rb +20 -0
- data/lib/pvectl/presenters/node.rb +762 -0
- data/lib/pvectl/presenters/node_operation_result.rb +50 -0
- data/lib/pvectl/presenters/operation_result.rb +61 -0
- data/lib/pvectl/presenters/service.rb +76 -0
- data/lib/pvectl/presenters/snapshot.rb +239 -0
- data/lib/pvectl/presenters/snapshot_operation_result.rb +125 -0
- data/lib/pvectl/presenters/storage.rb +329 -0
- data/lib/pvectl/presenters/subscription.rb +189 -0
- data/lib/pvectl/presenters/syslog_entry.rb +20 -0
- data/lib/pvectl/presenters/task_entry.rb +69 -0
- data/lib/pvectl/presenters/task_log_line.rb +20 -0
- data/lib/pvectl/presenters/template.rb +76 -0
- data/lib/pvectl/presenters/time_config.rb +86 -0
- data/lib/pvectl/presenters/top_container.rb +112 -0
- data/lib/pvectl/presenters/top_node.rb +115 -0
- data/lib/pvectl/presenters/top_presenter.rb +59 -0
- data/lib/pvectl/presenters/top_vm.rb +105 -0
- data/lib/pvectl/presenters/vm.rb +853 -0
- data/lib/pvectl/presenters/vm_operation_result.rb +109 -0
- data/lib/pvectl/presenters/volume.rb +136 -0
- data/lib/pvectl/presenters/volume_operation_result.rb +58 -0
- data/lib/pvectl/repositories/apt.rb +93 -0
- data/lib/pvectl/repositories/backup.rb +186 -0
- data/lib/pvectl/repositories/base.rb +110 -0
- data/lib/pvectl/repositories/capabilities.rb +96 -0
- data/lib/pvectl/repositories/container.rb +503 -0
- data/lib/pvectl/repositories/disk.rb +87 -0
- data/lib/pvectl/repositories/dns.rb +54 -0
- data/lib/pvectl/repositories/hosts.rb +63 -0
- data/lib/pvectl/repositories/journal.rb +23 -0
- data/lib/pvectl/repositories/node.rb +537 -0
- data/lib/pvectl/repositories/service.rb +139 -0
- data/lib/pvectl/repositories/snapshot.rb +133 -0
- data/lib/pvectl/repositories/storage.rb +302 -0
- data/lib/pvectl/repositories/subscription.rb +77 -0
- data/lib/pvectl/repositories/syslog.rb +25 -0
- data/lib/pvectl/repositories/task.rb +82 -0
- data/lib/pvectl/repositories/task_list.rb +30 -0
- data/lib/pvectl/repositories/task_log.rb +31 -0
- data/lib/pvectl/repositories/time_config.rb +53 -0
- data/lib/pvectl/repositories/vm.rb +616 -0
- data/lib/pvectl/repositories/volume.rb +306 -0
- data/lib/pvectl/selectors/base.rb +201 -0
- data/lib/pvectl/selectors/container.rb +116 -0
- data/lib/pvectl/selectors/disk.rb +59 -0
- data/lib/pvectl/selectors/vm.rb +116 -0
- data/lib/pvectl/selectors/volume.rb +59 -0
- data/lib/pvectl/services/backup.rb +209 -0
- data/lib/pvectl/services/clone_container.rb +260 -0
- data/lib/pvectl/services/clone_vm.rb +265 -0
- data/lib/pvectl/services/cloudinit.rb +96 -0
- data/lib/pvectl/services/console.rb +152 -0
- data/lib/pvectl/services/container_lifecycle.rb +124 -0
- data/lib/pvectl/services/create_container.rb +179 -0
- data/lib/pvectl/services/create_vm.rb +191 -0
- data/lib/pvectl/services/edit_container.rb +125 -0
- data/lib/pvectl/services/edit_dns.rb +159 -0
- data/lib/pvectl/services/edit_hosts.rb +78 -0
- data/lib/pvectl/services/edit_node.rb +147 -0
- data/lib/pvectl/services/edit_vm.rb +125 -0
- data/lib/pvectl/services/edit_volume.rb +224 -0
- data/lib/pvectl/services/get/resource_service.rb +98 -0
- data/lib/pvectl/services/move_disk.rb +132 -0
- data/lib/pvectl/services/pull_config.rb +94 -0
- data/lib/pvectl/services/push_config.rb +524 -0
- data/lib/pvectl/services/resize_volume.rb +253 -0
- data/lib/pvectl/services/resource_delete.rb +169 -0
- data/lib/pvectl/services/resource_migration.rb +170 -0
- data/lib/pvectl/services/sendkey.rb +108 -0
- data/lib/pvectl/services/service_lifecycle.rb +89 -0
- data/lib/pvectl/services/set_container.rb +128 -0
- data/lib/pvectl/services/set_node.rb +236 -0
- data/lib/pvectl/services/set_vm.rb +128 -0
- data/lib/pvectl/services/set_volume.rb +126 -0
- data/lib/pvectl/services/snapshot.rb +261 -0
- data/lib/pvectl/services/task_listing.rb +75 -0
- data/lib/pvectl/services/unlink_disk.rb +86 -0
- data/lib/pvectl/services/vm_lifecycle.rb +124 -0
- data/lib/pvectl/services/wakeonlan.rb +79 -0
- data/lib/pvectl/utils/resource_resolver.rb +80 -0
- data/lib/pvectl/version.rb +13 -0
- data/lib/pvectl/wizards/create_container.rb +105 -0
- data/lib/pvectl/wizards/create_vm.rb +98 -0
- data/lib/pvectl.rb +439 -0
- data/sig/external/gli.rbs +16 -0
- data/sig/external/proxmox_api.rbs +10 -0
- data/sig/pvectl/argv_preprocessor.rbs +53 -0
- data/sig/pvectl/cli.rbs +26 -0
- data/sig/pvectl/commands/apt.rbs +47 -0
- data/sig/pvectl/commands/clone_container.rbs +31 -0
- data/sig/pvectl/commands/clone_vm.rbs +33 -0
- data/sig/pvectl/commands/cloudinit/command.rbs +13 -0
- data/sig/pvectl/commands/cloudinit/dump.rbs +13 -0
- data/sig/pvectl/commands/cloudinit/pending.rbs +17 -0
- data/sig/pvectl/commands/cloudinit/regenerate.rbs +11 -0
- data/sig/pvectl/commands/config/command.rbs +9 -0
- data/sig/pvectl/commands/config/get_contexts.rbs +11 -0
- data/sig/pvectl/commands/config/set_cluster.rbs +11 -0
- data/sig/pvectl/commands/config/set_context.rbs +15 -0
- data/sig/pvectl/commands/config/set_credentials.rbs +15 -0
- data/sig/pvectl/commands/config/use_context.rbs +11 -0
- data/sig/pvectl/commands/config/view.rbs +11 -0
- data/sig/pvectl/commands/console.rbs +9 -0
- data/sig/pvectl/commands/console_ct.rbs +27 -0
- data/sig/pvectl/commands/console_vm.rbs +27 -0
- data/sig/pvectl/commands/container_lifecycle_command.rbs +25 -0
- data/sig/pvectl/commands/create_backup.rbs +29 -0
- data/sig/pvectl/commands/create_container.rbs +30 -0
- data/sig/pvectl/commands/create_resource_command.rbs +53 -0
- data/sig/pvectl/commands/create_snapshot.rbs +35 -0
- data/sig/pvectl/commands/create_vm.rbs +30 -0
- data/sig/pvectl/commands/delete_backup.rbs +25 -0
- data/sig/pvectl/commands/delete_command.rbs +45 -0
- data/sig/pvectl/commands/delete_container.rbs +11 -0
- data/sig/pvectl/commands/delete_snapshot.rbs +35 -0
- data/sig/pvectl/commands/delete_vm.rbs +13 -0
- data/sig/pvectl/commands/describe/command.rbs +27 -0
- data/sig/pvectl/commands/edit_container.rbs +17 -0
- data/sig/pvectl/commands/edit_dns.rbs +25 -0
- data/sig/pvectl/commands/edit_hosts.rbs +23 -0
- data/sig/pvectl/commands/edit_node.rbs +17 -0
- data/sig/pvectl/commands/edit_resource_command.rbs +35 -0
- data/sig/pvectl/commands/edit_vm.rbs +19 -0
- data/sig/pvectl/commands/edit_volume.rbs +24 -0
- data/sig/pvectl/commands/feature_command.rbs +43 -0
- data/sig/pvectl/commands/feature_container.rbs +10 -0
- data/sig/pvectl/commands/feature_vm.rbs +12 -0
- data/sig/pvectl/commands/get/command.rbs +42 -0
- data/sig/pvectl/commands/get/handlers/backups.rbs +23 -0
- data/sig/pvectl/commands/get/handlers/capabilities.rbs +29 -0
- data/sig/pvectl/commands/get/handlers/containers.rbs +35 -0
- data/sig/pvectl/commands/get/handlers/disks.rbs +27 -0
- data/sig/pvectl/commands/get/handlers/dns.rbs +25 -0
- data/sig/pvectl/commands/get/handlers/hosts.rbs +25 -0
- data/sig/pvectl/commands/get/handlers/nodes.rbs +33 -0
- data/sig/pvectl/commands/get/handlers/services.rbs +23 -0
- data/sig/pvectl/commands/get/handlers/snapshots.rbs +27 -0
- data/sig/pvectl/commands/get/handlers/storage.rbs +25 -0
- data/sig/pvectl/commands/get/handlers/subscription.rbs +25 -0
- data/sig/pvectl/commands/get/handlers/tasks.rbs +28 -0
- data/sig/pvectl/commands/get/handlers/templates.rbs +35 -0
- data/sig/pvectl/commands/get/handlers/time.rbs +29 -0
- data/sig/pvectl/commands/get/handlers/vms.rbs +35 -0
- data/sig/pvectl/commands/get/handlers/volume.rbs +27 -0
- data/sig/pvectl/commands/get/resource_handler.rbs +13 -0
- data/sig/pvectl/commands/get/resource_registry.rbs +8 -0
- data/sig/pvectl/commands/get/watch_loop.rbs +33 -0
- data/sig/pvectl/commands/irreversible_command.rbs +32 -0
- data/sig/pvectl/commands/logs/command.rbs +35 -0
- data/sig/pvectl/commands/logs/handlers/journal.rbs +21 -0
- data/sig/pvectl/commands/logs/handlers/syslog.rbs +21 -0
- data/sig/pvectl/commands/logs/handlers/task_detail.rbs +21 -0
- data/sig/pvectl/commands/logs/handlers/task_logs.rbs +35 -0
- data/sig/pvectl/commands/logs/resource_handler.rbs +11 -0
- data/sig/pvectl/commands/logs/resource_registry.rbs +8 -0
- data/sig/pvectl/commands/migrate_command.rbs +45 -0
- data/sig/pvectl/commands/migrate_container.rbs +11 -0
- data/sig/pvectl/commands/migrate_vm.rbs +13 -0
- data/sig/pvectl/commands/move_disk_command.rbs +43 -0
- data/sig/pvectl/commands/move_disk_container.rbs +11 -0
- data/sig/pvectl/commands/move_disk_vm.rbs +13 -0
- data/sig/pvectl/commands/ping.rbs +39 -0
- data/sig/pvectl/commands/pull.rbs +33 -0
- data/sig/pvectl/commands/push.rbs +32 -0
- data/sig/pvectl/commands/reset.rbs +11 -0
- data/sig/pvectl/commands/resource_lifecycle_command.rbs +55 -0
- data/sig/pvectl/commands/resource_registry.rbs +19 -0
- data/sig/pvectl/commands/restart.rbs +11 -0
- data/sig/pvectl/commands/restart_container.rbs +9 -0
- data/sig/pvectl/commands/restore_backup.rbs +27 -0
- data/sig/pvectl/commands/resume.rbs +11 -0
- data/sig/pvectl/commands/rollback_snapshot.rbs +31 -0
- data/sig/pvectl/commands/sendkey_vm.rbs +25 -0
- data/sig/pvectl/commands/service.rbs +38 -0
- data/sig/pvectl/commands/set_container.rbs +13 -0
- data/sig/pvectl/commands/set_node.rbs +13 -0
- data/sig/pvectl/commands/set_resource_command.rbs +25 -0
- data/sig/pvectl/commands/set_vm.rbs +15 -0
- data/sig/pvectl/commands/set_volume.rbs +24 -0
- data/sig/pvectl/commands/shared_config_parsers.rbs +19 -0
- data/sig/pvectl/commands/shared_flags.rbs +10 -0
- data/sig/pvectl/commands/shutdown.rbs +11 -0
- data/sig/pvectl/commands/shutdown_container.rbs +9 -0
- data/sig/pvectl/commands/start.rbs +11 -0
- data/sig/pvectl/commands/start_container.rbs +9 -0
- data/sig/pvectl/commands/stop.rbs +11 -0
- data/sig/pvectl/commands/stop_container.rbs +9 -0
- data/sig/pvectl/commands/suspend.rbs +11 -0
- data/sig/pvectl/commands/template_command.rbs +21 -0
- data/sig/pvectl/commands/template_container.rbs +10 -0
- data/sig/pvectl/commands/template_vm.rbs +12 -0
- data/sig/pvectl/commands/top/command.rbs +31 -0
- data/sig/pvectl/commands/top/handlers/containers.rbs +21 -0
- data/sig/pvectl/commands/top/handlers/nodes.rbs +21 -0
- data/sig/pvectl/commands/top/handlers/vms.rbs +21 -0
- data/sig/pvectl/commands/top/resource_handler.rbs +11 -0
- data/sig/pvectl/commands/top/resource_registry.rbs +8 -0
- data/sig/pvectl/commands/unlink_disk_vm.rbs +27 -0
- data/sig/pvectl/commands/vm_lifecycle_command.rbs +25 -0
- data/sig/pvectl/commands/wakeonlan_node.rbs +21 -0
- data/sig/pvectl/config/errors.rbs +24 -0
- data/sig/pvectl/config/models/cluster.rbs +39 -0
- data/sig/pvectl/config/models/context.rbs +23 -0
- data/sig/pvectl/config/models/resolved_config.rbs +51 -0
- data/sig/pvectl/config/models/user.rbs +31 -0
- data/sig/pvectl/config/provider.rbs +40 -0
- data/sig/pvectl/config/service.rbs +65 -0
- data/sig/pvectl/config/store.rbs +14 -0
- data/sig/pvectl/config/wizard.rbs +48 -0
- data/sig/pvectl/config_serializer.rbs +121 -0
- data/sig/pvectl/connection/retry_handler.rbs +31 -0
- data/sig/pvectl/connection.rbs +35 -0
- data/sig/pvectl/console/terminal_session.rbs +63 -0
- data/sig/pvectl/editor_session.rbs +33 -0
- data/sig/pvectl/exit_codes.rbs +19 -0
- data/sig/pvectl/formatters/base.rbs +13 -0
- data/sig/pvectl/formatters/color_support.rbs +13 -0
- data/sig/pvectl/formatters/json.rbs +7 -0
- data/sig/pvectl/formatters/output_helper.rbs +9 -0
- data/sig/pvectl/formatters/registry.rbs +13 -0
- data/sig/pvectl/formatters/table.rbs +25 -0
- data/sig/pvectl/formatters/wide.rbs +15 -0
- data/sig/pvectl/formatters/yaml.rbs +7 -0
- data/sig/pvectl/manifest_serializer.rbs +18 -0
- data/sig/pvectl/models/apt_package.rbs +26 -0
- data/sig/pvectl/models/backup.rbs +31 -0
- data/sig/pvectl/models/base.rbs +11 -0
- data/sig/pvectl/models/capability.rbs +16 -0
- data/sig/pvectl/models/container.rbs +44 -0
- data/sig/pvectl/models/container_operation_result.rbs +9 -0
- data/sig/pvectl/models/dns_config.rbs +15 -0
- data/sig/pvectl/models/hosts_file.rbs +13 -0
- data/sig/pvectl/models/journal_entry.rbs +10 -0
- data/sig/pvectl/models/network_interface.rbs +20 -0
- data/sig/pvectl/models/node.rbs +47 -0
- data/sig/pvectl/models/node_operation_result.rbs +12 -0
- data/sig/pvectl/models/operation_result.rbs +21 -0
- data/sig/pvectl/models/physical_disk.rbs +35 -0
- data/sig/pvectl/models/service.rbs +18 -0
- data/sig/pvectl/models/snapshot.rbs +21 -0
- data/sig/pvectl/models/snapshot_description.rbs +18 -0
- data/sig/pvectl/models/storage.rbs +39 -0
- data/sig/pvectl/models/subscription.rbs +24 -0
- data/sig/pvectl/models/syslog_entry.rbs +10 -0
- data/sig/pvectl/models/task.rbs +22 -0
- data/sig/pvectl/models/task_entry.rbs +24 -0
- data/sig/pvectl/models/task_log_line.rbs +10 -0
- data/sig/pvectl/models/time_config.rbs +12 -0
- data/sig/pvectl/models/vm.rbs +32 -0
- data/sig/pvectl/models/vm_operation_result.rbs +9 -0
- data/sig/pvectl/models/volume.rbs +29 -0
- data/sig/pvectl/models/volume_operation_result.rbs +9 -0
- data/sig/pvectl/parsers/cloud_init_config.rbs +15 -0
- data/sig/pvectl/parsers/disk_config.rbs +19 -0
- data/sig/pvectl/parsers/lxc_mount_config.rbs +19 -0
- data/sig/pvectl/parsers/lxc_net_config.rbs +19 -0
- data/sig/pvectl/parsers/net_config.rbs +19 -0
- data/sig/pvectl/parsers/smart_text.rbs +7 -0
- data/sig/pvectl/plugin_loader.rbs +25 -0
- data/sig/pvectl/presenters/apt_package.rbs +19 -0
- data/sig/pvectl/presenters/backup.rbs +25 -0
- data/sig/pvectl/presenters/base.rbs +41 -0
- data/sig/pvectl/presenters/capability.rbs +19 -0
- data/sig/pvectl/presenters/config/context.rbs +17 -0
- data/sig/pvectl/presenters/container.rbs +78 -0
- data/sig/pvectl/presenters/container_operation_result.rbs +19 -0
- data/sig/pvectl/presenters/disk.rbs +31 -0
- data/sig/pvectl/presenters/dns_config.rbs +13 -0
- data/sig/pvectl/presenters/hosts_file.rbs +13 -0
- data/sig/pvectl/presenters/journal_entry.rbs +11 -0
- data/sig/pvectl/presenters/node.rbs +118 -0
- data/sig/pvectl/presenters/node_operation_result.rbs +11 -0
- data/sig/pvectl/presenters/operation_result.rbs +17 -0
- data/sig/pvectl/presenters/service.rbs +15 -0
- data/sig/pvectl/presenters/snapshot.rbs +35 -0
- data/sig/pvectl/presenters/snapshot_operation_result.rbs +27 -0
- data/sig/pvectl/presenters/storage.rbs +59 -0
- data/sig/pvectl/presenters/subscription.rbs +36 -0
- data/sig/pvectl/presenters/syslog_entry.rbs +11 -0
- data/sig/pvectl/presenters/task_entry.rbs +21 -0
- data/sig/pvectl/presenters/task_log_line.rbs +11 -0
- data/sig/pvectl/presenters/template.rbs +15 -0
- data/sig/pvectl/presenters/time_config.rbs +19 -0
- data/sig/pvectl/presenters/top_container.rbs +17 -0
- data/sig/pvectl/presenters/top_node.rbs +17 -0
- data/sig/pvectl/presenters/top_presenter.rbs +13 -0
- data/sig/pvectl/presenters/top_vm.rbs +17 -0
- data/sig/pvectl/presenters/vm.rbs +91 -0
- data/sig/pvectl/presenters/vm_operation_result.rbs +19 -0
- data/sig/pvectl/presenters/volume.rbs +23 -0
- data/sig/pvectl/presenters/volume_operation_result.rbs +11 -0
- data/sig/pvectl/repositories/apt.rbs +17 -0
- data/sig/pvectl/repositories/backup.rbs +27 -0
- data/sig/pvectl/repositories/base.rbs +23 -0
- data/sig/pvectl/repositories/capabilities.rbs +20 -0
- data/sig/pvectl/repositories/container.rbs +63 -0
- data/sig/pvectl/repositories/disk.rbs +17 -0
- data/sig/pvectl/repositories/dns.rbs +13 -0
- data/sig/pvectl/repositories/hosts.rbs +13 -0
- data/sig/pvectl/repositories/journal.rbs +7 -0
- data/sig/pvectl/repositories/node.rbs +68 -0
- data/sig/pvectl/repositories/service.rbs +27 -0
- data/sig/pvectl/repositories/snapshot.rbs +19 -0
- data/sig/pvectl/repositories/storage.rbs +37 -0
- data/sig/pvectl/repositories/subscription.rbs +17 -0
- data/sig/pvectl/repositories/syslog.rbs +7 -0
- data/sig/pvectl/repositories/task.rbs +19 -0
- data/sig/pvectl/repositories/task_list.rbs +7 -0
- data/sig/pvectl/repositories/task_log.rbs +11 -0
- data/sig/pvectl/repositories/time_config.rbs +13 -0
- data/sig/pvectl/repositories/vm.rbs +85 -0
- data/sig/pvectl/repositories/volume.rbs +43 -0
- data/sig/pvectl/selectors/base.rbs +37 -0
- data/sig/pvectl/selectors/container.rbs +19 -0
- data/sig/pvectl/selectors/disk.rbs +13 -0
- data/sig/pvectl/selectors/vm.rbs +19 -0
- data/sig/pvectl/selectors/volume.rbs +13 -0
- data/sig/pvectl/services/backup.rbs +27 -0
- data/sig/pvectl/services/clone_container.rbs +35 -0
- data/sig/pvectl/services/clone_vm.rbs +35 -0
- data/sig/pvectl/services/cloudinit.rbs +19 -0
- data/sig/pvectl/services/console.rbs +23 -0
- data/sig/pvectl/services/container_lifecycle.rbs +26 -0
- data/sig/pvectl/services/create_container.rbs +64 -0
- data/sig/pvectl/services/create_vm.rbs +72 -0
- data/sig/pvectl/services/edit_container.rbs +17 -0
- data/sig/pvectl/services/edit_dns.rbs +23 -0
- data/sig/pvectl/services/edit_hosts.rbs +13 -0
- data/sig/pvectl/services/edit_node.rbs +21 -0
- data/sig/pvectl/services/edit_vm.rbs +17 -0
- data/sig/pvectl/services/edit_volume.rbs +18 -0
- data/sig/pvectl/services/get/resource_service.rbs +23 -0
- data/sig/pvectl/services/move_disk.rbs +21 -0
- data/sig/pvectl/services/pull_config.rbs +18 -0
- data/sig/pvectl/services/push_config.rbs +37 -0
- data/sig/pvectl/services/resize_volume.rbs +47 -0
- data/sig/pvectl/services/resource_delete.rbs +27 -0
- data/sig/pvectl/services/resource_migration.rbs +29 -0
- data/sig/pvectl/services/sendkey.rbs +19 -0
- data/sig/pvectl/services/service_lifecycle.rbs +17 -0
- data/sig/pvectl/services/set_container.rbs +14 -0
- data/sig/pvectl/services/set_node.rbs +23 -0
- data/sig/pvectl/services/set_vm.rbs +14 -0
- data/sig/pvectl/services/set_volume.rbs +12 -0
- data/sig/pvectl/services/snapshot.rbs +35 -0
- data/sig/pvectl/services/task_listing.rbs +13 -0
- data/sig/pvectl/services/unlink_disk.rbs +17 -0
- data/sig/pvectl/services/vm_lifecycle.rbs +26 -0
- data/sig/pvectl/services/wakeonlan.rbs +17 -0
- data/sig/pvectl/utils/resource_resolver.rbs +17 -0
- data/sig/pvectl/wizards/create_container.rbs +21 -0
- data/sig/pvectl/wizards/create_vm.rbs +21 -0
- data/sig/pvectl.rbs +9 -0
- metadata +675 -0
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
module Get
|
|
6
|
+
module Handlers
|
|
7
|
+
# Handler for listing templates (both VM and container).
|
|
8
|
+
#
|
|
9
|
+
# Queries both VM and Container repositories, filters by template? == true,
|
|
10
|
+
# and merges into a single list. Supports --type flag for filtering by
|
|
11
|
+
# resource type (vm/ct/qemu/lxc).
|
|
12
|
+
#
|
|
13
|
+
# @example Using via ResourceRegistry
|
|
14
|
+
# handler = ResourceRegistry.for("templates")
|
|
15
|
+
# templates = handler.list(type_filter: "vm")
|
|
16
|
+
#
|
|
17
|
+
# @see Pvectl::Repositories::Vm VM repository
|
|
18
|
+
# @see Pvectl::Repositories::Container Container repository
|
|
19
|
+
# @see Pvectl::Presenters::Template Template presenter
|
|
20
|
+
#
|
|
21
|
+
class Templates
|
|
22
|
+
include ResourceHandler
|
|
23
|
+
|
|
24
|
+
# Type filter mapping — normalizes user input to API type values.
|
|
25
|
+
TYPE_MAP = {
|
|
26
|
+
"vm" => "qemu",
|
|
27
|
+
"qemu" => "qemu",
|
|
28
|
+
"ct" => "lxc",
|
|
29
|
+
"container" => "lxc",
|
|
30
|
+
"lxc" => "lxc"
|
|
31
|
+
}.freeze
|
|
32
|
+
|
|
33
|
+
# Sort field mappings for template listing.
|
|
34
|
+
SORT_FIELDS = {
|
|
35
|
+
"name" => ->(t) { t.name || "" },
|
|
36
|
+
"node" => ->(t) { t.node || "" },
|
|
37
|
+
"type" => ->(t) { t.type || "" },
|
|
38
|
+
"disk" => ->(t) { -(t.maxdisk || 0) }
|
|
39
|
+
}.freeze
|
|
40
|
+
|
|
41
|
+
# Creates handler with optional repositories for dependency injection.
|
|
42
|
+
#
|
|
43
|
+
# @param vm_repository [Repositories::Vm, nil] VM repository
|
|
44
|
+
# @param container_repository [Repositories::Container, nil] Container repository
|
|
45
|
+
def initialize(vm_repository: nil, container_repository: nil)
|
|
46
|
+
@vm_repository = vm_repository
|
|
47
|
+
@container_repository = container_repository
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Lists templates with optional filtering.
|
|
51
|
+
#
|
|
52
|
+
# @param node [String, nil] filter by node name
|
|
53
|
+
# @param type_filter [String, nil] filter by type (vm, ct, qemu, lxc)
|
|
54
|
+
# @param sort [String, nil] sort field
|
|
55
|
+
# @param name [String, nil] unused, interface compatibility
|
|
56
|
+
# @raise [ArgumentError] if type_filter is not a recognized type
|
|
57
|
+
# @return [Array<Models::Vm, Models::Container>] template models
|
|
58
|
+
def list(node: nil, name: nil, type_filter: nil, sort: nil, **_options)
|
|
59
|
+
validate_type_filter!(type_filter)
|
|
60
|
+
|
|
61
|
+
templates = []
|
|
62
|
+
|
|
63
|
+
unless skip_vms?(type_filter)
|
|
64
|
+
vms = vm_repository.list(node: node)
|
|
65
|
+
templates.concat(vms.select(&:template?))
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
unless skip_containers?(type_filter)
|
|
69
|
+
containers = container_repository.list(node: node)
|
|
70
|
+
templates.concat(containers.select(&:template?))
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
templates = apply_sort(templates, sort) if sort
|
|
74
|
+
templates
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Returns presenter for templates.
|
|
78
|
+
#
|
|
79
|
+
# @return [Presenters::Template] template presenter
|
|
80
|
+
def presenter
|
|
81
|
+
Pvectl::Presenters::Template.new
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
private
|
|
85
|
+
|
|
86
|
+
# Validates type_filter value against known types.
|
|
87
|
+
#
|
|
88
|
+
# @param type_filter [String, nil] type filter value
|
|
89
|
+
# @raise [ArgumentError] if type_filter is not a recognized type
|
|
90
|
+
# @return [void]
|
|
91
|
+
def validate_type_filter!(type_filter)
|
|
92
|
+
return if type_filter.nil?
|
|
93
|
+
return if TYPE_MAP.key?(type_filter)
|
|
94
|
+
|
|
95
|
+
valid_types = TYPE_MAP.keys.join(", ")
|
|
96
|
+
raise ArgumentError, "Unknown type: #{type_filter}. Valid types: #{valid_types}"
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Returns VM repository, creating it if necessary.
|
|
100
|
+
#
|
|
101
|
+
# @return [Repositories::Vm]
|
|
102
|
+
def vm_repository
|
|
103
|
+
@vm_repository ||= build_vm_repository
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Returns Container repository, creating it if necessary.
|
|
107
|
+
#
|
|
108
|
+
# @return [Repositories::Container]
|
|
109
|
+
def container_repository
|
|
110
|
+
@container_repository ||= build_container_repository
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Builds VM repository with connection from config.
|
|
114
|
+
#
|
|
115
|
+
# @return [Repositories::Vm]
|
|
116
|
+
def build_vm_repository
|
|
117
|
+
config_service = Pvectl::Config::Service.new
|
|
118
|
+
config_service.load
|
|
119
|
+
connection = Pvectl::Connection.new(config_service.current_config)
|
|
120
|
+
Pvectl::Repositories::Vm.new(connection)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Builds Container repository with connection from config.
|
|
124
|
+
#
|
|
125
|
+
# @return [Repositories::Container]
|
|
126
|
+
def build_container_repository
|
|
127
|
+
config_service = Pvectl::Config::Service.new
|
|
128
|
+
config_service.load
|
|
129
|
+
connection = Pvectl::Connection.new(config_service.current_config)
|
|
130
|
+
Pvectl::Repositories::Container.new(connection)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# Checks if VMs should be skipped based on type filter.
|
|
134
|
+
#
|
|
135
|
+
# @param type_filter [String, nil] type filter value
|
|
136
|
+
# @return [Boolean]
|
|
137
|
+
def skip_vms?(type_filter)
|
|
138
|
+
return false if type_filter.nil?
|
|
139
|
+
|
|
140
|
+
TYPE_MAP[type_filter] == "lxc"
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Checks if containers should be skipped based on type filter.
|
|
144
|
+
#
|
|
145
|
+
# @param type_filter [String, nil] type filter value
|
|
146
|
+
# @return [Boolean]
|
|
147
|
+
def skip_containers?(type_filter)
|
|
148
|
+
return false if type_filter.nil?
|
|
149
|
+
|
|
150
|
+
TYPE_MAP[type_filter] == "qemu"
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# Applies sorting to templates collection.
|
|
154
|
+
#
|
|
155
|
+
# @param templates [Array] templates to sort
|
|
156
|
+
# @param sort_field [String] field to sort by
|
|
157
|
+
# @return [Array] sorted templates
|
|
158
|
+
def apply_sort(templates, sort_field)
|
|
159
|
+
sort_proc = SORT_FIELDS[sort_field.to_s]
|
|
160
|
+
return templates unless sort_proc
|
|
161
|
+
|
|
162
|
+
templates.sort_by(&sort_proc)
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# Register handler with ResourceRegistry
|
|
171
|
+
Pvectl::Commands::Get::ResourceRegistry.register(
|
|
172
|
+
"templates",
|
|
173
|
+
Pvectl::Commands::Get::Handlers::Templates,
|
|
174
|
+
aliases: ["template"]
|
|
175
|
+
)
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
module Get
|
|
6
|
+
module Handlers
|
|
7
|
+
# Handler for listing node time and timezone settings.
|
|
8
|
+
#
|
|
9
|
+
# Implements ResourceHandler interface for the "time" resource type.
|
|
10
|
+
# When `--node` is supplied, returns the time config for that single node.
|
|
11
|
+
# Otherwise, iterates over all online nodes and aggregates their time configs.
|
|
12
|
+
# Unreachable nodes (those that raise during fetch) are silently skipped so
|
|
13
|
+
# one bad node does not abort the whole listing.
|
|
14
|
+
#
|
|
15
|
+
# @example Using via ResourceRegistry
|
|
16
|
+
# handler = ResourceRegistry.for("time")
|
|
17
|
+
# configs = handler.list(node: "pve1")
|
|
18
|
+
#
|
|
19
|
+
# @see Pvectl::Commands::Get::ResourceHandler Handler interface
|
|
20
|
+
# @see Pvectl::Repositories::TimeConfig Time repository
|
|
21
|
+
# @see Pvectl::Presenters::TimeConfig Time presenter
|
|
22
|
+
#
|
|
23
|
+
class Time
|
|
24
|
+
include ResourceHandler
|
|
25
|
+
|
|
26
|
+
# Creates handler with optional repositories for dependency injection.
|
|
27
|
+
#
|
|
28
|
+
# @param repository [Repositories::TimeConfig, nil] time repository
|
|
29
|
+
# @param node_repository [Repositories::Node, nil] node repository
|
|
30
|
+
def initialize(repository: nil, node_repository: nil)
|
|
31
|
+
@repository = repository
|
|
32
|
+
@node_repository = node_repository
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Lists time/timezone configs.
|
|
36
|
+
#
|
|
37
|
+
# @param node [String, nil] when given, only that node is queried;
|
|
38
|
+
# otherwise iterates all online nodes
|
|
39
|
+
# @param name [String, nil] unused, for interface compatibility
|
|
40
|
+
# @param args [Array<String>] unused, for interface compatibility
|
|
41
|
+
# @param storage [String, nil] unused, for interface compatibility
|
|
42
|
+
# @return [Array<Models::TimeConfig>] one entry per node queried
|
|
43
|
+
# @raise [Pvectl::ResourceNotFoundError] if a specific node was requested but does not exist
|
|
44
|
+
def list(node: nil, name: nil, args: [], storage: nil, **_options)
|
|
45
|
+
return [fetch_for(node)] if node
|
|
46
|
+
|
|
47
|
+
online_node_names.filter_map do |node_name|
|
|
48
|
+
begin
|
|
49
|
+
repository.fetch(node_name)
|
|
50
|
+
rescue StandardError
|
|
51
|
+
# Skip unreachable nodes - one bad node should not abort the listing.
|
|
52
|
+
nil
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Returns presenter for time configs.
|
|
58
|
+
#
|
|
59
|
+
# @return [Presenters::TimeConfig]
|
|
60
|
+
def presenter
|
|
61
|
+
Pvectl::Presenters::TimeConfig.new
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
private
|
|
65
|
+
|
|
66
|
+
# Fetches the time config for a specific node, raising ResourceNotFoundError
|
|
67
|
+
# if the node itself does not exist in the cluster.
|
|
68
|
+
#
|
|
69
|
+
# @param node_name [String] node name
|
|
70
|
+
# @return [Models::TimeConfig]
|
|
71
|
+
# @raise [Pvectl::ResourceNotFoundError] if the node does not exist
|
|
72
|
+
def fetch_for(node_name)
|
|
73
|
+
unless node_repository.get(node_name)
|
|
74
|
+
raise Pvectl::ResourceNotFoundError, "Node not found: #{node_name}"
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
repository.fetch(node_name)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Names of online nodes (offline nodes are skipped because querying
|
|
81
|
+
# them is guaranteed to fail).
|
|
82
|
+
#
|
|
83
|
+
# @return [Array<String>] node names
|
|
84
|
+
def online_node_names
|
|
85
|
+
node_repository.list.select { |n| n.status == "online" }.map(&:name)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# @return [Repositories::TimeConfig] time repository, lazily built
|
|
89
|
+
def repository
|
|
90
|
+
@repository ||= Pvectl::Repositories::TimeConfig.new(connection)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# @return [Repositories::Node] node repository, lazily built
|
|
94
|
+
def node_repository
|
|
95
|
+
@node_repository ||= Pvectl::Repositories::Node.new(connection)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Builds API connection from current config.
|
|
99
|
+
#
|
|
100
|
+
# @return [Pvectl::Connection]
|
|
101
|
+
def connection
|
|
102
|
+
@connection ||= begin
|
|
103
|
+
config_service = Pvectl::Config::Service.new
|
|
104
|
+
config_service.load
|
|
105
|
+
Pvectl::Connection.new(config_service.current_config)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Register handler with ResourceRegistry
|
|
115
|
+
Pvectl::Commands::Get::ResourceRegistry.register(
|
|
116
|
+
"time",
|
|
117
|
+
Pvectl::Commands::Get::Handlers::Time
|
|
118
|
+
)
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
module Get
|
|
6
|
+
module Handlers
|
|
7
|
+
# Handler for listing QEMU virtual machines.
|
|
8
|
+
#
|
|
9
|
+
# Implements ResourceHandler interface for the "vms" resource type.
|
|
10
|
+
# Uses Repositories::Vm for data access and Presenters::Vm for formatting.
|
|
11
|
+
#
|
|
12
|
+
# Registered with ResourceRegistry on file load for both "vms" and "vm".
|
|
13
|
+
#
|
|
14
|
+
# @example Using via ResourceRegistry
|
|
15
|
+
# handler = ResourceRegistry.for("vms")
|
|
16
|
+
# vms = handler.list(node: "pve1")
|
|
17
|
+
# presenter = handler.presenter
|
|
18
|
+
#
|
|
19
|
+
# @see Pvectl::Commands::Get::ResourceHandler Handler interface
|
|
20
|
+
# @see Pvectl::Repositories::Vm VM repository
|
|
21
|
+
# @see Pvectl::Presenters::Vm VM presenter
|
|
22
|
+
#
|
|
23
|
+
class Vms
|
|
24
|
+
include ResourceHandler
|
|
25
|
+
|
|
26
|
+
# VMID validation pattern (1-999999999)
|
|
27
|
+
VMID_PATTERN = /\A[1-9]\d{0,8}\z/
|
|
28
|
+
|
|
29
|
+
# Sort field mappings.
|
|
30
|
+
# Negative values for descending sort (higher values first).
|
|
31
|
+
SORT_FIELDS = {
|
|
32
|
+
"name" => ->(v) { v.name || "" },
|
|
33
|
+
"node" => ->(v) { v.node || "" },
|
|
34
|
+
"cpu" => ->(v) { -(v.cpu || 0) },
|
|
35
|
+
"memory" => ->(v) { -(v.mem || 0) },
|
|
36
|
+
"disk" => ->(v) { -(v.disk || 0) },
|
|
37
|
+
"netin" => ->(v) { -(v.netin || 0) },
|
|
38
|
+
"netout" => ->(v) { -(v.netout || 0) }
|
|
39
|
+
}.freeze
|
|
40
|
+
|
|
41
|
+
# Creates handler with optional repository for dependency injection.
|
|
42
|
+
#
|
|
43
|
+
# @param repository [Repositories::Vm, nil] repository (default: create new)
|
|
44
|
+
def initialize(repository: nil)
|
|
45
|
+
@repository = repository
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Returns selector class for VM filtering.
|
|
49
|
+
#
|
|
50
|
+
# @return [Class] Selectors::Vm
|
|
51
|
+
def selector_class
|
|
52
|
+
Pvectl::Selectors::Vm
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Lists VMs with optional filtering and sorting.
|
|
56
|
+
#
|
|
57
|
+
# @param node [String, nil] filter by node name
|
|
58
|
+
# @param name [String, nil] filter by VM name
|
|
59
|
+
# @param args [Array<String>] unused, for interface compatibility
|
|
60
|
+
# @param storage [String, nil] unused, for interface compatibility
|
|
61
|
+
# @param sort [String, nil] sort field (name, node, cpu, memory, disk, netin, netout)
|
|
62
|
+
# @return [Array<Models::Vm>] collection of VM models
|
|
63
|
+
def list(node: nil, name: nil, args: [], storage: nil, sort: nil, **_options)
|
|
64
|
+
vms = repository.list(node: node)
|
|
65
|
+
vms = vms.select { |vm| vm.name == name } if name
|
|
66
|
+
vms = apply_sort(vms, sort) if sort
|
|
67
|
+
vms
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Returns presenter for VMs.
|
|
71
|
+
#
|
|
72
|
+
# @return [Presenters::Vm] VM presenter instance
|
|
73
|
+
def presenter
|
|
74
|
+
Pvectl::Presenters::Vm.new
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Describes a single VM with comprehensive details.
|
|
78
|
+
#
|
|
79
|
+
# @param name [String] VMID as string (consistent with handler interface)
|
|
80
|
+
# @param node [String, nil] unused, for API consistency
|
|
81
|
+
# @return [Models::Vm] VM model with full details
|
|
82
|
+
# @raise [ArgumentError] if VMID format is invalid
|
|
83
|
+
# @raise [Pvectl::ResourceNotFoundError] if VM not found
|
|
84
|
+
def describe(name:, node: nil, args: [], vmid: nil)
|
|
85
|
+
raise ArgumentError, "Invalid VMID: must be positive integer (1-999999999)" unless valid_vmid?(name)
|
|
86
|
+
|
|
87
|
+
vmid = name.to_i
|
|
88
|
+
vm = repository.describe(vmid)
|
|
89
|
+
raise Pvectl::ResourceNotFoundError, "VM not found: #{vmid}" if vm.nil?
|
|
90
|
+
|
|
91
|
+
vm
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
private
|
|
95
|
+
|
|
96
|
+
# Returns repository, creating it if necessary.
|
|
97
|
+
#
|
|
98
|
+
# @return [Repositories::Vm] VM repository
|
|
99
|
+
def repository
|
|
100
|
+
@repository ||= build_repository
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Builds repository with connection from config.
|
|
104
|
+
#
|
|
105
|
+
# @return [Repositories::Vm] configured VM repository
|
|
106
|
+
def build_repository
|
|
107
|
+
config_service = Pvectl::Config::Service.new
|
|
108
|
+
config_service.load
|
|
109
|
+
connection = Pvectl::Connection.new(config_service.current_config)
|
|
110
|
+
Pvectl::Repositories::Vm.new(connection)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Applies sorting to VMs collection.
|
|
114
|
+
#
|
|
115
|
+
# @param vms [Array<Models::Vm>] VMs to sort
|
|
116
|
+
# @param sort_field [String] field to sort by
|
|
117
|
+
# @return [Array<Models::Vm>] sorted VMs
|
|
118
|
+
def apply_sort(vms, sort_field)
|
|
119
|
+
sort_proc = SORT_FIELDS[sort_field.to_s]
|
|
120
|
+
return vms unless sort_proc
|
|
121
|
+
|
|
122
|
+
vms.sort_by(&sort_proc)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Validates VMID format.
|
|
126
|
+
#
|
|
127
|
+
# @param vmid [String, nil] VMID to validate
|
|
128
|
+
# @return [Boolean] true if valid
|
|
129
|
+
def valid_vmid?(vmid)
|
|
130
|
+
return false if vmid.nil? || vmid.to_s.empty?
|
|
131
|
+
|
|
132
|
+
vmid.to_s.match?(VMID_PATTERN)
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Register handler with ResourceRegistry
|
|
141
|
+
Pvectl::Commands::Get::ResourceRegistry.register(
|
|
142
|
+
"vms",
|
|
143
|
+
Pvectl::Commands::Get::Handlers::Vms,
|
|
144
|
+
aliases: ["vm"]
|
|
145
|
+
)
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
module Get
|
|
6
|
+
module Handlers
|
|
7
|
+
# Handler for listing and describing virtual disk volumes.
|
|
8
|
+
#
|
|
9
|
+
# Implements ResourceHandler interface for the "volumes" resource type.
|
|
10
|
+
# Supports two listing modes:
|
|
11
|
+
# - Config mode: list volumes from VM/CT config by resource type and IDs
|
|
12
|
+
# - Storage mode: list volumes from a specific storage
|
|
13
|
+
#
|
|
14
|
+
# Uses Repositories::Volume for data access, Presenters::Volume for
|
|
15
|
+
# formatting, and Selectors::Volume for client-side filtering.
|
|
16
|
+
#
|
|
17
|
+
# @example List VM volumes via ResourceRegistry
|
|
18
|
+
# handler = ResourceRegistry.for("volumes")
|
|
19
|
+
# volumes = handler.list(args: ["vm", "100"], node: "pve1")
|
|
20
|
+
#
|
|
21
|
+
# @example List storage volumes
|
|
22
|
+
# handler = ResourceRegistry.for("volumes")
|
|
23
|
+
# volumes = handler.list(storage: "local-lvm")
|
|
24
|
+
#
|
|
25
|
+
# @example Describe a specific volume
|
|
26
|
+
# handler = ResourceRegistry.for("volumes")
|
|
27
|
+
# volume = handler.describe(name: "vm", args: ["100", "scsi0"])
|
|
28
|
+
#
|
|
29
|
+
# @see Pvectl::Commands::Get::ResourceHandler Handler interface
|
|
30
|
+
# @see Pvectl::Repositories::Volume Volume repository
|
|
31
|
+
# @see Pvectl::Presenters::Volume Volume presenter
|
|
32
|
+
#
|
|
33
|
+
class Volume
|
|
34
|
+
include ResourceHandler
|
|
35
|
+
|
|
36
|
+
# Creates handler with optional repository for dependency injection.
|
|
37
|
+
#
|
|
38
|
+
# @param repository [Repositories::Volume, nil] repository (default: create new)
|
|
39
|
+
def initialize(repository: nil)
|
|
40
|
+
@repository = repository
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Lists virtual disk volumes with two modes of operation.
|
|
44
|
+
#
|
|
45
|
+
# Config mode: requires resource type and at least one ID in args.
|
|
46
|
+
# args = ["vm", "100", "101"] lists volumes from VMs 100 and 101.
|
|
47
|
+
#
|
|
48
|
+
# Storage mode: requires storage parameter.
|
|
49
|
+
# storage = "local-lvm" lists all volumes on that storage.
|
|
50
|
+
#
|
|
51
|
+
# @param args [Array<String>] resource type and IDs (config mode)
|
|
52
|
+
# @param storage [String, nil] storage name (storage mode)
|
|
53
|
+
# @param node [String, nil] filter by node name
|
|
54
|
+
# @param _options [Hash] unused, for interface compatibility
|
|
55
|
+
# @return [Array<Models::Volume>] collection of Volume models
|
|
56
|
+
def list(args: [], storage: nil, node: nil, **_options)
|
|
57
|
+
if storage
|
|
58
|
+
repository.list_from_storage(storage: storage, node: node)
|
|
59
|
+
elsif args.length >= 2
|
|
60
|
+
resource_type = args[0]
|
|
61
|
+
ids = args[1..].map(&:to_i)
|
|
62
|
+
repository.list_from_config(resource_type: resource_type, ids: ids, node: node)
|
|
63
|
+
else
|
|
64
|
+
$stderr.puts "Usage: pvectl get volume <vm|ct> <ID...> [--node NODE]"
|
|
65
|
+
$stderr.puts " pvectl get volume --storage <STORAGE> [--node NODE]"
|
|
66
|
+
[]
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Describes a single virtual disk volume.
|
|
71
|
+
#
|
|
72
|
+
# Locates a specific disk by resource type, ID, and disk name.
|
|
73
|
+
#
|
|
74
|
+
# @param name [String] resource type ("vm" or "ct")
|
|
75
|
+
# @param args [Array<String>] [id, disk_name] pair
|
|
76
|
+
# @param node [String, nil] optional node filter
|
|
77
|
+
# @param _options [Hash] unused, for interface compatibility
|
|
78
|
+
# @return [Models::Volume] found Volume model
|
|
79
|
+
# @raise [Pvectl::ResourceNotFoundError] when volume not found
|
|
80
|
+
def describe(name:, args: [], node: nil, **_options)
|
|
81
|
+
resource_type = name
|
|
82
|
+
id = args[0]&.to_i
|
|
83
|
+
disk_name = args[1]
|
|
84
|
+
|
|
85
|
+
volume = repository.find(resource_type: resource_type, id: id, disk_name: disk_name, node: node)
|
|
86
|
+
raise Pvectl::ResourceNotFoundError, "Volume '#{disk_name}' not found on #{resource_type} #{id}" unless volume
|
|
87
|
+
|
|
88
|
+
volume
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Returns presenter for virtual disk volumes.
|
|
92
|
+
#
|
|
93
|
+
# @return [Presenters::Volume] Volume presenter instance
|
|
94
|
+
def presenter
|
|
95
|
+
Pvectl::Presenters::Volume.new
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Returns selector class for client-side filtering.
|
|
99
|
+
#
|
|
100
|
+
# @return [Class] Selectors::Volume class
|
|
101
|
+
def selector_class
|
|
102
|
+
Pvectl::Selectors::Volume
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
private
|
|
106
|
+
|
|
107
|
+
# Returns repository, creating it if necessary.
|
|
108
|
+
#
|
|
109
|
+
# @return [Repositories::Volume] Volume repository
|
|
110
|
+
def repository
|
|
111
|
+
@repository ||= build_repository
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Builds repository with connection from config.
|
|
115
|
+
#
|
|
116
|
+
# @return [Repositories::Volume] configured Volume repository
|
|
117
|
+
def build_repository
|
|
118
|
+
config_service = Pvectl::Config::Service.new
|
|
119
|
+
config_service.load
|
|
120
|
+
connection = Pvectl::Connection.new(config_service.current_config)
|
|
121
|
+
Pvectl::Repositories::Volume.new(connection)
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Register handler with ResourceRegistry
|
|
130
|
+
Pvectl::Commands::Get::ResourceRegistry.register(
|
|
131
|
+
"volumes",
|
|
132
|
+
Pvectl::Commands::Get::Handlers::Volume,
|
|
133
|
+
aliases: ["volume", "vol"]
|
|
134
|
+
)
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
module Get
|
|
6
|
+
# Interface module for resource handlers.
|
|
7
|
+
#
|
|
8
|
+
# Each resource type (nodes, vms, containers, storage) implements
|
|
9
|
+
# this interface to provide listing capabilities.
|
|
10
|
+
#
|
|
11
|
+
# Minimal interface with two methods:
|
|
12
|
+
# - #list - fetches and returns model objects
|
|
13
|
+
# - #presenter - returns presenter for formatting
|
|
14
|
+
#
|
|
15
|
+
# @abstract Include in handler class and implement required methods.
|
|
16
|
+
#
|
|
17
|
+
# @example Implementing a handler
|
|
18
|
+
# class NodesHandler
|
|
19
|
+
# include ResourceHandler
|
|
20
|
+
#
|
|
21
|
+
# def list(node: nil, name: nil)
|
|
22
|
+
# # Fetch and return array of Node models
|
|
23
|
+
# repository.list.select { |n| name.nil? || n.name == name }
|
|
24
|
+
# end
|
|
25
|
+
#
|
|
26
|
+
# def presenter
|
|
27
|
+
# Presenters::Node.new
|
|
28
|
+
# end
|
|
29
|
+
# end
|
|
30
|
+
#
|
|
31
|
+
module ResourceHandler
|
|
32
|
+
# Lists resources, optionally filtered by node and name.
|
|
33
|
+
#
|
|
34
|
+
# @param node [String, nil] filter by node name (for VMs/containers)
|
|
35
|
+
# @param name [String, nil] filter by resource name
|
|
36
|
+
# @param _options [Hash] additional options passed through from CLI (e.g., limit, since, type_filter)
|
|
37
|
+
# @return [Array<Object>] collection of model objects
|
|
38
|
+
# @raise [NotImplementedError] if not implemented by including class
|
|
39
|
+
def list(node: nil, name: nil, **_options)
|
|
40
|
+
raise NotImplementedError, "#{self.class}#list must be implemented"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Returns the presenter for this resource type.
|
|
44
|
+
#
|
|
45
|
+
# @return [Presenters::Base] presenter instance
|
|
46
|
+
# @raise [NotImplementedError] if not implemented by including class
|
|
47
|
+
def presenter
|
|
48
|
+
raise NotImplementedError, "#{self.class}#presenter must be implemented"
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Returns the selector class for client-side filtering.
|
|
52
|
+
#
|
|
53
|
+
# Handlers that support selector-based filtering (e.g., -l status=running)
|
|
54
|
+
# should override this to return their selector class.
|
|
55
|
+
#
|
|
56
|
+
# @return [Class, nil] selector class (e.g., Selectors::Vm) or nil if not supported
|
|
57
|
+
def selector_class
|
|
58
|
+
nil
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
module Get
|
|
6
|
+
# Registry for Get command resource handlers.
|
|
7
|
+
#
|
|
8
|
+
# Inherits all registration and lookup logic from Commands::ResourceRegistry.
|
|
9
|
+
# Each handler registers itself at load time.
|
|
10
|
+
#
|
|
11
|
+
# @example Looking up a handler
|
|
12
|
+
# handler = ResourceRegistry.for("nodes")
|
|
13
|
+
# handler.list(node: "pve1") if handler
|
|
14
|
+
#
|
|
15
|
+
class ResourceRegistry < Commands::ResourceRegistry; end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|