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,173 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
# Handler for the `pvectl create backup` command.
|
|
6
|
+
#
|
|
7
|
+
# Creates backups for one or more VMs/containers.
|
|
8
|
+
# Supports multiple VMIDs with optional confirmation prompt.
|
|
9
|
+
#
|
|
10
|
+
# @example Create single backup
|
|
11
|
+
# pvectl create backup 100 --storage local
|
|
12
|
+
#
|
|
13
|
+
# @example Create backup for multiple VMs
|
|
14
|
+
# pvectl create backup 100 101 102 --storage nfs --mode snapshot
|
|
15
|
+
#
|
|
16
|
+
# @example Create backup with options
|
|
17
|
+
# pvectl create backup 100 --storage local --compress zstd --notes "Pre-upgrade" --protected
|
|
18
|
+
#
|
|
19
|
+
class CreateBackup
|
|
20
|
+
SUPPORTED_RESOURCES = %w[backup].freeze
|
|
21
|
+
|
|
22
|
+
# Executes the create backup command.
|
|
23
|
+
#
|
|
24
|
+
# @param resource_type [String, nil] resource type (backup)
|
|
25
|
+
# @param resource_ids [Array<String>, String, nil] VM identifiers
|
|
26
|
+
# @param options [Hash] command options
|
|
27
|
+
# @param global_options [Hash] global CLI options
|
|
28
|
+
# @return [Integer] exit code
|
|
29
|
+
def self.execute(resource_type, resource_ids, options, global_options)
|
|
30
|
+
new(resource_type, resource_ids, options, global_options).execute
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Initializes a create backup command.
|
|
34
|
+
#
|
|
35
|
+
# @param resource_type [String, nil] resource type (backup)
|
|
36
|
+
# @param resource_ids [Array<String>, String, nil] VM identifiers
|
|
37
|
+
# @param options [Hash] command options
|
|
38
|
+
# @param global_options [Hash] global CLI options
|
|
39
|
+
def initialize(resource_type, resource_ids, options, global_options)
|
|
40
|
+
@resource_type = resource_type
|
|
41
|
+
@resource_ids = Array(resource_ids).compact.map(&:to_i)
|
|
42
|
+
@options = options
|
|
43
|
+
@global_options = global_options
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Executes the create backup command.
|
|
47
|
+
#
|
|
48
|
+
# @return [Integer] exit code
|
|
49
|
+
def execute
|
|
50
|
+
return usage_error("Resource type required (backup)") unless @resource_type
|
|
51
|
+
return usage_error("Unsupported resource: #{@resource_type}") unless SUPPORTED_RESOURCES.include?(@resource_type)
|
|
52
|
+
return usage_error("At least one VMID is required") if @resource_ids.empty?
|
|
53
|
+
return usage_error("--storage is required") unless @options[:storage]
|
|
54
|
+
|
|
55
|
+
perform_operation
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
private
|
|
59
|
+
|
|
60
|
+
# Performs the backup creation operation.
|
|
61
|
+
#
|
|
62
|
+
# @return [Integer] exit code
|
|
63
|
+
def perform_operation
|
|
64
|
+
load_config
|
|
65
|
+
connection = Pvectl::Connection.new(@config)
|
|
66
|
+
|
|
67
|
+
backup_repo = Pvectl::Repositories::Backup.new(connection)
|
|
68
|
+
resolver = Pvectl::Utils::ResourceResolver.new(connection)
|
|
69
|
+
task_repo = Pvectl::Repositories::Task.new(connection)
|
|
70
|
+
|
|
71
|
+
service = Pvectl::Services::Backup.new(
|
|
72
|
+
backup_repo: backup_repo,
|
|
73
|
+
resource_resolver: resolver,
|
|
74
|
+
task_repo: task_repo,
|
|
75
|
+
options: service_options
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
return ExitCodes::SUCCESS unless confirm_operation
|
|
79
|
+
|
|
80
|
+
results = service.create(
|
|
81
|
+
@resource_ids,
|
|
82
|
+
storage: @options[:storage],
|
|
83
|
+
mode: @options[:mode] || "snapshot",
|
|
84
|
+
compress: @options[:compress] || "zstd",
|
|
85
|
+
notes: @options[:notes],
|
|
86
|
+
protected: @options[:protected] || false
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
output_results(results)
|
|
90
|
+
determine_exit_code(results)
|
|
91
|
+
rescue Pvectl::Config::ConfigNotFoundError,
|
|
92
|
+
Pvectl::Config::InvalidConfigError,
|
|
93
|
+
Pvectl::Config::ContextNotFoundError,
|
|
94
|
+
Pvectl::Config::ClusterNotFoundError,
|
|
95
|
+
Pvectl::Config::UserNotFoundError
|
|
96
|
+
raise
|
|
97
|
+
rescue StandardError => e
|
|
98
|
+
$stderr.puts "Error: #{e.message}"
|
|
99
|
+
ExitCodes::GENERAL_ERROR
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Confirms multi-VMID operation with user.
|
|
103
|
+
#
|
|
104
|
+
# @return [Boolean] true if operation should proceed
|
|
105
|
+
def confirm_operation
|
|
106
|
+
return true if @resource_ids.size == 1
|
|
107
|
+
return true if @options[:yes]
|
|
108
|
+
|
|
109
|
+
$stdout.puts "You are about to create backups for #{@resource_ids.size} VMs:"
|
|
110
|
+
@resource_ids.each { |vmid| $stdout.puts " - #{vmid}" }
|
|
111
|
+
$stdout.puts ""
|
|
112
|
+
$stdout.print "Proceed? [y/N]: "
|
|
113
|
+
|
|
114
|
+
response = $stdin.gets&.strip&.downcase
|
|
115
|
+
%w[y yes].include?(response)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Loads configuration from file or environment.
|
|
119
|
+
#
|
|
120
|
+
# @return [void]
|
|
121
|
+
def load_config
|
|
122
|
+
service = Pvectl::Config::Service.new
|
|
123
|
+
service.load(config: @global_options[:config])
|
|
124
|
+
@config = service.current_config
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Builds service options from command options.
|
|
128
|
+
#
|
|
129
|
+
# @return [Hash] service options
|
|
130
|
+
def service_options
|
|
131
|
+
opts = {}
|
|
132
|
+
opts[:timeout] = @options[:timeout] if @options[:timeout]
|
|
133
|
+
opts[:async] = true if @options[:async]
|
|
134
|
+
opts[:fail_fast] = true if @options[:"fail-fast"]
|
|
135
|
+
opts
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# Outputs operation results using the configured formatter.
|
|
139
|
+
#
|
|
140
|
+
# @param results [Array<Models::OperationResult>] operation results
|
|
141
|
+
# @return [void]
|
|
142
|
+
def output_results(results)
|
|
143
|
+
presenter = Pvectl::Presenters::SnapshotOperationResult.new
|
|
144
|
+
format = @global_options[:output] || "table"
|
|
145
|
+
color_flag = @global_options[:color]
|
|
146
|
+
|
|
147
|
+
formatter = Pvectl::Formatters::Registry.for(format)
|
|
148
|
+
output = formatter.format(results, presenter, color: color_flag)
|
|
149
|
+
puts output
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# Determines exit code based on results.
|
|
153
|
+
#
|
|
154
|
+
# @param results [Array<Models::OperationResult>] operation results
|
|
155
|
+
# @return [Integer] exit code
|
|
156
|
+
def determine_exit_code(results)
|
|
157
|
+
return ExitCodes::SUCCESS if results.all?(&:successful?)
|
|
158
|
+
return ExitCodes::SUCCESS if results.all?(&:pending?)
|
|
159
|
+
|
|
160
|
+
ExitCodes::GENERAL_ERROR
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Outputs usage error and returns exit code.
|
|
164
|
+
#
|
|
165
|
+
# @param message [String] error message
|
|
166
|
+
# @return [Integer] exit code
|
|
167
|
+
def usage_error(message)
|
|
168
|
+
$stderr.puts "Error: #{message}"
|
|
169
|
+
ExitCodes::USAGE_ERROR
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
# Handler for the `pvectl create container` command.
|
|
6
|
+
#
|
|
7
|
+
# Includes CreateResourceCommand for shared workflow and overrides
|
|
8
|
+
# template methods with container-specific behavior.
|
|
9
|
+
#
|
|
10
|
+
# @example Flag-based creation
|
|
11
|
+
# pvectl create container --hostname web-ct --ostemplate local:vztmpl/debian-12.tar.zst \
|
|
12
|
+
# --rootfs storage=local-lvm,size=8G --cores 2 --memory 2048
|
|
13
|
+
#
|
|
14
|
+
class CreateContainer
|
|
15
|
+
include CreateResourceCommand
|
|
16
|
+
include SharedConfigParsers
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
# @return [String] human label for container resources
|
|
21
|
+
def resource_label
|
|
22
|
+
"container"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# @return [String] human label for container IDs
|
|
26
|
+
def resource_id_label
|
|
27
|
+
"CTID"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# @return [Boolean] true if --hostname is missing
|
|
31
|
+
def required_params_missing?
|
|
32
|
+
!@options[:hostname]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# @return [Object] container creation wizard
|
|
36
|
+
def build_wizard
|
|
37
|
+
Pvectl::Wizards::CreateContainer.new(@options, @global_options)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# @param connection [Connection] API connection
|
|
41
|
+
# @param task_repo [Repositories::Task] task repository
|
|
42
|
+
# @return [Services::CreateContainer] container creation service
|
|
43
|
+
def build_create_service(connection, task_repo)
|
|
44
|
+
ct_repo = Pvectl::Repositories::Container.new(connection)
|
|
45
|
+
Pvectl::Services::CreateContainer.new(
|
|
46
|
+
container_repository: ct_repo,
|
|
47
|
+
task_repository: task_repo,
|
|
48
|
+
options: service_options
|
|
49
|
+
)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# @param result [Models::ContainerOperationResult] operation result
|
|
53
|
+
# @return [void]
|
|
54
|
+
def output_result(result)
|
|
55
|
+
presenter = Pvectl::Presenters::ContainerOperationResult.new
|
|
56
|
+
format = @global_options[:output] || "table"
|
|
57
|
+
color_flag = @global_options[:color]
|
|
58
|
+
|
|
59
|
+
formatter = Pvectl::Formatters::Registry.for(format)
|
|
60
|
+
output = formatter.format([result], presenter, color: color_flag)
|
|
61
|
+
puts output
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Validates flags and performs flag-based creation.
|
|
65
|
+
#
|
|
66
|
+
# @return [Integer] exit code
|
|
67
|
+
def perform_create
|
|
68
|
+
return usage_error("--hostname is required") unless @options[:hostname]
|
|
69
|
+
return usage_error("--ostemplate is required") unless @options[:ostemplate]
|
|
70
|
+
return usage_error("--rootfs is required") unless @options[:rootfs]
|
|
71
|
+
|
|
72
|
+
super
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Extracts CLI options into a service params hash.
|
|
76
|
+
#
|
|
77
|
+
# Delegates container config parsing to SharedConfigParsers#build_ct_config_params,
|
|
78
|
+
# then adds create-specific parameters.
|
|
79
|
+
#
|
|
80
|
+
# @return [Hash] service-compatible parameters
|
|
81
|
+
# @raise [ArgumentError] if parser validation fails
|
|
82
|
+
def build_params_from_flags
|
|
83
|
+
params = build_ct_config_params
|
|
84
|
+
params[:hostname] = @options[:hostname]
|
|
85
|
+
params[:node] = @options[:node] || resolve_default_node
|
|
86
|
+
params[:ostemplate] = @options[:ostemplate]
|
|
87
|
+
params[:description] = @options[:description]
|
|
88
|
+
params[:pool] = @options[:pool]
|
|
89
|
+
|
|
90
|
+
ctid = @args.first
|
|
91
|
+
params[:ctid] = ctid.to_i if ctid
|
|
92
|
+
|
|
93
|
+
params.compact
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# @param params [Hash] container creation parameters
|
|
97
|
+
# @return [void]
|
|
98
|
+
def display_resource_summary(params)
|
|
99
|
+
$stdout.puts " Hostname: #{params[:hostname]}"
|
|
100
|
+
$stdout.puts " Node: #{params[:node] || '(from context)'}"
|
|
101
|
+
$stdout.puts " Template: #{truncate_template(params[:ostemplate])}"
|
|
102
|
+
$stdout.puts " CPU: #{params[:cores] || 1} cores" if params[:cores]
|
|
103
|
+
$stdout.puts " Memory: #{params[:memory] || 512} MB"
|
|
104
|
+
$stdout.puts " Swap: #{params[:swap] || 512} MB"
|
|
105
|
+
|
|
106
|
+
if params[:rootfs]
|
|
107
|
+
$stdout.puts " Root FS: #{params[:rootfs][:storage]}, #{params[:rootfs][:size]}"
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
if params[:mountpoints]
|
|
111
|
+
params[:mountpoints].each_with_index do |mp, i|
|
|
112
|
+
$stdout.puts " Mount#{i}: #{mp[:storage]}, #{mp[:size]} -> #{mp[:mp]}"
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
if params[:nets]
|
|
117
|
+
params[:nets].each_with_index do |net, i|
|
|
118
|
+
ip_info = net[:ip] ? ", #{net[:ip]}" : ""
|
|
119
|
+
$stdout.puts " Net#{i}: #{net[:bridge]}, #{net[:name] || 'eth0'}#{ip_info}"
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
$stdout.puts " Unpriv: #{params[:privileged] ? 'No' : 'Yes'}"
|
|
124
|
+
$stdout.puts " Features: #{params[:features]}" if params[:features]
|
|
125
|
+
$stdout.puts " Tags: #{params[:tags]}" if params[:tags]
|
|
126
|
+
$stdout.puts " Pool: #{params[:pool]}" if params[:pool]
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Truncates long template paths for display.
|
|
130
|
+
#
|
|
131
|
+
# @param template [String] full template path
|
|
132
|
+
# @return [String] truncated template name
|
|
133
|
+
def truncate_template(template)
|
|
134
|
+
return template unless template
|
|
135
|
+
|
|
136
|
+
parts = template.split("/")
|
|
137
|
+
parts.last || template
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
# Shared functionality for resource creation commands.
|
|
6
|
+
#
|
|
7
|
+
# Template method pattern: provides common create workflow
|
|
8
|
+
# (interactive detection, confirmation, dry-run, config loading)
|
|
9
|
+
# while specialization classes define resource-specific hooks.
|
|
10
|
+
#
|
|
11
|
+
# @abstract Include this module and implement template methods.
|
|
12
|
+
#
|
|
13
|
+
# @example Specialization
|
|
14
|
+
# class CreateVm
|
|
15
|
+
# include CreateResourceCommand
|
|
16
|
+
# private
|
|
17
|
+
# def resource_label = "VM"
|
|
18
|
+
# def resource_id_label = "VMID"
|
|
19
|
+
# # ...
|
|
20
|
+
# end
|
|
21
|
+
#
|
|
22
|
+
module CreateResourceCommand
|
|
23
|
+
# Class methods added when the module is included.
|
|
24
|
+
module ClassMethods
|
|
25
|
+
# Executes the create 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 create 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 create command.
|
|
55
|
+
#
|
|
56
|
+
# @return [Integer] exit code
|
|
57
|
+
def execute
|
|
58
|
+
if interactive_mode?
|
|
59
|
+
perform_interactive
|
|
60
|
+
else
|
|
61
|
+
perform_create
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
private
|
|
66
|
+
|
|
67
|
+
# --- Template methods (override in specialization) ---
|
|
68
|
+
|
|
69
|
+
# @return [String] human label for resource ("VM" or "container")
|
|
70
|
+
def resource_label
|
|
71
|
+
raise NotImplementedError, "#{self.class} must implement #resource_label"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# @return [String] human label for resource ID ("VMID" or "CTID")
|
|
75
|
+
def resource_id_label
|
|
76
|
+
raise NotImplementedError, "#{self.class} must implement #resource_id_label"
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# @return [Boolean] true if required params for non-interactive mode are missing
|
|
80
|
+
def required_params_missing?
|
|
81
|
+
raise NotImplementedError, "#{self.class} must implement #required_params_missing?"
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# @return [Hash] parameters built from CLI flags
|
|
85
|
+
def build_params_from_flags
|
|
86
|
+
raise NotImplementedError, "#{self.class} must implement #build_params_from_flags"
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# @return [Object] wizard instance for interactive mode
|
|
90
|
+
def build_wizard
|
|
91
|
+
raise NotImplementedError, "#{self.class} must implement #build_wizard"
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# @param connection [Connection] API connection
|
|
95
|
+
# @param task_repo [Repositories::Task] task repository
|
|
96
|
+
# @return [Object] create service instance
|
|
97
|
+
def build_create_service(connection, task_repo)
|
|
98
|
+
raise NotImplementedError, "#{self.class} must implement #build_create_service"
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# @param result [Models::OperationResult] operation result
|
|
102
|
+
# @return [void]
|
|
103
|
+
def output_result(result)
|
|
104
|
+
raise NotImplementedError, "#{self.class} must implement #output_result"
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# @param params [Hash] creation parameters
|
|
108
|
+
# @return [void]
|
|
109
|
+
def display_resource_summary(params)
|
|
110
|
+
raise NotImplementedError, "#{self.class} must implement #display_resource_summary"
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# --- Shared implementation ---
|
|
114
|
+
|
|
115
|
+
# Determines whether to use interactive mode.
|
|
116
|
+
#
|
|
117
|
+
# @return [Boolean] true if interactive mode should be used
|
|
118
|
+
def interactive_mode?
|
|
119
|
+
return true if @options[:interactive]
|
|
120
|
+
return false if @options[:"no-interactive"]
|
|
121
|
+
|
|
122
|
+
$stdin.tty? && required_params_missing?
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Runs the interactive wizard flow.
|
|
126
|
+
#
|
|
127
|
+
# @return [Integer] exit code
|
|
128
|
+
def perform_interactive
|
|
129
|
+
wizard = build_wizard
|
|
130
|
+
wizard_params = wizard.run
|
|
131
|
+
return ExitCodes::SUCCESS unless wizard_params
|
|
132
|
+
|
|
133
|
+
@options[:start] = wizard_params.delete(:start) if wizard_params.key?(:start)
|
|
134
|
+
perform_create_with_params(wizard_params)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# Validates flags and performs flag-based creation.
|
|
138
|
+
#
|
|
139
|
+
# @return [Integer] exit code
|
|
140
|
+
def perform_create
|
|
141
|
+
params = build_params_from_flags
|
|
142
|
+
perform_create_with_params(params)
|
|
143
|
+
rescue ArgumentError => e
|
|
144
|
+
usage_error(e.message)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Creates a resource with the given parameters.
|
|
148
|
+
#
|
|
149
|
+
# @param params [Hash] creation parameters
|
|
150
|
+
# @return [Integer] exit code
|
|
151
|
+
def perform_create_with_params(params)
|
|
152
|
+
return ExitCodes::SUCCESS if display_summary_and_confirm(params) == :cancelled
|
|
153
|
+
return ExitCodes::SUCCESS if @options[:"dry-run"]
|
|
154
|
+
|
|
155
|
+
load_config
|
|
156
|
+
connection = Pvectl::Connection.new(@config)
|
|
157
|
+
task_repo = Pvectl::Repositories::Task.new(connection)
|
|
158
|
+
|
|
159
|
+
service = build_create_service(connection, task_repo)
|
|
160
|
+
result = service.execute(**params)
|
|
161
|
+
output_result(result)
|
|
162
|
+
result.failed? ? ExitCodes::GENERAL_ERROR : ExitCodes::SUCCESS
|
|
163
|
+
rescue Pvectl::Config::ConfigNotFoundError,
|
|
164
|
+
Pvectl::Config::InvalidConfigError,
|
|
165
|
+
Pvectl::Config::ContextNotFoundError,
|
|
166
|
+
Pvectl::Config::ClusterNotFoundError,
|
|
167
|
+
Pvectl::Config::UserNotFoundError
|
|
168
|
+
raise
|
|
169
|
+
rescue StandardError => e
|
|
170
|
+
$stderr.puts "Error: #{e.message}"
|
|
171
|
+
ExitCodes::GENERAL_ERROR
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# Displays a creation summary and prompts for confirmation.
|
|
175
|
+
#
|
|
176
|
+
# @param params [Hash] creation parameters
|
|
177
|
+
# @return [Symbol, nil] +:cancelled+ if user declines, +nil+ otherwise
|
|
178
|
+
def display_summary_and_confirm(params)
|
|
179
|
+
display_summary(params)
|
|
180
|
+
|
|
181
|
+
return nil if @options[:yes]
|
|
182
|
+
|
|
183
|
+
$stdout.print "Create this #{resource_label}? [y/N] "
|
|
184
|
+
$stdout.flush
|
|
185
|
+
answer = $stdin.gets&.strip&.downcase
|
|
186
|
+
answer == "y" ? nil : :cancelled
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# Displays the creation summary.
|
|
190
|
+
#
|
|
191
|
+
# @param params [Hash] creation parameters
|
|
192
|
+
# @return [void]
|
|
193
|
+
def display_summary(params)
|
|
194
|
+
$stdout.puts ""
|
|
195
|
+
$stdout.puts " Create #{resource_label} - Summary"
|
|
196
|
+
$stdout.puts " #{'─' * 40}"
|
|
197
|
+
$stdout.puts " #{resource_id_label}:#{' ' * (10 - resource_id_label.length)}#{params[:vmid] || params[:ctid] || '(auto)'}"
|
|
198
|
+
display_resource_summary(params)
|
|
199
|
+
$stdout.puts " #{'─' * 40}"
|
|
200
|
+
$stdout.puts " (dry-run mode -- no #{resource_label} will be created)" if @options[:"dry-run"]
|
|
201
|
+
$stdout.puts ""
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# Resolves the default node from configuration.
|
|
205
|
+
#
|
|
206
|
+
# @return [String, nil] default node name or nil
|
|
207
|
+
def resolve_default_node
|
|
208
|
+
load_config unless @config
|
|
209
|
+
@config&.default_node
|
|
210
|
+
rescue StandardError
|
|
211
|
+
nil
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
# Loads configuration from file or environment.
|
|
215
|
+
#
|
|
216
|
+
# @return [void]
|
|
217
|
+
def load_config
|
|
218
|
+
service = Pvectl::Config::Service.new
|
|
219
|
+
service.load(config: @global_options[:config])
|
|
220
|
+
@config = service.current_config
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
# Builds service options from command options.
|
|
224
|
+
#
|
|
225
|
+
# @return [Hash] service options
|
|
226
|
+
def service_options
|
|
227
|
+
opts = {}
|
|
228
|
+
opts[:timeout] = @options[:timeout] if @options[:timeout]
|
|
229
|
+
opts[:async] = true if @options[:async]
|
|
230
|
+
opts[:start] = true if @options[:start]
|
|
231
|
+
opts
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
# Outputs usage error and returns exit code.
|
|
235
|
+
#
|
|
236
|
+
# @param message [String] error message
|
|
237
|
+
# @return [Integer] exit code
|
|
238
|
+
def usage_error(message)
|
|
239
|
+
$stderr.puts "Error: #{message}"
|
|
240
|
+
ExitCodes::USAGE_ERROR
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
end
|