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,79 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
module Cloudinit
|
|
6
|
+
# Handler for the `pvectl cloudinit regenerate vm <id>` subcommand.
|
|
7
|
+
#
|
|
8
|
+
# Triggers Proxmox to rebuild the cloud-init ISO from the current
|
|
9
|
+
# VM configuration. The operation is synchronous on the Proxmox side
|
|
10
|
+
# and returns null on success.
|
|
11
|
+
#
|
|
12
|
+
# @example Usage
|
|
13
|
+
# pvectl cloudinit regenerate vm 100
|
|
14
|
+
# pvectl cloudinit regenerate vm 100 --node pve2
|
|
15
|
+
#
|
|
16
|
+
class Regenerate
|
|
17
|
+
# Registers the regenerate subcommand under the cloudinit parent.
|
|
18
|
+
#
|
|
19
|
+
# @param parent [GLI::Command] parent cloudinit command
|
|
20
|
+
# @return [void]
|
|
21
|
+
def self.register_subcommand(parent)
|
|
22
|
+
parent.desc "Regenerate the cloud-init ISO for a VM"
|
|
23
|
+
parent.long_desc <<~HELP
|
|
24
|
+
DESCRIPTION
|
|
25
|
+
Rebuild the cloud-init configuration drive (ISO) for a VM from
|
|
26
|
+
the current Proxmox configuration. This is required after
|
|
27
|
+
editing cloud-init-related options (user, ipconfig, sshkeys, etc.)
|
|
28
|
+
for the changes to take effect inside the guest on next boot.
|
|
29
|
+
|
|
30
|
+
EXAMPLES
|
|
31
|
+
Regenerate cloud-init for VM 100:
|
|
32
|
+
$ pvectl cloudinit regenerate vm 100
|
|
33
|
+
|
|
34
|
+
Skip VMID lookup by passing the node explicitly:
|
|
35
|
+
$ pvectl cloudinit regenerate vm 100 --node pve2
|
|
36
|
+
|
|
37
|
+
NOTES
|
|
38
|
+
Cloud-init is a VM-only feature — LXC containers do not expose
|
|
39
|
+
cloud-init endpoints.
|
|
40
|
+
|
|
41
|
+
The VM does NOT need to be running. The regenerated ISO will
|
|
42
|
+
be picked up at the next guest reboot.
|
|
43
|
+
|
|
44
|
+
SEE ALSO
|
|
45
|
+
pvectl help cloudinit pending Show pending cloud-init changes
|
|
46
|
+
pvectl help cloudinit dump Inspect generated cloud-init YAML
|
|
47
|
+
HELP
|
|
48
|
+
parent.arg_name "RESOURCE_TYPE ID"
|
|
49
|
+
parent.command :regenerate do |c|
|
|
50
|
+
c.action do |global_options, options, args|
|
|
51
|
+
exit_code = execute(args, options, global_options)
|
|
52
|
+
exit exit_code if exit_code != 0
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Executes the regenerate subcommand.
|
|
58
|
+
#
|
|
59
|
+
# @param args [Array<String>] command arguments (RESOURCE_TYPE, ID)
|
|
60
|
+
# @param options [Hash] command-local options (:node)
|
|
61
|
+
# @param global_options [Hash] global CLI options
|
|
62
|
+
# @return [Integer] exit code
|
|
63
|
+
def self.execute(args, options, global_options)
|
|
64
|
+
resource_type = args[0]
|
|
65
|
+
vmid_arg = args[1]
|
|
66
|
+
|
|
67
|
+
return Cloudinit.usage_error("Resource type required (vm)") unless resource_type
|
|
68
|
+
return Cloudinit.usage_error("VMID is required") unless vmid_arg
|
|
69
|
+
return Cloudinit.unknown_resource_type(resource_type) unless resource_type == "vm"
|
|
70
|
+
|
|
71
|
+
Cloudinit.with_service(global_options) do |service|
|
|
72
|
+
result = service.regenerate(vmid_arg.to_i, node: options[:node])
|
|
73
|
+
$stdout.puts "Cloud-init ISO regenerated for VM #{result[:vmid]} on #{result[:node]}."
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
module Config
|
|
6
|
+
# Registers the `pvectl config` command group with all subcommands.
|
|
7
|
+
#
|
|
8
|
+
# @example
|
|
9
|
+
# Commands::Config::Command.register(cli)
|
|
10
|
+
#
|
|
11
|
+
class Command
|
|
12
|
+
# Registers the config command and all subcommands with the CLI.
|
|
13
|
+
#
|
|
14
|
+
# @param cli [GLI::App] the CLI application object
|
|
15
|
+
# @return [void]
|
|
16
|
+
def self.register(cli)
|
|
17
|
+
cli.desc "Manage pvectl configuration"
|
|
18
|
+
cli.long_desc <<~HELP
|
|
19
|
+
Manage pvectl configuration. Configuration uses kubeconfig-style
|
|
20
|
+
contexts to support multiple Proxmox clusters.
|
|
21
|
+
|
|
22
|
+
Configuration file location: ~/.pvectl/config
|
|
23
|
+
|
|
24
|
+
SUBCOMMANDS
|
|
25
|
+
config get-contexts List all available contexts
|
|
26
|
+
config use-context NAME Switch to a different context
|
|
27
|
+
config set-context NAME Create or modify a context
|
|
28
|
+
config set-cluster NAME Create or modify a cluster definition
|
|
29
|
+
config set-credentials NAME Create or modify user credentials
|
|
30
|
+
config view Display current configuration (secrets masked)
|
|
31
|
+
|
|
32
|
+
EXAMPLES
|
|
33
|
+
View current configuration:
|
|
34
|
+
$ pvectl config view
|
|
35
|
+
|
|
36
|
+
Switch to a different context:
|
|
37
|
+
$ pvectl config use-context production
|
|
38
|
+
|
|
39
|
+
Set up a new cluster:
|
|
40
|
+
$ pvectl config set-cluster prod --server=https://pve.example.com:8006
|
|
41
|
+
$ pvectl config set-credentials admin --token-id=root@pam!pvectl --token-secret=xxx
|
|
42
|
+
$ pvectl config set-context prod --cluster=prod --user=admin
|
|
43
|
+
|
|
44
|
+
NOTES
|
|
45
|
+
On first run, pvectl launches an interactive wizard if no config exists.
|
|
46
|
+
|
|
47
|
+
Environment variables (PROXMOX_HOST, PROXMOX_TOKEN_ID, etc.) override
|
|
48
|
+
config file values. Use PVECTL_CONTEXT to override the active context.
|
|
49
|
+
|
|
50
|
+
SEE ALSO
|
|
51
|
+
pvectl help ping Test connectivity after configuration
|
|
52
|
+
HELP
|
|
53
|
+
cli.command :config do |c|
|
|
54
|
+
UseContext.register_subcommand(c)
|
|
55
|
+
GetContexts.register_subcommand(c)
|
|
56
|
+
SetContext.register_subcommand(c)
|
|
57
|
+
SetCluster.register_subcommand(c)
|
|
58
|
+
SetCredentials.register_subcommand(c)
|
|
59
|
+
View.register_subcommand(c)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
module Config
|
|
6
|
+
# Handler for the `pvectl config get-contexts` command.
|
|
7
|
+
#
|
|
8
|
+
# Lists all contexts defined in the configuration file with
|
|
9
|
+
# an indicator showing which context is currently active.
|
|
10
|
+
# Uses the unified OutputHelper for formatting output.
|
|
11
|
+
#
|
|
12
|
+
# @example Usage
|
|
13
|
+
# pvectl config get-contexts
|
|
14
|
+
# pvectl config get-contexts -o json
|
|
15
|
+
# pvectl config get-contexts -o yaml
|
|
16
|
+
# pvectl config get-contexts -o wide
|
|
17
|
+
# pvectl config get-contexts --no-color
|
|
18
|
+
#
|
|
19
|
+
class GetContexts
|
|
20
|
+
# Registers the get-contexts subcommand.
|
|
21
|
+
#
|
|
22
|
+
# @param parent [GLI::Command] parent config command
|
|
23
|
+
# @return [void]
|
|
24
|
+
def self.register_subcommand(parent)
|
|
25
|
+
parent.desc "List all available contexts"
|
|
26
|
+
parent.long_desc <<~HELP
|
|
27
|
+
List all contexts defined in the configuration file. The currently
|
|
28
|
+
active context is marked with an asterisk (*).
|
|
29
|
+
|
|
30
|
+
EXAMPLES
|
|
31
|
+
$ pvectl config get-contexts
|
|
32
|
+
HELP
|
|
33
|
+
parent.command :"get-contexts" do |get_ctx|
|
|
34
|
+
get_ctx.action do |global_options, _options, _args|
|
|
35
|
+
exit_code = execute(global_options)
|
|
36
|
+
exit exit_code if exit_code != 0
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Executes the get-contexts command.
|
|
42
|
+
#
|
|
43
|
+
# @param global_options [Hash] global CLI options (includes :config, :output, :color)
|
|
44
|
+
# @return [Integer] exit code (0 for success)
|
|
45
|
+
def self.execute(global_options)
|
|
46
|
+
config_path = global_options[:config]
|
|
47
|
+
|
|
48
|
+
service = Pvectl::Config::Service.new
|
|
49
|
+
service.load(config: config_path)
|
|
50
|
+
|
|
51
|
+
contexts = service.contexts
|
|
52
|
+
current_context_name = service.current_context_name
|
|
53
|
+
presenter = Pvectl::Presenters::Config::Context.new
|
|
54
|
+
|
|
55
|
+
Pvectl::Formatters::OutputHelper.print(
|
|
56
|
+
data: contexts,
|
|
57
|
+
presenter: presenter,
|
|
58
|
+
format: global_options[:output] || "table",
|
|
59
|
+
color_flag: global_options[:color],
|
|
60
|
+
current_context: current_context_name
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
0
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
module Config
|
|
6
|
+
# Handler for the `pvectl config set-cluster` command.
|
|
7
|
+
#
|
|
8
|
+
# Creates a new cluster or modifies an existing one in the configuration.
|
|
9
|
+
# Requires --server flag for new clusters.
|
|
10
|
+
#
|
|
11
|
+
# @example Usage
|
|
12
|
+
# pvectl config set-cluster staging --server=https://pve-staging.example.com:8006
|
|
13
|
+
# pvectl config set-cluster prod --server=https://pve.example.com:8006 --certificate-authority=/path/to/ca.crt
|
|
14
|
+
# pvectl config set-cluster dev --server=https://pve-dev.local:8006 --insecure-skip-tls-verify
|
|
15
|
+
#
|
|
16
|
+
class SetCluster
|
|
17
|
+
# Registers the set-cluster subcommand.
|
|
18
|
+
#
|
|
19
|
+
# @param parent [GLI::Command] parent config command
|
|
20
|
+
# @return [void]
|
|
21
|
+
def self.register_subcommand(parent)
|
|
22
|
+
parent.desc "Create or modify a cluster"
|
|
23
|
+
parent.long_desc <<~HELP
|
|
24
|
+
Create a new cluster definition or modify an existing one.
|
|
25
|
+
|
|
26
|
+
EXAMPLES
|
|
27
|
+
Add a cluster:
|
|
28
|
+
$ pvectl config set-cluster production --server=https://pve.example.com:8006
|
|
29
|
+
|
|
30
|
+
Skip TLS verification (testing only):
|
|
31
|
+
$ pvectl config set-cluster lab --server=https://pve-lab:8006 --insecure-skip-tls-verify
|
|
32
|
+
HELP
|
|
33
|
+
parent.command :"set-cluster" do |set_cluster|
|
|
34
|
+
set_cluster.arg_name "CLUSTER_NAME"
|
|
35
|
+
|
|
36
|
+
set_cluster.desc "Proxmox server URL (e.g., https://pve.example.com:8006)"
|
|
37
|
+
set_cluster.flag [:server]
|
|
38
|
+
|
|
39
|
+
set_cluster.desc "Path to CA certificate file"
|
|
40
|
+
set_cluster.flag [:"certificate-authority"]
|
|
41
|
+
|
|
42
|
+
set_cluster.desc "Skip TLS certificate verification"
|
|
43
|
+
set_cluster.switch [:"insecure-skip-tls-verify"], negatable: false
|
|
44
|
+
|
|
45
|
+
set_cluster.action do |global_options, options, args|
|
|
46
|
+
if args.empty?
|
|
47
|
+
$stderr.puts "Error: cluster name is required"
|
|
48
|
+
exit ExitCodes::USAGE_ERROR
|
|
49
|
+
end
|
|
50
|
+
exit_code = execute(args[0], options, global_options)
|
|
51
|
+
exit exit_code if exit_code != 0
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Executes the set-cluster command.
|
|
57
|
+
#
|
|
58
|
+
# @param cluster_name [String] name of the cluster to create or modify
|
|
59
|
+
# @param options [Hash] command options (:server, :certificate_authority, :insecure_skip_tls_verify)
|
|
60
|
+
# @param global_options [Hash] global CLI options (includes :config)
|
|
61
|
+
# @return [Integer] exit code (0 for success)
|
|
62
|
+
def self.execute(cluster_name, options, global_options)
|
|
63
|
+
config_path = global_options[:config]
|
|
64
|
+
service = Pvectl::Config::Service.new
|
|
65
|
+
service.load(config: config_path)
|
|
66
|
+
|
|
67
|
+
existing_cluster = service.cluster(cluster_name)
|
|
68
|
+
action = existing_cluster ? "modified" : "created"
|
|
69
|
+
|
|
70
|
+
# Use existing values if not provided
|
|
71
|
+
server = options[:server] || existing_cluster&.server
|
|
72
|
+
certificate_authority = options[:"certificate-authority"] ||
|
|
73
|
+
options[:certificate_authority] ||
|
|
74
|
+
existing_cluster&.certificate_authority
|
|
75
|
+
|
|
76
|
+
# Handle insecure-skip-tls-verify flag
|
|
77
|
+
insecure_skip = options[:"insecure-skip-tls-verify"]
|
|
78
|
+
verify_ssl = if insecure_skip.nil?
|
|
79
|
+
existing_cluster ? existing_cluster.verify_ssl : true
|
|
80
|
+
else
|
|
81
|
+
!insecure_skip
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Validate required fields for new clusters
|
|
85
|
+
if server.nil?
|
|
86
|
+
$stderr.puts "Error: --server is required for new clusters"
|
|
87
|
+
return ExitCodes::USAGE_ERROR
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
service.set_cluster(
|
|
91
|
+
name: cluster_name,
|
|
92
|
+
server: server,
|
|
93
|
+
verify_ssl: verify_ssl,
|
|
94
|
+
certificate_authority: certificate_authority
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
puts "Cluster \"#{cluster_name}\" #{action}."
|
|
98
|
+
0
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
module Config
|
|
6
|
+
# Handler for the `pvectl config set-context` command.
|
|
7
|
+
#
|
|
8
|
+
# Creates a new context or modifies an existing one in the configuration.
|
|
9
|
+
# Requires --cluster and --user flags for new contexts.
|
|
10
|
+
#
|
|
11
|
+
# @example Usage
|
|
12
|
+
# pvectl config set-context production --cluster=pve-prod --user=admin
|
|
13
|
+
# pvectl config set-context dev --cluster=pve-dev --user=admin --default-node=pve1
|
|
14
|
+
#
|
|
15
|
+
class SetContext
|
|
16
|
+
# Registers the set-context subcommand.
|
|
17
|
+
#
|
|
18
|
+
# @param parent [GLI::Command] parent config command
|
|
19
|
+
# @return [void]
|
|
20
|
+
def self.register_subcommand(parent)
|
|
21
|
+
parent.desc "Create or modify a context"
|
|
22
|
+
parent.long_desc <<~HELP
|
|
23
|
+
Create a new context or modify an existing one. A context links
|
|
24
|
+
a cluster definition with user credentials.
|
|
25
|
+
|
|
26
|
+
EXAMPLES
|
|
27
|
+
Create a new context:
|
|
28
|
+
$ pvectl config set-context prod --cluster=production --user=admin-prod
|
|
29
|
+
|
|
30
|
+
Set a default node:
|
|
31
|
+
$ pvectl config set-context prod --default-node=pve1
|
|
32
|
+
HELP
|
|
33
|
+
parent.command :"set-context" do |set_ctx|
|
|
34
|
+
set_ctx.arg_name "CONTEXT_NAME"
|
|
35
|
+
|
|
36
|
+
set_ctx.desc "Cluster name"
|
|
37
|
+
set_ctx.flag [:cluster]
|
|
38
|
+
|
|
39
|
+
set_ctx.desc "User name"
|
|
40
|
+
set_ctx.flag [:user]
|
|
41
|
+
|
|
42
|
+
set_ctx.desc "Default node"
|
|
43
|
+
set_ctx.flag [:"default-node"]
|
|
44
|
+
|
|
45
|
+
set_ctx.action do |global_options, options, args|
|
|
46
|
+
if args.empty?
|
|
47
|
+
$stderr.puts "Error: context name is required"
|
|
48
|
+
exit ExitCodes::USAGE_ERROR
|
|
49
|
+
end
|
|
50
|
+
exit_code = execute(args[0], options, global_options)
|
|
51
|
+
exit exit_code if exit_code != 0
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Executes the set-context command.
|
|
57
|
+
#
|
|
58
|
+
# @param context_name [String] name of the context to create or modify
|
|
59
|
+
# @param options [Hash] command options (:cluster, :user, :default_node)
|
|
60
|
+
# @param global_options [Hash] global CLI options (includes :config)
|
|
61
|
+
# @return [Integer] exit code (0 for success)
|
|
62
|
+
# @raise [Config::ClusterNotFoundError] if cluster doesn't exist
|
|
63
|
+
# @raise [Config::UserNotFoundError] if user doesn't exist
|
|
64
|
+
def self.execute(context_name, options, global_options)
|
|
65
|
+
config_path = global_options[:config]
|
|
66
|
+
service = Pvectl::Config::Service.new
|
|
67
|
+
service.load(config: config_path)
|
|
68
|
+
|
|
69
|
+
existing_context = service.context(context_name)
|
|
70
|
+
action = existing_context ? "modified" : "created"
|
|
71
|
+
|
|
72
|
+
# Use existing values if not provided
|
|
73
|
+
cluster = options[:cluster] || existing_context&.cluster_ref
|
|
74
|
+
user = options[:user] || existing_context&.user_ref
|
|
75
|
+
default_node = options[:"default-node"] || options[:default_node] || existing_context&.default_node
|
|
76
|
+
|
|
77
|
+
# Validate required fields for new contexts
|
|
78
|
+
if cluster.nil? || user.nil?
|
|
79
|
+
$stderr.puts "Error: --cluster and --user are required for new contexts"
|
|
80
|
+
return ExitCodes::USAGE_ERROR
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Validate cluster and user exist
|
|
84
|
+
validate_cluster_exists!(service, cluster)
|
|
85
|
+
validate_user_exists!(service, user)
|
|
86
|
+
|
|
87
|
+
service.set_context(
|
|
88
|
+
name: context_name,
|
|
89
|
+
cluster: cluster,
|
|
90
|
+
user: user,
|
|
91
|
+
default_node: default_node
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
puts "Context \"#{context_name}\" #{action}."
|
|
95
|
+
0
|
|
96
|
+
rescue Pvectl::Config::ClusterNotFoundError => e
|
|
97
|
+
$stderr.puts "Error: #{e.message}"
|
|
98
|
+
ExitCodes::CONFIG_ERROR
|
|
99
|
+
rescue Pvectl::Config::UserNotFoundError => e
|
|
100
|
+
$stderr.puts "Error: #{e.message}"
|
|
101
|
+
ExitCodes::CONFIG_ERROR
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Validates that the cluster exists in the configuration.
|
|
105
|
+
#
|
|
106
|
+
# @param service [Config::Service] configuration service
|
|
107
|
+
# @param cluster_name [String] cluster name to validate
|
|
108
|
+
# @raise [Config::ClusterNotFoundError] if cluster doesn't exist
|
|
109
|
+
def self.validate_cluster_exists!(service, cluster_name)
|
|
110
|
+
clusters = service.raw_config["clusters"] || []
|
|
111
|
+
found = clusters.any? { |c| c["name"] == cluster_name }
|
|
112
|
+
unless found
|
|
113
|
+
available = clusters.map { |c| c["name"] }.join(", ")
|
|
114
|
+
raise Pvectl::Config::ClusterNotFoundError,
|
|
115
|
+
"Cluster '#{cluster_name}' not found in configuration. Available: #{available}"
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Validates that the user exists in the configuration.
|
|
120
|
+
#
|
|
121
|
+
# @param service [Config::Service] configuration service
|
|
122
|
+
# @param user_name [String] user name to validate
|
|
123
|
+
# @raise [Config::UserNotFoundError] if user doesn't exist
|
|
124
|
+
def self.validate_user_exists!(service, user_name)
|
|
125
|
+
users = service.raw_config["users"] || []
|
|
126
|
+
found = users.any? { |u| u["name"] == user_name }
|
|
127
|
+
unless found
|
|
128
|
+
available = users.map { |u| u["name"] }.join(", ")
|
|
129
|
+
raise Pvectl::Config::UserNotFoundError,
|
|
130
|
+
"User '#{user_name}' not found in configuration. Available: #{available}"
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Commands
|
|
5
|
+
module Config
|
|
6
|
+
# Handler for the `pvectl config set-credentials` command.
|
|
7
|
+
#
|
|
8
|
+
# Creates a new user or modifies existing credentials in the configuration.
|
|
9
|
+
# Supports two authentication methods:
|
|
10
|
+
# - API Token: --token-id and --token-secret
|
|
11
|
+
# - Password: --username and --password
|
|
12
|
+
#
|
|
13
|
+
# @example Usage with token authentication
|
|
14
|
+
# pvectl config set-credentials admin --token-id=root@pam!automation --token-secret=xxx-xxx
|
|
15
|
+
#
|
|
16
|
+
# @example Usage with password authentication
|
|
17
|
+
# pvectl config set-credentials dev-user --username=root@pam --password=secret
|
|
18
|
+
#
|
|
19
|
+
class SetCredentials
|
|
20
|
+
# Registers the set-credentials subcommand.
|
|
21
|
+
#
|
|
22
|
+
# @param parent [GLI::Command] parent config command
|
|
23
|
+
# @return [void]
|
|
24
|
+
def self.register_subcommand(parent)
|
|
25
|
+
parent.desc "Create or modify user credentials"
|
|
26
|
+
parent.long_desc <<~HELP
|
|
27
|
+
Create or modify user credentials. Supports API token (recommended)
|
|
28
|
+
and username/password authentication.
|
|
29
|
+
|
|
30
|
+
EXAMPLES
|
|
31
|
+
Set API token credentials:
|
|
32
|
+
$ pvectl config set-credentials admin --token-id=root@pam!pvectl --token-secret=xxx
|
|
33
|
+
|
|
34
|
+
Set username/password credentials:
|
|
35
|
+
$ pvectl config set-credentials admin --username=root@pam --password=secret
|
|
36
|
+
|
|
37
|
+
NOTES
|
|
38
|
+
API tokens are recommended over passwords — they are more secure
|
|
39
|
+
and don't expire with password changes.
|
|
40
|
+
HELP
|
|
41
|
+
parent.command :"set-credentials" do |set_creds|
|
|
42
|
+
set_creds.arg_name "USER_NAME"
|
|
43
|
+
|
|
44
|
+
set_creds.desc "API token ID (e.g., root@pam!tokenname)"
|
|
45
|
+
set_creds.flag [:"token-id"]
|
|
46
|
+
|
|
47
|
+
set_creds.desc "API token secret"
|
|
48
|
+
set_creds.flag [:"token-secret"]
|
|
49
|
+
|
|
50
|
+
set_creds.desc "Username for password authentication"
|
|
51
|
+
set_creds.flag [:username]
|
|
52
|
+
|
|
53
|
+
set_creds.desc "Password for password authentication"
|
|
54
|
+
set_creds.flag [:password]
|
|
55
|
+
|
|
56
|
+
set_creds.action do |global_options, options, args|
|
|
57
|
+
if args.empty?
|
|
58
|
+
$stderr.puts "Error: user name is required"
|
|
59
|
+
exit ExitCodes::USAGE_ERROR
|
|
60
|
+
end
|
|
61
|
+
exit_code = execute(args[0], options, global_options)
|
|
62
|
+
exit exit_code if exit_code != 0
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Executes the set-credentials command.
|
|
68
|
+
#
|
|
69
|
+
# @param user_name [String] name of the user to create or modify
|
|
70
|
+
# @param options [Hash] command options (:token_id, :token_secret, :username, :password)
|
|
71
|
+
# @param global_options [Hash] global CLI options (includes :config)
|
|
72
|
+
# @return [Integer] exit code (0 for success)
|
|
73
|
+
def self.execute(user_name, options, global_options)
|
|
74
|
+
config_path = global_options[:config]
|
|
75
|
+
service = Pvectl::Config::Service.new
|
|
76
|
+
service.load(config: config_path)
|
|
77
|
+
|
|
78
|
+
existing_user = service.user(user_name)
|
|
79
|
+
action = existing_user ? "modified" : "created"
|
|
80
|
+
|
|
81
|
+
# Use existing values if not provided
|
|
82
|
+
token_id = options[:"token-id"] || options[:token_id] || existing_user&.token_id
|
|
83
|
+
token_secret = options[:"token-secret"] || options[:token_secret] || existing_user&.token_secret
|
|
84
|
+
username = options[:username] || existing_user&.username
|
|
85
|
+
password = options[:password] || existing_user&.password
|
|
86
|
+
|
|
87
|
+
# Validate credentials for new users
|
|
88
|
+
if existing_user.nil?
|
|
89
|
+
validation_error = validate_new_user_credentials(token_id, token_secret, username, password)
|
|
90
|
+
return validation_error if validation_error
|
|
91
|
+
else
|
|
92
|
+
# For existing users, validate that partial updates are complete
|
|
93
|
+
validation_error = validate_partial_update(options, existing_user)
|
|
94
|
+
return validation_error if validation_error
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
service.set_credentials(
|
|
98
|
+
name: user_name,
|
|
99
|
+
token_id: token_id,
|
|
100
|
+
token_secret: token_secret,
|
|
101
|
+
username: username,
|
|
102
|
+
password: password
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
puts "User \"#{user_name}\" #{action}."
|
|
106
|
+
0
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Validates credentials for a new user.
|
|
110
|
+
#
|
|
111
|
+
# @param token_id [String, nil] API token ID
|
|
112
|
+
# @param token_secret [String, nil] API token secret
|
|
113
|
+
# @param username [String, nil] username
|
|
114
|
+
# @param password [String, nil] password
|
|
115
|
+
# @return [Integer, nil] exit code if validation fails, nil otherwise
|
|
116
|
+
def self.validate_new_user_credentials(token_id, token_secret, username, password)
|
|
117
|
+
has_token_auth = token_id && token_secret
|
|
118
|
+
has_password_auth = username && password
|
|
119
|
+
|
|
120
|
+
if !has_token_auth && !has_password_auth
|
|
121
|
+
if token_id && !token_secret
|
|
122
|
+
$stderr.puts "Error: --token-secret is required when using --token-id"
|
|
123
|
+
return ExitCodes::USAGE_ERROR
|
|
124
|
+
elsif token_secret && !token_id
|
|
125
|
+
$stderr.puts "Error: --token-id is required when using --token-secret"
|
|
126
|
+
return ExitCodes::USAGE_ERROR
|
|
127
|
+
elsif username && !password
|
|
128
|
+
$stderr.puts "Error: --password is required when using --username"
|
|
129
|
+
return ExitCodes::USAGE_ERROR
|
|
130
|
+
elsif password && !username
|
|
131
|
+
$stderr.puts "Error: --username is required when using --password"
|
|
132
|
+
return ExitCodes::USAGE_ERROR
|
|
133
|
+
else
|
|
134
|
+
$stderr.puts "Error: credentials required (--token-id/--token-secret or --username/--password)"
|
|
135
|
+
return ExitCodes::USAGE_ERROR
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
nil
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Validates partial update for existing user.
|
|
143
|
+
#
|
|
144
|
+
# @param options [Hash] command options
|
|
145
|
+
# @param existing_user [Models::User] existing user model
|
|
146
|
+
# @return [Integer, nil] exit code if validation fails, nil otherwise
|
|
147
|
+
def self.validate_partial_update(options, existing_user)
|
|
148
|
+
# Check if user is trying to set incomplete token auth
|
|
149
|
+
token_id_provided = options[:"token-id"] || options[:token_id]
|
|
150
|
+
token_secret_provided = options[:"token-secret"] || options[:token_secret]
|
|
151
|
+
|
|
152
|
+
if token_id_provided && !token_secret_provided && existing_user.token_secret.nil?
|
|
153
|
+
$stderr.puts "Error: --token-secret is required when using --token-id"
|
|
154
|
+
return ExitCodes::USAGE_ERROR
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
if token_secret_provided && !token_id_provided && existing_user.token_id.nil?
|
|
158
|
+
$stderr.puts "Error: --token-id is required when using --token-secret"
|
|
159
|
+
return ExitCodes::USAGE_ERROR
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Check if user is trying to set incomplete password auth
|
|
163
|
+
username_provided = options[:username]
|
|
164
|
+
password_provided = options[:password]
|
|
165
|
+
|
|
166
|
+
if username_provided && !password_provided && existing_user.password.nil?
|
|
167
|
+
$stderr.puts "Error: --password is required when using --username"
|
|
168
|
+
return ExitCodes::USAGE_ERROR
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
if password_provided && !username_provided && existing_user.username.nil?
|
|
172
|
+
$stderr.puts "Error: --username is required when using --password"
|
|
173
|
+
return ExitCodes::USAGE_ERROR
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
nil
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|