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,389 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
# Top-level `pvectl apt` command for managing APT packages on Proxmox nodes.
|
|
6
|
+
#
|
|
7
|
+
# Exposes four sub-commands:
|
|
8
|
+
#
|
|
9
|
+
# * `apt list` list pending package updates
|
|
10
|
+
# * `apt update` refresh the package index (apt-get update)
|
|
11
|
+
# * `apt changelog` show changelog for a package
|
|
12
|
+
# * `apt versions` list installed Proxmox-relevant package versions
|
|
13
|
+
#
|
|
14
|
+
# Each sub-command requires `--node NODE` (falls back to default-node from
|
|
15
|
+
# the active context configuration when not provided).
|
|
16
|
+
#
|
|
17
|
+
# @example Register with the CLI
|
|
18
|
+
# Commands::Apt.register(cli)
|
|
19
|
+
#
|
|
20
|
+
class Apt
|
|
21
|
+
# Registers the apt command and all sub-commands with the CLI.
|
|
22
|
+
#
|
|
23
|
+
# @param cli [GLI::App] the CLI application object
|
|
24
|
+
# @return [void]
|
|
25
|
+
def self.register(cli)
|
|
26
|
+
cli.desc "Manage APT packages on Proxmox nodes"
|
|
27
|
+
cli.long_desc <<~HELP
|
|
28
|
+
DESCRIPTION
|
|
29
|
+
Manage APT (Advanced Package Tool) packages on Proxmox VE nodes.
|
|
30
|
+
Wraps the Proxmox /nodes/{node}/apt API to inspect pending updates,
|
|
31
|
+
refresh the package index, read package changelogs, and report
|
|
32
|
+
installed Proxmox-relevant package versions.
|
|
33
|
+
|
|
34
|
+
SUB-COMMANDS
|
|
35
|
+
apt list List pending package updates
|
|
36
|
+
apt update Refresh the package index (apt-get update)
|
|
37
|
+
apt changelog PACKAGE Show changelog for a package
|
|
38
|
+
apt versions Show installed Proxmox package versions
|
|
39
|
+
|
|
40
|
+
EXAMPLES
|
|
41
|
+
List pending updates on a node:
|
|
42
|
+
$ pvectl apt list --node pve1
|
|
43
|
+
|
|
44
|
+
Refresh the package index on the default node:
|
|
45
|
+
$ pvectl apt update
|
|
46
|
+
|
|
47
|
+
Refresh quietly without sending update notifications:
|
|
48
|
+
$ pvectl apt update --node pve1 --quiet
|
|
49
|
+
|
|
50
|
+
Show changelog for a specific package version:
|
|
51
|
+
$ pvectl apt changelog pve-manager --node pve1 --version 8.2.4-1
|
|
52
|
+
|
|
53
|
+
Inspect installed Proxmox versions (parity with pveversion -v):
|
|
54
|
+
$ pvectl apt versions --node pve1 -o wide
|
|
55
|
+
|
|
56
|
+
NOTES
|
|
57
|
+
--node defaults to the context's default-node when configured.
|
|
58
|
+
|
|
59
|
+
Proxmox does NOT expose `apt upgrade` over the API (security
|
|
60
|
+
restriction). To actually install updates you must SSH to the
|
|
61
|
+
node and run apt full-upgrade manually.
|
|
62
|
+
|
|
63
|
+
`apt update` is asynchronous; the response includes the Proxmox
|
|
64
|
+
task UPID, inspect with `pvectl get tasks` and
|
|
65
|
+
`pvectl logs task UPID`.
|
|
66
|
+
|
|
67
|
+
SEE ALSO
|
|
68
|
+
pvectl help get List resources (try `get nodes`)
|
|
69
|
+
pvectl help logs Inspect task output
|
|
70
|
+
HELP
|
|
71
|
+
|
|
72
|
+
cli.command :apt do |c|
|
|
73
|
+
# Shared --node flag declared on the parent so every subcommand inherits it.
|
|
74
|
+
c.desc "Node name (defaults to context default-node)"
|
|
75
|
+
c.flag [:node], arg_name: "NODE"
|
|
76
|
+
|
|
77
|
+
register_list(c)
|
|
78
|
+
register_update(c)
|
|
79
|
+
register_changelog(c)
|
|
80
|
+
register_versions(c)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Registers the `apt list` subcommand.
|
|
85
|
+
#
|
|
86
|
+
# @param parent [GLI::Command] parent apt command
|
|
87
|
+
# @return [void]
|
|
88
|
+
def self.register_list(parent)
|
|
89
|
+
parent.desc "List pending APT updates on a node"
|
|
90
|
+
parent.long_desc <<~HELP
|
|
91
|
+
List packages that have an available APT update on the target node.
|
|
92
|
+
|
|
93
|
+
EXAMPLES
|
|
94
|
+
$ pvectl apt list --node pve1
|
|
95
|
+
$ pvectl apt list --node pve1 -o wide
|
|
96
|
+
$ pvectl apt list --node pve1 -o json
|
|
97
|
+
|
|
98
|
+
SEE ALSO
|
|
99
|
+
pvectl help apt Parent command
|
|
100
|
+
HELP
|
|
101
|
+
parent.command :list do |sub|
|
|
102
|
+
sub.action do |global_options, options, args|
|
|
103
|
+
exit_code = execute(:list, args, options, global_options)
|
|
104
|
+
exit exit_code if exit_code != 0
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Registers the `apt update` subcommand.
|
|
110
|
+
#
|
|
111
|
+
# @param parent [GLI::Command] parent apt command
|
|
112
|
+
# @return [void]
|
|
113
|
+
def self.register_update(parent)
|
|
114
|
+
parent.desc "Refresh the APT package index on a node (apt-get update)"
|
|
115
|
+
parent.long_desc <<~HELP
|
|
116
|
+
Refresh the APT package index on the target node. Equivalent to
|
|
117
|
+
running `apt-get update` directly on the node.
|
|
118
|
+
|
|
119
|
+
This does NOT install updates — Proxmox does not expose apt upgrade
|
|
120
|
+
over the API for security reasons.
|
|
121
|
+
|
|
122
|
+
EXAMPLES
|
|
123
|
+
$ pvectl apt update --node pve1
|
|
124
|
+
$ pvectl apt update --node pve1 --quiet
|
|
125
|
+
$ pvectl apt update --node pve1 --notify
|
|
126
|
+
|
|
127
|
+
SEE ALSO
|
|
128
|
+
pvectl help apt Parent command
|
|
129
|
+
HELP
|
|
130
|
+
parent.command :update do |sub|
|
|
131
|
+
sub.desc "Send a notification about new packages"
|
|
132
|
+
sub.switch [:notify], negatable: false
|
|
133
|
+
|
|
134
|
+
sub.desc "Suppress progress output"
|
|
135
|
+
sub.switch [:quiet], negatable: false
|
|
136
|
+
|
|
137
|
+
sub.action do |global_options, options, args|
|
|
138
|
+
exit_code = execute(:update, args, options, global_options)
|
|
139
|
+
exit exit_code if exit_code != 0
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Registers the `apt changelog` subcommand.
|
|
145
|
+
#
|
|
146
|
+
# @param parent [GLI::Command] parent apt command
|
|
147
|
+
# @return [void]
|
|
148
|
+
def self.register_changelog(parent)
|
|
149
|
+
parent.desc "Show the changelog for an APT package on a node"
|
|
150
|
+
parent.long_desc <<~HELP
|
|
151
|
+
Show the upstream changelog for a package on the target node. When
|
|
152
|
+
--version is omitted the latest available version's changelog is
|
|
153
|
+
returned.
|
|
154
|
+
|
|
155
|
+
EXAMPLES
|
|
156
|
+
$ pvectl apt changelog pve-manager --node pve1
|
|
157
|
+
$ pvectl apt changelog pve-manager --node pve1 --version 8.2.4-1
|
|
158
|
+
|
|
159
|
+
SEE ALSO
|
|
160
|
+
pvectl help apt Parent command
|
|
161
|
+
HELP
|
|
162
|
+
parent.arg_name "PACKAGE"
|
|
163
|
+
parent.command :changelog do |sub|
|
|
164
|
+
sub.desc "Package version (optional, defaults to latest)"
|
|
165
|
+
sub.flag [:version], arg_name: "VERSION"
|
|
166
|
+
|
|
167
|
+
sub.action do |global_options, options, args|
|
|
168
|
+
exit_code = execute(:changelog, args, options, global_options)
|
|
169
|
+
exit exit_code if exit_code != 0
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Registers the `apt versions` subcommand.
|
|
175
|
+
#
|
|
176
|
+
# @param parent [GLI::Command] parent apt command
|
|
177
|
+
# @return [void]
|
|
178
|
+
def self.register_versions(parent)
|
|
179
|
+
parent.desc "Show installed Proxmox package versions on a node"
|
|
180
|
+
parent.long_desc <<~HELP
|
|
181
|
+
Show installed versions of important Proxmox VE packages on the
|
|
182
|
+
target node — parity with `pveversion -v` on the node itself.
|
|
183
|
+
|
|
184
|
+
EXAMPLES
|
|
185
|
+
$ pvectl apt versions --node pve1
|
|
186
|
+
$ pvectl apt versions --node pve1 -o wide
|
|
187
|
+
$ pvectl apt versions --node pve1 -o yaml
|
|
188
|
+
|
|
189
|
+
SEE ALSO
|
|
190
|
+
pvectl help apt Parent command
|
|
191
|
+
HELP
|
|
192
|
+
parent.command :versions do |sub|
|
|
193
|
+
sub.action do |global_options, options, args|
|
|
194
|
+
exit_code = execute(:versions, args, options, global_options)
|
|
195
|
+
exit exit_code if exit_code != 0
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
# Executes the command.
|
|
201
|
+
#
|
|
202
|
+
# @param operation [Symbol] :list, :update, :changelog, :versions
|
|
203
|
+
# @param args [Array<String>] positional CLI arguments
|
|
204
|
+
# @param options [Hash] command options
|
|
205
|
+
# @param global_options [Hash] global CLI options
|
|
206
|
+
# @return [Integer] exit code
|
|
207
|
+
def self.execute(operation, args, options, global_options)
|
|
208
|
+
new(operation, args, options, global_options).execute
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
# Initializes an apt command instance.
|
|
212
|
+
#
|
|
213
|
+
# @param operation [Symbol] operation
|
|
214
|
+
# @param args [Array<String>] positional CLI arguments
|
|
215
|
+
# @param options [Hash] command options
|
|
216
|
+
# @param global_options [Hash] global CLI options
|
|
217
|
+
# @param output [IO] IO for output (default: $stdout)
|
|
218
|
+
def initialize(operation, args, options, global_options, output: $stdout)
|
|
219
|
+
@operation = operation
|
|
220
|
+
@args = Array(args).compact
|
|
221
|
+
@options = options
|
|
222
|
+
@global_options = global_options
|
|
223
|
+
@output = output
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
# Executes the command.
|
|
227
|
+
#
|
|
228
|
+
# @return [Integer] exit code
|
|
229
|
+
def execute
|
|
230
|
+
load_config
|
|
231
|
+
node = resolve_node
|
|
232
|
+
return config_error("node is required (provide --node or configure default-node)") unless node
|
|
233
|
+
|
|
234
|
+
case @operation
|
|
235
|
+
when :list then run_list(node)
|
|
236
|
+
when :update then run_update(node)
|
|
237
|
+
when :changelog then run_changelog(node)
|
|
238
|
+
when :versions then run_versions(node)
|
|
239
|
+
else
|
|
240
|
+
usage_error("Unknown apt operation: #{@operation}")
|
|
241
|
+
end
|
|
242
|
+
rescue Pvectl::Config::ConfigNotFoundError,
|
|
243
|
+
Pvectl::Config::InvalidConfigError,
|
|
244
|
+
Pvectl::Config::ContextNotFoundError,
|
|
245
|
+
Pvectl::Config::ClusterNotFoundError,
|
|
246
|
+
Pvectl::Config::UserNotFoundError => e
|
|
247
|
+
$stderr.puts "Error: #{e.message}"
|
|
248
|
+
ExitCodes::CONFIG_ERROR
|
|
249
|
+
rescue StandardError => e
|
|
250
|
+
$stderr.puts "Error: #{e.message}"
|
|
251
|
+
ExitCodes::GENERAL_ERROR
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
private
|
|
255
|
+
|
|
256
|
+
# Loads configuration.
|
|
257
|
+
#
|
|
258
|
+
# @return [void]
|
|
259
|
+
def load_config
|
|
260
|
+
service = Pvectl::Config::Service.new
|
|
261
|
+
service.load(config: @global_options[:config])
|
|
262
|
+
@config = service.current_config
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
# Resolves the node from --node option or default-node config.
|
|
266
|
+
#
|
|
267
|
+
# @return [String, nil] node name or nil if unresolvable
|
|
268
|
+
def resolve_node
|
|
269
|
+
@options[:node] || @config&.default_node
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
# Returns the apt repository (lazy).
|
|
273
|
+
#
|
|
274
|
+
# @return [Repositories::Apt] APT repository
|
|
275
|
+
def repository
|
|
276
|
+
@repository ||= Pvectl::Repositories::Apt.new(Pvectl::Connection.new(@config))
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
# Runs `apt list` — prints pending updates as a table.
|
|
280
|
+
#
|
|
281
|
+
# @param node [String] node name
|
|
282
|
+
# @return [Integer] exit code
|
|
283
|
+
def run_list(node)
|
|
284
|
+
packages = repository.pending(node)
|
|
285
|
+
render_packages(packages)
|
|
286
|
+
ExitCodes::SUCCESS
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
# Runs `apt update` — triggers index refresh and reports the UPID.
|
|
290
|
+
#
|
|
291
|
+
# @param node [String] node name
|
|
292
|
+
# @return [Integer] exit code
|
|
293
|
+
def run_update(node)
|
|
294
|
+
upid = repository.refresh(node, notify: @options[:notify] ? true : false,
|
|
295
|
+
quiet: @options[:quiet] ? true : false)
|
|
296
|
+
result = build_update_result(node, upid)
|
|
297
|
+
render_operation_result(result)
|
|
298
|
+
ExitCodes::SUCCESS
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
# Runs `apt changelog` — prints raw changelog text to stdout.
|
|
302
|
+
#
|
|
303
|
+
# @param node [String] node name
|
|
304
|
+
# @return [Integer] exit code
|
|
305
|
+
def run_changelog(node)
|
|
306
|
+
return usage_error("package name is required") if @args.empty?
|
|
307
|
+
|
|
308
|
+
package = @args.first
|
|
309
|
+
version = @options[:version]
|
|
310
|
+
text = repository.changelog(node, package, version: version)
|
|
311
|
+
if text.nil? || text.empty?
|
|
312
|
+
@output.puts "(no changelog available)"
|
|
313
|
+
else
|
|
314
|
+
@output.puts text
|
|
315
|
+
end
|
|
316
|
+
ExitCodes::SUCCESS
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
# Runs `apt versions` — lists important Proxmox package versions.
|
|
320
|
+
#
|
|
321
|
+
# @param node [String] node name
|
|
322
|
+
# @return [Integer] exit code
|
|
323
|
+
def run_versions(node)
|
|
324
|
+
packages = repository.versions(node)
|
|
325
|
+
render_packages(packages)
|
|
326
|
+
ExitCodes::SUCCESS
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
# Renders an array of AptPackage models using the configured formatter.
|
|
330
|
+
#
|
|
331
|
+
# @param packages [Array<Models::AptPackage>] packages
|
|
332
|
+
# @return [void]
|
|
333
|
+
def render_packages(packages)
|
|
334
|
+
Pvectl::Formatters::OutputHelper.print(
|
|
335
|
+
data: packages,
|
|
336
|
+
presenter: Pvectl::Presenters::AptPackage.new,
|
|
337
|
+
format: @global_options[:output] || "table",
|
|
338
|
+
color_flag: @global_options[:color]
|
|
339
|
+
)
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
# Renders a NodeOperationResult (used by `apt update`).
|
|
343
|
+
#
|
|
344
|
+
# @param result [Models::NodeOperationResult] operation result
|
|
345
|
+
# @return [void]
|
|
346
|
+
def render_operation_result(result)
|
|
347
|
+
Pvectl::Formatters::OutputHelper.print(
|
|
348
|
+
data: [result],
|
|
349
|
+
presenter: Pvectl::Presenters::NodeOperationResult.new,
|
|
350
|
+
format: @global_options[:output] || "table",
|
|
351
|
+
color_flag: @global_options[:color]
|
|
352
|
+
)
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
# Builds a NodeOperationResult representing an apt update kick-off.
|
|
356
|
+
#
|
|
357
|
+
# @param node [String] node name
|
|
358
|
+
# @param upid [String] task UPID returned by the API
|
|
359
|
+
# @return [Models::NodeOperationResult]
|
|
360
|
+
def build_update_result(node, upid)
|
|
361
|
+
Pvectl::Models::NodeOperationResult.new(
|
|
362
|
+
operation: :update,
|
|
363
|
+
node_model: Pvectl::Models::Node.new(name: node),
|
|
364
|
+
resource: { node: node },
|
|
365
|
+
task_upid: upid,
|
|
366
|
+
success: :pending
|
|
367
|
+
)
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
# Outputs a usage error.
|
|
371
|
+
#
|
|
372
|
+
# @param message [String] error message
|
|
373
|
+
# @return [Integer] USAGE_ERROR exit code
|
|
374
|
+
def usage_error(message)
|
|
375
|
+
$stderr.puts "Error: #{message}"
|
|
376
|
+
ExitCodes::USAGE_ERROR
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
# Outputs a config error.
|
|
380
|
+
#
|
|
381
|
+
# @param message [String] error message
|
|
382
|
+
# @return [Integer] CONFIG_ERROR exit code
|
|
383
|
+
def config_error(message)
|
|
384
|
+
$stderr.puts "Error: #{message}"
|
|
385
|
+
ExitCodes::CONFIG_ERROR
|
|
386
|
+
end
|
|
387
|
+
end
|
|
388
|
+
end
|
|
389
|
+
end
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
# Handler for the `pvectl clone container` command.
|
|
6
|
+
#
|
|
7
|
+
# Clones a container by CTID, supporting full and linked clones,
|
|
8
|
+
# custom hostname, target node, storage, pool, and description.
|
|
9
|
+
# No batch operations - clones exactly one container at a time.
|
|
10
|
+
#
|
|
11
|
+
# @example Full clone with auto-generated CTID
|
|
12
|
+
# pvectl clone container 100
|
|
13
|
+
#
|
|
14
|
+
# @example Clone with custom hostname and target CTID
|
|
15
|
+
# pvectl clone container 100 --vmid 200 --name web-clone
|
|
16
|
+
#
|
|
17
|
+
# @example Linked clone to different node
|
|
18
|
+
# pvectl clone container 100 --linked --target pve2
|
|
19
|
+
#
|
|
20
|
+
class CloneContainer
|
|
21
|
+
include SharedConfigParsers
|
|
22
|
+
|
|
23
|
+
# Executes the clone container command.
|
|
24
|
+
#
|
|
25
|
+
# @param args [Array<String>] command arguments (CTID)
|
|
26
|
+
# @param options [Hash] command options
|
|
27
|
+
# @param global_options [Hash] global CLI options
|
|
28
|
+
# @return [Integer] exit code
|
|
29
|
+
def self.execute(args, options, global_options)
|
|
30
|
+
new(args, options, global_options).execute
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Initializes a clone container command.
|
|
34
|
+
#
|
|
35
|
+
# @param args [Array<String>] command arguments
|
|
36
|
+
# @param options [Hash] command options
|
|
37
|
+
# @param global_options [Hash] global CLI options
|
|
38
|
+
def initialize(args, options, global_options)
|
|
39
|
+
@args = args
|
|
40
|
+
@options = options
|
|
41
|
+
@global_options = global_options
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Executes the clone container command.
|
|
45
|
+
#
|
|
46
|
+
# Builds config params from shared flags, validates async+config
|
|
47
|
+
# compatibility, and delegates to the clone operation.
|
|
48
|
+
#
|
|
49
|
+
# @return [Integer] exit code
|
|
50
|
+
def execute
|
|
51
|
+
ctid = @args.first
|
|
52
|
+
return usage_error("Source CTID required") unless ctid
|
|
53
|
+
|
|
54
|
+
config_params = build_ct_config_params
|
|
55
|
+
|
|
56
|
+
if @options[:async] && !config_params.empty?
|
|
57
|
+
return usage_error("Config flags require sync mode (remove --async)")
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
perform_clone(ctid.to_i, config_params)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
private
|
|
64
|
+
|
|
65
|
+
# Performs the clone operation.
|
|
66
|
+
#
|
|
67
|
+
# When config params are present, displays a summary and prompts
|
|
68
|
+
# for confirmation before proceeding. Passes config_params to the
|
|
69
|
+
# service for the two-step clone+configure flow.
|
|
70
|
+
#
|
|
71
|
+
# @param ctid [Integer] source container identifier
|
|
72
|
+
# @param config_params [Hash] container config parameters to apply after clone
|
|
73
|
+
# @return [Integer] exit code
|
|
74
|
+
def perform_clone(ctid, config_params)
|
|
75
|
+
unless config_params.empty?
|
|
76
|
+
return ExitCodes::SUCCESS if display_clone_summary(ctid, config_params) == :cancelled
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
load_config
|
|
80
|
+
connection = Pvectl::Connection.new(@config)
|
|
81
|
+
|
|
82
|
+
ct_repo = Pvectl::Repositories::Container.new(connection)
|
|
83
|
+
task_repo = Pvectl::Repositories::Task.new(connection)
|
|
84
|
+
|
|
85
|
+
service = Pvectl::Services::CloneContainer.new(
|
|
86
|
+
container_repository: ct_repo,
|
|
87
|
+
task_repository: task_repo,
|
|
88
|
+
options: service_options
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
result = service.execute(
|
|
92
|
+
ctid: ctid,
|
|
93
|
+
new_ctid: @options[:newid]&.to_i,
|
|
94
|
+
hostname: @options[:name],
|
|
95
|
+
target_node: @options[:target],
|
|
96
|
+
storage: @options[:storage],
|
|
97
|
+
linked: @options[:linked],
|
|
98
|
+
pool: @options[:pool],
|
|
99
|
+
description: @options[:description],
|
|
100
|
+
config_params: config_params
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
print_progress(result) if !@options[:async] && result.container
|
|
104
|
+
|
|
105
|
+
output_result(result)
|
|
106
|
+
result.failed? ? ExitCodes::GENERAL_ERROR : ExitCodes::SUCCESS
|
|
107
|
+
rescue Pvectl::Config::ConfigNotFoundError,
|
|
108
|
+
Pvectl::Config::InvalidConfigError,
|
|
109
|
+
Pvectl::Config::ContextNotFoundError,
|
|
110
|
+
Pvectl::Config::ClusterNotFoundError,
|
|
111
|
+
Pvectl::Config::UserNotFoundError
|
|
112
|
+
raise
|
|
113
|
+
rescue StandardError => e
|
|
114
|
+
$stderr.puts "Error: #{e.message}"
|
|
115
|
+
ExitCodes::GENERAL_ERROR
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Prints progress message for sync mode.
|
|
119
|
+
#
|
|
120
|
+
# @param result [Models::ContainerOperationResult] clone result
|
|
121
|
+
# @return [void]
|
|
122
|
+
def print_progress(result)
|
|
123
|
+
source = result.container
|
|
124
|
+
new_hostname = result.resource&.dig(:hostname) || "clone"
|
|
125
|
+
new_id = result.resource&.dig(:new_ctid)
|
|
126
|
+
$stderr.puts "Cloning container #{source.vmid} (#{source.name || 'unnamed'}) to #{new_id} (#{new_hostname})..."
|
|
127
|
+
$stderr.puts ""
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# Loads configuration from file or environment.
|
|
131
|
+
#
|
|
132
|
+
# @return [void]
|
|
133
|
+
def load_config
|
|
134
|
+
service = Pvectl::Config::Service.new
|
|
135
|
+
service.load(config: @global_options[:config])
|
|
136
|
+
@config = service.current_config
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Builds service options from command options.
|
|
140
|
+
#
|
|
141
|
+
# @return [Hash] service options
|
|
142
|
+
def service_options
|
|
143
|
+
opts = {}
|
|
144
|
+
opts[:timeout] = @options[:timeout] if @options[:timeout]
|
|
145
|
+
opts[:async] = true if @options[:async]
|
|
146
|
+
opts[:start] = true if @options[:start]
|
|
147
|
+
opts
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# Outputs operation result using the configured formatter.
|
|
151
|
+
#
|
|
152
|
+
# @param result [Models::ContainerOperationResult] operation result
|
|
153
|
+
# @return [void]
|
|
154
|
+
def output_result(result)
|
|
155
|
+
presenter = Pvectl::Presenters::ContainerOperationResult.new
|
|
156
|
+
format = @global_options[:output] || "table"
|
|
157
|
+
color_flag = @global_options[:color]
|
|
158
|
+
|
|
159
|
+
formatter = Pvectl::Formatters::Registry.for(format)
|
|
160
|
+
output = formatter.format([result], presenter, color: color_flag)
|
|
161
|
+
puts output
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# Displays clone summary with config changes and prompts for confirmation.
|
|
165
|
+
#
|
|
166
|
+
# Only called when config params are present. Shows source/target info
|
|
167
|
+
# and the config changes that will be applied after cloning.
|
|
168
|
+
#
|
|
169
|
+
# @param ctid [Integer] source container identifier
|
|
170
|
+
# @param config_params [Hash] config parameters to display
|
|
171
|
+
# @return [Symbol, nil] +:cancelled+ if user declines, +nil+ otherwise
|
|
172
|
+
def display_clone_summary(ctid, config_params)
|
|
173
|
+
$stdout.puts ""
|
|
174
|
+
$stdout.puts " Clone Container - Summary"
|
|
175
|
+
$stdout.puts " #{'─' * 40}"
|
|
176
|
+
$stdout.puts " Source: #{ctid}"
|
|
177
|
+
$stdout.puts " New ID: #{@options[:newid] || '(auto)'}"
|
|
178
|
+
$stdout.puts " Hostname: #{@options[:name] || '(auto)'}"
|
|
179
|
+
target_display = @options[:target] ? "→ #{@options[:target]}" : "(same)"
|
|
180
|
+
$stdout.puts " Node: #{target_display}"
|
|
181
|
+
$stdout.puts " Storage: #{@options[:storage]}" if @options[:storage]
|
|
182
|
+
display_config_changes(config_params)
|
|
183
|
+
$stdout.puts " #{'─' * 40}"
|
|
184
|
+
$stdout.puts ""
|
|
185
|
+
|
|
186
|
+
return nil if @options[:yes]
|
|
187
|
+
|
|
188
|
+
$stdout.print "Clone and configure this container? [y/N] "
|
|
189
|
+
$stdout.flush
|
|
190
|
+
answer = $stdin.gets&.strip&.downcase
|
|
191
|
+
answer == "y" ? nil : :cancelled
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
# Displays the config changes section of the clone summary.
|
|
195
|
+
#
|
|
196
|
+
# @param params [Hash] config parameters
|
|
197
|
+
# @return [void]
|
|
198
|
+
def display_config_changes(params)
|
|
199
|
+
$stdout.puts " ── Config changes #{'─' * 23}"
|
|
200
|
+
$stdout.puts " CPU: #{params[:cores]} cores" if params[:cores]
|
|
201
|
+
$stdout.puts " Memory: #{params[:memory]} MB" if params[:memory]
|
|
202
|
+
$stdout.puts " Swap: #{params[:swap]} MB" if params[:swap]
|
|
203
|
+
if params[:rootfs]
|
|
204
|
+
$stdout.puts " RootFS: #{params[:rootfs][:storage]}, #{params[:rootfs][:size]}"
|
|
205
|
+
end
|
|
206
|
+
if params[:mountpoints]
|
|
207
|
+
params[:mountpoints].each_with_index do |mp, i|
|
|
208
|
+
$stdout.puts " MP#{i}: #{mp[:mp]}, #{mp[:storage]}"
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
if params[:nets]
|
|
212
|
+
params[:nets].each_with_index do |n, i|
|
|
213
|
+
$stdout.puts " Net#{i}: #{n[:bridge]}"
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
$stdout.puts " Privileged: yes" if params[:privileged]
|
|
217
|
+
$stdout.puts " Tags: #{params[:tags]}" if params[:tags]
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
# Outputs usage error and returns exit code.
|
|
221
|
+
#
|
|
222
|
+
# @param message [String] error message
|
|
223
|
+
# @return [Integer] exit code
|
|
224
|
+
def usage_error(message)
|
|
225
|
+
$stderr.puts "Error: #{message}"
|
|
226
|
+
ExitCodes::USAGE_ERROR
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
end
|