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,185 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
# Shared functionality for resource set commands.
|
|
6
|
+
#
|
|
7
|
+
# Template method pattern: provides common set workflow
|
|
8
|
+
# (config loading, key-value parsing, diff display, dry-run)
|
|
9
|
+
# while specialization classes define resource-specific hooks.
|
|
10
|
+
#
|
|
11
|
+
# @abstract Include this module and implement template methods.
|
|
12
|
+
#
|
|
13
|
+
# @example Specialization
|
|
14
|
+
# class SetVm
|
|
15
|
+
# include SetResourceCommand
|
|
16
|
+
# private
|
|
17
|
+
# def resource_label = "VM"
|
|
18
|
+
# def resource_id_label = "VMID"
|
|
19
|
+
# # ...
|
|
20
|
+
# end
|
|
21
|
+
#
|
|
22
|
+
module SetResourceCommand
|
|
23
|
+
# Class methods added when the module is included.
|
|
24
|
+
module ClassMethods
|
|
25
|
+
# Executes the set command.
|
|
26
|
+
#
|
|
27
|
+
# @param args [Array<String>] command arguments
|
|
28
|
+
# @param options [Hash] command options
|
|
29
|
+
# @param global_options [Hash] global CLI options
|
|
30
|
+
# @return [Integer] exit code
|
|
31
|
+
def execute(args, options, global_options)
|
|
32
|
+
new(args, options, global_options).execute
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Hook called when module is included.
|
|
37
|
+
#
|
|
38
|
+
# @param base [Class] the class including this module
|
|
39
|
+
def self.included(base)
|
|
40
|
+
base.extend(ClassMethods)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Initializes a set command.
|
|
44
|
+
#
|
|
45
|
+
# @param args [Array<String>] command arguments
|
|
46
|
+
# @param options [Hash] command options
|
|
47
|
+
# @param global_options [Hash] global CLI options
|
|
48
|
+
def initialize(args, options, global_options)
|
|
49
|
+
@args = args
|
|
50
|
+
@options = options
|
|
51
|
+
@global_options = global_options
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Executes the set command.
|
|
55
|
+
#
|
|
56
|
+
# @return [Integer] exit code
|
|
57
|
+
def execute
|
|
58
|
+
resource_id = @args.first
|
|
59
|
+
return usage_error("#{resource_id_label} is required") unless resource_id
|
|
60
|
+
|
|
61
|
+
key_values = parse_key_values(@args[1..])
|
|
62
|
+
return usage_error("At least one key=value pair is required") if key_values.empty?
|
|
63
|
+
|
|
64
|
+
load_config
|
|
65
|
+
connection = Pvectl::Connection.new(@config)
|
|
66
|
+
service = build_set_service(connection)
|
|
67
|
+
result = service.execute(**execute_params(resource_id, key_values))
|
|
68
|
+
|
|
69
|
+
if result.nil?
|
|
70
|
+
$stdout.puts "No changes detected."
|
|
71
|
+
return ExitCodes::SUCCESS
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
if result.successful?
|
|
75
|
+
display_diff(result)
|
|
76
|
+
if @options[:"dry-run"]
|
|
77
|
+
$stdout.puts "(dry-run mode — no changes applied)"
|
|
78
|
+
else
|
|
79
|
+
$stdout.puts "#{resource_label} #{resource_id} updated successfully."
|
|
80
|
+
end
|
|
81
|
+
ExitCodes::SUCCESS
|
|
82
|
+
else
|
|
83
|
+
$stderr.puts "Error: #{result.error}"
|
|
84
|
+
ExitCodes::GENERAL_ERROR
|
|
85
|
+
end
|
|
86
|
+
rescue Pvectl::Config::ConfigNotFoundError,
|
|
87
|
+
Pvectl::Config::InvalidConfigError,
|
|
88
|
+
Pvectl::Config::ContextNotFoundError,
|
|
89
|
+
Pvectl::Config::ClusterNotFoundError,
|
|
90
|
+
Pvectl::Config::UserNotFoundError
|
|
91
|
+
raise
|
|
92
|
+
rescue StandardError => e
|
|
93
|
+
$stderr.puts "Error: #{e.message}"
|
|
94
|
+
ExitCodes::GENERAL_ERROR
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
private
|
|
98
|
+
|
|
99
|
+
# @return [String] human label for resource
|
|
100
|
+
def resource_label
|
|
101
|
+
raise NotImplementedError, "#{self.class} must implement #resource_label"
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# @return [String] human label for resource ID
|
|
105
|
+
def resource_id_label
|
|
106
|
+
raise NotImplementedError, "#{self.class} must implement #resource_id_label"
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Builds execution parameters.
|
|
110
|
+
#
|
|
111
|
+
# @param resource_id [String] resource identifier
|
|
112
|
+
# @param key_values [Hash] parsed key-value pairs
|
|
113
|
+
# @return [Hash] parameters for the service
|
|
114
|
+
def execute_params(resource_id, key_values)
|
|
115
|
+
raise NotImplementedError, "#{self.class} must implement #execute_params"
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Builds the set service.
|
|
119
|
+
#
|
|
120
|
+
# @param connection [Connection] API connection
|
|
121
|
+
# @return [Object] set service instance
|
|
122
|
+
def build_set_service(connection)
|
|
123
|
+
raise NotImplementedError, "#{self.class} must implement #build_set_service"
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Parses key=value pairs from argument list.
|
|
127
|
+
#
|
|
128
|
+
# @param args [Array<String>] arguments like ["memory=4096", "cores=2"]
|
|
129
|
+
# @return [Hash] parsed pairs { "memory" => "4096", "cores" => "2" }
|
|
130
|
+
def parse_key_values(args)
|
|
131
|
+
pairs = {}
|
|
132
|
+
(args || []).each do |arg|
|
|
133
|
+
unless arg.include?("=")
|
|
134
|
+
$stderr.puts "Warning: Ignoring argument without '=': #{arg}"
|
|
135
|
+
next
|
|
136
|
+
end
|
|
137
|
+
key, value = arg.split("=", 2)
|
|
138
|
+
pairs[key] = value
|
|
139
|
+
end
|
|
140
|
+
pairs
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Displays a formatted diff from the operation result.
|
|
144
|
+
#
|
|
145
|
+
# @param result [Models::OperationResult] operation result
|
|
146
|
+
# @return [void]
|
|
147
|
+
def display_diff(result)
|
|
148
|
+
diff = result.resource&.dig(:diff)
|
|
149
|
+
return unless diff
|
|
150
|
+
return if diff[:changed].empty? && diff[:added].empty? && diff[:removed].empty?
|
|
151
|
+
|
|
152
|
+
$stdout.puts "\nChanges:"
|
|
153
|
+
$stdout.puts Pvectl::ConfigSerializer.format_diff(diff)
|
|
154
|
+
$stdout.puts ""
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# Loads configuration.
|
|
158
|
+
#
|
|
159
|
+
# @return [void]
|
|
160
|
+
def load_config
|
|
161
|
+
service = Pvectl::Config::Service.new
|
|
162
|
+
service.load(config: @global_options[:config])
|
|
163
|
+
@config = service.current_config
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# Outputs usage error.
|
|
167
|
+
#
|
|
168
|
+
# @param message [String] error message
|
|
169
|
+
# @return [Integer] exit code
|
|
170
|
+
def usage_error(message)
|
|
171
|
+
$stderr.puts "Error: #{message}"
|
|
172
|
+
ExitCodes::USAGE_ERROR
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# Returns service options.
|
|
176
|
+
#
|
|
177
|
+
# @return [Hash] service options
|
|
178
|
+
def service_options
|
|
179
|
+
opts = {}
|
|
180
|
+
opts[:dry_run] = true if @options[:"dry-run"]
|
|
181
|
+
opts
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
# Handler for the `pvectl set vm` command.
|
|
6
|
+
#
|
|
7
|
+
# Includes SetResourceCommand for shared workflow and overrides
|
|
8
|
+
# template methods with VM-specific behavior.
|
|
9
|
+
#
|
|
10
|
+
# Also registers the top-level `set` command with all resource types.
|
|
11
|
+
#
|
|
12
|
+
# @example Basic usage
|
|
13
|
+
# pvectl set vm 100 memory=4096 cores=2
|
|
14
|
+
#
|
|
15
|
+
# @example Dry-run mode
|
|
16
|
+
# pvectl set vm 100 memory=8192 --dry-run
|
|
17
|
+
#
|
|
18
|
+
class SetVm
|
|
19
|
+
include SetResourceCommand
|
|
20
|
+
|
|
21
|
+
# Registers the set command with the CLI.
|
|
22
|
+
#
|
|
23
|
+
# @param cli [GLI::App] the CLI application object
|
|
24
|
+
# @return [void]
|
|
25
|
+
def self.register(cli)
|
|
26
|
+
cli.desc "Set a resource property (non-interactive)"
|
|
27
|
+
cli.long_desc <<~HELP
|
|
28
|
+
Set configuration properties on a resource without opening an editor.
|
|
29
|
+
Accepts key=value pairs as arguments. This is the non-interactive
|
|
30
|
+
counterpart to the edit command.
|
|
31
|
+
|
|
32
|
+
EXAMPLES
|
|
33
|
+
Set VM memory and CPU:
|
|
34
|
+
$ pvectl set vm 100 memory=4096 cores=2
|
|
35
|
+
|
|
36
|
+
Set container hostname:
|
|
37
|
+
$ pvectl set container 200 hostname=web01
|
|
38
|
+
|
|
39
|
+
Resize a volume:
|
|
40
|
+
$ pvectl set volume vm 100 scsi0 size=+10G
|
|
41
|
+
|
|
42
|
+
Set volume cache mode:
|
|
43
|
+
$ pvectl set volume vm 100 scsi0 cache=writeback
|
|
44
|
+
|
|
45
|
+
Set node description:
|
|
46
|
+
$ pvectl set node pve1 description="Production node"
|
|
47
|
+
|
|
48
|
+
Change node timezone:
|
|
49
|
+
$ pvectl set node pve1 timezone=Europe/Warsaw
|
|
50
|
+
|
|
51
|
+
Preview changes without applying:
|
|
52
|
+
$ pvectl set vm 100 memory=8192 --dry-run
|
|
53
|
+
|
|
54
|
+
NOTES
|
|
55
|
+
Volume resize (size=) is irreversible. A confirmation prompt is shown
|
|
56
|
+
unless --yes is specified.
|
|
57
|
+
|
|
58
|
+
Keys are passed directly to the Proxmox API. Use Proxmox documentation
|
|
59
|
+
to find valid configuration keys for each resource type.
|
|
60
|
+
|
|
61
|
+
SEE ALSO
|
|
62
|
+
pvectl help edit Interactive configuration editor
|
|
63
|
+
pvectl help describe View current configuration
|
|
64
|
+
HELP
|
|
65
|
+
cli.arg_name "RESOURCE_TYPE RESOURCE_ID [SUB_ID] KEY=VALUE [KEY=VALUE ...]"
|
|
66
|
+
cli.command :set do |c|
|
|
67
|
+
c.desc "Skip confirmation prompt"
|
|
68
|
+
c.switch [:yes, :y], negatable: false
|
|
69
|
+
|
|
70
|
+
c.desc "Target node name"
|
|
71
|
+
c.flag [:node, :n], arg_name: "NODE"
|
|
72
|
+
|
|
73
|
+
c.desc "Show diff without applying changes"
|
|
74
|
+
c.switch [:"dry-run"], negatable: false
|
|
75
|
+
|
|
76
|
+
c.action do |global_options, options, args|
|
|
77
|
+
resource_type = args.shift
|
|
78
|
+
|
|
79
|
+
exit_code = case resource_type
|
|
80
|
+
when "vm"
|
|
81
|
+
Commands::SetVm.execute(args, options, global_options)
|
|
82
|
+
when "container", "ct"
|
|
83
|
+
Commands::SetContainer.execute(args, options, global_options)
|
|
84
|
+
when "volume", "vol"
|
|
85
|
+
Commands::SetVolume.execute(args, options, global_options)
|
|
86
|
+
when "node"
|
|
87
|
+
Commands::SetNode.execute(args, options, global_options)
|
|
88
|
+
when nil
|
|
89
|
+
$stderr.puts "Error: Resource type required (vm, container, volume, node)"
|
|
90
|
+
ExitCodes::USAGE_ERROR
|
|
91
|
+
else
|
|
92
|
+
$stderr.puts "Error: Unknown resource type: #{resource_type}"
|
|
93
|
+
$stderr.puts "Valid types: vm, container, volume, node"
|
|
94
|
+
ExitCodes::USAGE_ERROR
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
exit exit_code if exit_code != 0
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
private
|
|
103
|
+
|
|
104
|
+
# @return [String] human label for VM resources
|
|
105
|
+
def resource_label
|
|
106
|
+
"VM"
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# @return [String] human label for VM IDs
|
|
110
|
+
def resource_id_label
|
|
111
|
+
"VMID"
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Builds execution parameters from a VM ID.
|
|
115
|
+
#
|
|
116
|
+
# @param resource_id [String] VMID
|
|
117
|
+
# @param key_values [Hash] parsed key-value pairs
|
|
118
|
+
# @return [Hash] parameters for the set service
|
|
119
|
+
def execute_params(resource_id, key_values)
|
|
120
|
+
{ vmid: resource_id.to_i, params: key_values }
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Builds the VM set service.
|
|
124
|
+
#
|
|
125
|
+
# @param connection [Connection] API connection
|
|
126
|
+
# @return [Services::SetVm] VM set service
|
|
127
|
+
def build_set_service(connection)
|
|
128
|
+
vm_repo = Pvectl::Repositories::Vm.new(connection)
|
|
129
|
+
Pvectl::Services::SetVm.new(
|
|
130
|
+
vm_repository: vm_repo,
|
|
131
|
+
options: service_options
|
|
132
|
+
)
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
# Handler for the `pvectl set volume` command.
|
|
6
|
+
#
|
|
7
|
+
# Does NOT use SetResourceCommand template — has custom flow due to
|
|
8
|
+
# different argument structure (resource_type + id + disk + key=value).
|
|
9
|
+
#
|
|
10
|
+
# @example Resize volume
|
|
11
|
+
# pvectl set volume vm 100 scsi0 size=+10G
|
|
12
|
+
#
|
|
13
|
+
# @example Set cache mode
|
|
14
|
+
# pvectl set volume vm 100 scsi0 cache=writeback
|
|
15
|
+
#
|
|
16
|
+
# @example Mixed operations
|
|
17
|
+
# pvectl set volume vm 100 scsi0 size=+10G cache=writeback --yes
|
|
18
|
+
#
|
|
19
|
+
class SetVolume
|
|
20
|
+
# Class methods for command execution.
|
|
21
|
+
module ClassMethods
|
|
22
|
+
# Executes the set volume command.
|
|
23
|
+
#
|
|
24
|
+
# @param args [Array<String>] command arguments
|
|
25
|
+
# @param options [Hash] command options
|
|
26
|
+
# @param global_options [Hash] global CLI options
|
|
27
|
+
# @return [Integer] exit code
|
|
28
|
+
def execute(args, options, global_options)
|
|
29
|
+
new(args, options, global_options).execute
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
extend ClassMethods
|
|
34
|
+
|
|
35
|
+
# Initializes a set volume command.
|
|
36
|
+
#
|
|
37
|
+
# @param args [Array<String>] command arguments
|
|
38
|
+
# @param options [Hash] command options
|
|
39
|
+
# @param global_options [Hash] global CLI options
|
|
40
|
+
def initialize(args, options, global_options)
|
|
41
|
+
@args = args
|
|
42
|
+
@options = options
|
|
43
|
+
@global_options = global_options
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Executes the set volume command.
|
|
47
|
+
#
|
|
48
|
+
# @return [Integer] exit code
|
|
49
|
+
def execute
|
|
50
|
+
resource_type = @args[0]
|
|
51
|
+
resource_id = @args[1]
|
|
52
|
+
disk = @args[2]
|
|
53
|
+
key_value_args = @args[3..] || []
|
|
54
|
+
|
|
55
|
+
return usage_error("Resource type required (vm, container)") unless resource_type
|
|
56
|
+
return usage_error("Resource ID is required") unless resource_id
|
|
57
|
+
return usage_error("Volume name is required (e.g., scsi0, rootfs)") unless disk
|
|
58
|
+
|
|
59
|
+
key_values = parse_key_values(key_value_args)
|
|
60
|
+
return usage_error("At least one key=value pair is required") if key_values.empty?
|
|
61
|
+
|
|
62
|
+
load_config
|
|
63
|
+
connection = Pvectl::Connection.new(@config)
|
|
64
|
+
|
|
65
|
+
node = resolve_node(resource_id.to_i, connection, resource_type)
|
|
66
|
+
return ExitCodes::NOT_FOUND unless node
|
|
67
|
+
|
|
68
|
+
# Confirmation for resize operations
|
|
69
|
+
if key_values.key?("size") && !@options[:yes]
|
|
70
|
+
return ExitCodes::SUCCESS unless confirm_resize(resource_id, disk, key_values["size"])
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
repo = build_repository(connection, resource_type)
|
|
74
|
+
service = Pvectl::Services::SetVolume.new(
|
|
75
|
+
repository: repo,
|
|
76
|
+
resource_type: resource_type_symbol(resource_type)
|
|
77
|
+
)
|
|
78
|
+
result = service.execute(id: resource_id.to_i, disk: disk, params: key_values, node: node)
|
|
79
|
+
|
|
80
|
+
output_result(result)
|
|
81
|
+
|
|
82
|
+
result.successful? ? ExitCodes::SUCCESS : ExitCodes::GENERAL_ERROR
|
|
83
|
+
rescue Pvectl::Config::ConfigNotFoundError,
|
|
84
|
+
Pvectl::Config::InvalidConfigError,
|
|
85
|
+
Pvectl::Config::ContextNotFoundError,
|
|
86
|
+
Pvectl::Config::ClusterNotFoundError,
|
|
87
|
+
Pvectl::Config::UserNotFoundError
|
|
88
|
+
raise
|
|
89
|
+
rescue StandardError => e
|
|
90
|
+
$stderr.puts "Error: #{e.message}"
|
|
91
|
+
ExitCodes::GENERAL_ERROR
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
private
|
|
95
|
+
|
|
96
|
+
# Parses key=value pairs from argument list.
|
|
97
|
+
#
|
|
98
|
+
# @param args [Array<String>] arguments
|
|
99
|
+
# @return [Hash] parsed pairs
|
|
100
|
+
def parse_key_values(args)
|
|
101
|
+
pairs = {}
|
|
102
|
+
args.each do |arg|
|
|
103
|
+
unless arg.include?("=")
|
|
104
|
+
$stderr.puts "Warning: Ignoring argument without '=': #{arg}"
|
|
105
|
+
next
|
|
106
|
+
end
|
|
107
|
+
key, value = arg.split("=", 2)
|
|
108
|
+
pairs[key] = value
|
|
109
|
+
end
|
|
110
|
+
pairs
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Resolves node for a resource.
|
|
114
|
+
#
|
|
115
|
+
# @param resource_id [Integer] resource ID
|
|
116
|
+
# @param connection [Connection] API connection
|
|
117
|
+
# @param resource_type [String] resource type
|
|
118
|
+
# @return [String, nil] node name or nil
|
|
119
|
+
def resolve_node(resource_id, connection, resource_type)
|
|
120
|
+
return @options[:node] if @options[:node]
|
|
121
|
+
|
|
122
|
+
resolver = Pvectl::Utils::ResourceResolver.new(connection)
|
|
123
|
+
resolved = resolver.resolve(resource_id)
|
|
124
|
+
|
|
125
|
+
unless resolved
|
|
126
|
+
label = resource_type == "vm" ? "VM" : "container"
|
|
127
|
+
$stderr.puts "Error: #{label} #{resource_id} not found"
|
|
128
|
+
return nil
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
resolved[:node]
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Confirms resize operation.
|
|
135
|
+
#
|
|
136
|
+
# @param resource_id [String] resource ID
|
|
137
|
+
# @param disk [String] disk name
|
|
138
|
+
# @param size [String] size value
|
|
139
|
+
# @return [Boolean] true if should proceed
|
|
140
|
+
def confirm_resize(resource_id, disk, size)
|
|
141
|
+
$stdout.puts "Resize volume #{disk} on resource #{resource_id}:"
|
|
142
|
+
$stdout.puts " New size: #{size}"
|
|
143
|
+
$stdout.puts ""
|
|
144
|
+
$stdout.puts "This action is IRREVERSIBLE — volumes cannot be shrunk via API."
|
|
145
|
+
$stdout.print "Proceed? [y/N]: "
|
|
146
|
+
|
|
147
|
+
response = $stdin.gets&.strip&.downcase
|
|
148
|
+
%w[y yes].include?(response)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# Builds repository for resource type.
|
|
152
|
+
#
|
|
153
|
+
# @param connection [Connection] API connection
|
|
154
|
+
# @param resource_type [String] resource type
|
|
155
|
+
# @return [Repositories::Vm, Repositories::Container] repository
|
|
156
|
+
def build_repository(connection, resource_type)
|
|
157
|
+
case resource_type
|
|
158
|
+
when "vm"
|
|
159
|
+
Pvectl::Repositories::Vm.new(connection)
|
|
160
|
+
when "container", "ct"
|
|
161
|
+
Pvectl::Repositories::Container.new(connection)
|
|
162
|
+
else
|
|
163
|
+
raise ArgumentError, "Unknown resource type: #{resource_type}"
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# Converts string resource type to symbol.
|
|
168
|
+
#
|
|
169
|
+
# @param resource_type [String] resource type
|
|
170
|
+
# @return [Symbol] :vm or :container
|
|
171
|
+
def resource_type_symbol(resource_type)
|
|
172
|
+
case resource_type
|
|
173
|
+
when "vm" then :vm
|
|
174
|
+
when "container", "ct" then :container
|
|
175
|
+
else :vm
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
# Outputs operation result.
|
|
180
|
+
#
|
|
181
|
+
# @param result [Models::VolumeOperationResult] operation result
|
|
182
|
+
# @return [void]
|
|
183
|
+
def output_result(result)
|
|
184
|
+
presenter = Pvectl::Presenters::VolumeOperationResult.new
|
|
185
|
+
format = @global_options[:output] || "table"
|
|
186
|
+
color_flag = @global_options[:color]
|
|
187
|
+
|
|
188
|
+
formatter = Pvectl::Formatters::Registry.for(format)
|
|
189
|
+
output = formatter.format([result], presenter, color: color_flag)
|
|
190
|
+
puts output
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# Loads configuration.
|
|
194
|
+
#
|
|
195
|
+
# @return [void]
|
|
196
|
+
def load_config
|
|
197
|
+
service = Pvectl::Config::Service.new
|
|
198
|
+
service.load(config: @global_options[:config])
|
|
199
|
+
@config = service.current_config
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
# Outputs usage error.
|
|
203
|
+
#
|
|
204
|
+
# @param message [String] error message
|
|
205
|
+
# @return [Integer] exit code
|
|
206
|
+
def usage_error(message)
|
|
207
|
+
$stderr.puts "Error: #{message}"
|
|
208
|
+
ExitCodes::USAGE_ERROR
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
end
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
# Shared parser methods for CLI flag values.
|
|
6
|
+
#
|
|
7
|
+
# Provides reusable methods that parse --disk, --net, --cloud-init,
|
|
8
|
+
# --mp flags through their respective Parsers. Included by create
|
|
9
|
+
# and clone commands to avoid parser logic duplication.
|
|
10
|
+
#
|
|
11
|
+
# Expects +@options+ (a Hash of CLI flag values) to be available
|
|
12
|
+
# in the including class.
|
|
13
|
+
#
|
|
14
|
+
# @example Including in a command class
|
|
15
|
+
# class CreateVm
|
|
16
|
+
# include SharedConfigParsers
|
|
17
|
+
# # ...
|
|
18
|
+
# end
|
|
19
|
+
#
|
|
20
|
+
module SharedConfigParsers
|
|
21
|
+
# Parses VM disk configuration strings through the DiskConfig parser.
|
|
22
|
+
#
|
|
23
|
+
# @return [Array<Hash<Symbol, String>>] parsed disk configurations
|
|
24
|
+
# @raise [ArgumentError] if any disk string is invalid
|
|
25
|
+
def parse_vm_disks
|
|
26
|
+
Array(@options[:disk]).map { |d| Parsers::DiskConfig.parse(d) }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Parses VM network configuration strings through the NetConfig parser.
|
|
30
|
+
#
|
|
31
|
+
# @return [Array<Hash<Symbol, String>>] parsed network configurations
|
|
32
|
+
# @raise [ArgumentError] if any net string is invalid
|
|
33
|
+
def parse_vm_nets
|
|
34
|
+
Array(@options[:net]).map { |n| Parsers::NetConfig.parse(n) }
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Parses cloud-init configuration string and converts to Proxmox params.
|
|
38
|
+
#
|
|
39
|
+
# @return [Hash<Symbol, untyped>] Proxmox-compatible cloud-init parameters
|
|
40
|
+
# @raise [ArgumentError] if the cloud-init string is invalid
|
|
41
|
+
def parse_vm_cloud_init
|
|
42
|
+
config = Parsers::CloudInitConfig.parse(@options[:"cloud-init"])
|
|
43
|
+
Parsers::CloudInitConfig.to_proxmox_params(config)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Parses LXC mountpoint configuration strings through the LxcMountConfig parser.
|
|
47
|
+
#
|
|
48
|
+
# @return [Array<Hash<Symbol, String>>] parsed mountpoint configurations
|
|
49
|
+
# @raise [ArgumentError] if any mountpoint string is invalid
|
|
50
|
+
def parse_ct_mountpoints
|
|
51
|
+
Array(@options[:mp]).map { |m| Parsers::LxcMountConfig.parse(m) }
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Parses LXC network configuration strings through the LxcNetConfig parser.
|
|
55
|
+
#
|
|
56
|
+
# @return [Array<Hash<Symbol, String>>] parsed network configurations
|
|
57
|
+
# @raise [ArgumentError] if any net string is invalid
|
|
58
|
+
def parse_ct_nets
|
|
59
|
+
Array(@options[:net]).map { |n| Parsers::LxcNetConfig.parse(n) }
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Builds a VM config parameters hash from CLI options.
|
|
63
|
+
#
|
|
64
|
+
# Extracts VM-specific configuration keys from @options, parsing
|
|
65
|
+
# disk, network, and cloud-init flags through their respective parsers.
|
|
66
|
+
# Nil values are compacted out.
|
|
67
|
+
#
|
|
68
|
+
# @return [Hash<Symbol, untyped>] VM configuration parameters
|
|
69
|
+
# @raise [ArgumentError] if any parser validation fails
|
|
70
|
+
def build_vm_config_params
|
|
71
|
+
params = {
|
|
72
|
+
cores: @options[:cores],
|
|
73
|
+
sockets: @options[:sockets],
|
|
74
|
+
cpu_type: @options[:"cpu-type"],
|
|
75
|
+
numa: @options[:numa],
|
|
76
|
+
memory: @options[:memory],
|
|
77
|
+
balloon: @options[:balloon],
|
|
78
|
+
scsihw: @options[:scsihw],
|
|
79
|
+
cdrom: @options[:cdrom],
|
|
80
|
+
bios: @options[:bios],
|
|
81
|
+
boot_order: @options[:"boot-order"],
|
|
82
|
+
machine: @options[:machine],
|
|
83
|
+
efidisk: @options[:efidisk],
|
|
84
|
+
agent: @options[:agent],
|
|
85
|
+
ostype: @options[:ostype],
|
|
86
|
+
tags: @options[:tags]
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
params[:disks] = parse_vm_disks if @options[:disk]
|
|
90
|
+
params[:nets] = parse_vm_nets if @options[:net]
|
|
91
|
+
params[:cloud_init] = parse_vm_cloud_init if @options[:"cloud-init"]
|
|
92
|
+
|
|
93
|
+
params.compact
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Builds a container config parameters hash from CLI options.
|
|
97
|
+
#
|
|
98
|
+
# Extracts container-specific configuration keys from @options, parsing
|
|
99
|
+
# rootfs, mountpoint, and network flags through their respective parsers.
|
|
100
|
+
# Nil values are compacted out.
|
|
101
|
+
#
|
|
102
|
+
# @return [Hash<Symbol, untyped>] container configuration parameters
|
|
103
|
+
# @raise [ArgumentError] if any parser validation fails
|
|
104
|
+
def build_ct_config_params
|
|
105
|
+
params = {
|
|
106
|
+
cores: @options[:cores],
|
|
107
|
+
memory: @options[:memory],
|
|
108
|
+
swap: @options[:swap],
|
|
109
|
+
tags: @options[:tags],
|
|
110
|
+
features: @options[:features],
|
|
111
|
+
password: @options[:password],
|
|
112
|
+
ssh_public_keys: @options[:"ssh-public-keys"],
|
|
113
|
+
onboot: @options[:onboot],
|
|
114
|
+
startup: @options[:startup]
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
params[:rootfs] = Parsers::LxcMountConfig.parse(@options[:rootfs]) if @options[:rootfs]
|
|
118
|
+
params[:mountpoints] = parse_ct_mountpoints if @options[:mp]
|
|
119
|
+
params[:nets] = parse_ct_nets if @options[:net]
|
|
120
|
+
params[:privileged] = @options[:privileged]
|
|
121
|
+
|
|
122
|
+
params.compact
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|