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,180 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Config
|
|
5
|
+
module Models
|
|
6
|
+
# Represents a Proxmox cluster server configuration.
|
|
7
|
+
#
|
|
8
|
+
# Cluster is an immutable value object containing connection settings
|
|
9
|
+
# for a single Proxmox server. It stores the server URL, SSL options,
|
|
10
|
+
# and retry/timeout configuration.
|
|
11
|
+
#
|
|
12
|
+
# @example Creating a cluster from constructor
|
|
13
|
+
# cluster = Cluster.new(
|
|
14
|
+
# name: "production",
|
|
15
|
+
# server: "https://pve.example.com:8006",
|
|
16
|
+
# verify_ssl: true,
|
|
17
|
+
# certificate_authority: "/path/to/ca.crt"
|
|
18
|
+
# )
|
|
19
|
+
#
|
|
20
|
+
# @example Creating from YAML config hash
|
|
21
|
+
# hash = {
|
|
22
|
+
# "name" => "production",
|
|
23
|
+
# "cluster" => {
|
|
24
|
+
# "server" => "https://pve.example.com:8006",
|
|
25
|
+
# "insecure-skip-tls-verify" => false
|
|
26
|
+
# }
|
|
27
|
+
# }
|
|
28
|
+
# cluster = Cluster.from_hash(hash)
|
|
29
|
+
#
|
|
30
|
+
class Cluster
|
|
31
|
+
# @return [String] unique name identifying this cluster
|
|
32
|
+
attr_reader :name
|
|
33
|
+
|
|
34
|
+
# @return [String] Proxmox server URL (e.g., "https://pve.example.com:8006")
|
|
35
|
+
attr_reader :server
|
|
36
|
+
|
|
37
|
+
# @return [Boolean] whether to verify SSL certificates
|
|
38
|
+
attr_reader :verify_ssl
|
|
39
|
+
|
|
40
|
+
# @return [String, nil] path to CA certificate file
|
|
41
|
+
attr_reader :certificate_authority
|
|
42
|
+
|
|
43
|
+
# @return [Integer, nil] request timeout in seconds
|
|
44
|
+
attr_reader :timeout
|
|
45
|
+
|
|
46
|
+
# @return [Integer, nil] maximum retry attempts
|
|
47
|
+
attr_reader :retry_count
|
|
48
|
+
|
|
49
|
+
# @return [Integer, nil] base delay between retries in seconds
|
|
50
|
+
attr_reader :retry_delay
|
|
51
|
+
|
|
52
|
+
# @return [Integer, nil] maximum delay cap for exponential backoff
|
|
53
|
+
attr_reader :max_retry_delay
|
|
54
|
+
|
|
55
|
+
# @return [Boolean, nil] whether to retry write operations
|
|
56
|
+
attr_reader :retry_writes
|
|
57
|
+
|
|
58
|
+
# Creates a new Cluster instance.
|
|
59
|
+
#
|
|
60
|
+
# @param name [String] unique name for this cluster
|
|
61
|
+
# @param server [String] Proxmox server URL
|
|
62
|
+
# @param verify_ssl [Boolean] whether to verify SSL (default: true)
|
|
63
|
+
# @param certificate_authority [String, nil] path to CA certificate
|
|
64
|
+
# @param timeout [Integer, nil] request timeout in seconds
|
|
65
|
+
# @param retry_count [Integer, nil] maximum retry attempts
|
|
66
|
+
# @param retry_delay [Integer, nil] base delay between retries
|
|
67
|
+
# @param max_retry_delay [Integer, nil] maximum delay cap
|
|
68
|
+
# @param retry_writes [Boolean, nil] whether to retry write operations
|
|
69
|
+
#
|
|
70
|
+
# @raise [InvalidConfigError] if validation fails
|
|
71
|
+
def initialize(name:, server:, verify_ssl: true, certificate_authority: nil,
|
|
72
|
+
timeout: nil, retry_count: nil, retry_delay: nil,
|
|
73
|
+
max_retry_delay: nil, retry_writes: nil)
|
|
74
|
+
@name = name
|
|
75
|
+
@server = server
|
|
76
|
+
@verify_ssl = verify_ssl
|
|
77
|
+
@certificate_authority = certificate_authority
|
|
78
|
+
@timeout = timeout
|
|
79
|
+
@retry_count = retry_count
|
|
80
|
+
@retry_delay = retry_delay
|
|
81
|
+
@max_retry_delay = max_retry_delay
|
|
82
|
+
@retry_writes = retry_writes
|
|
83
|
+
|
|
84
|
+
validate_retry_settings!
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Creates a Cluster from a kubeconfig-style hash structure.
|
|
88
|
+
#
|
|
89
|
+
# @param hash [Hash] hash with "name" and "cluster" keys
|
|
90
|
+
# @return [Cluster] new cluster instance
|
|
91
|
+
# @raise [InvalidConfigError] if validation fails
|
|
92
|
+
#
|
|
93
|
+
# @example Hash structure
|
|
94
|
+
# {
|
|
95
|
+
# "name" => "production",
|
|
96
|
+
# "cluster" => {
|
|
97
|
+
# "server" => "https://pve.example.com:8006",
|
|
98
|
+
# "insecure-skip-tls-verify" => true,
|
|
99
|
+
# "certificate-authority" => "/path/to/ca.crt"
|
|
100
|
+
# }
|
|
101
|
+
# }
|
|
102
|
+
def self.from_hash(hash)
|
|
103
|
+
cluster_data = hash["cluster"] || {}
|
|
104
|
+
|
|
105
|
+
new(
|
|
106
|
+
name: hash["name"],
|
|
107
|
+
server: cluster_data["server"],
|
|
108
|
+
verify_ssl: !cluster_data["insecure-skip-tls-verify"],
|
|
109
|
+
certificate_authority: cluster_data["certificate-authority"],
|
|
110
|
+
timeout: cluster_data["timeout"],
|
|
111
|
+
retry_count: cluster_data["retry-count"],
|
|
112
|
+
retry_delay: cluster_data["retry-delay"],
|
|
113
|
+
max_retry_delay: cluster_data["max-retry-delay"],
|
|
114
|
+
retry_writes: cluster_data["retry-writes"]
|
|
115
|
+
)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Converts the cluster to a kubeconfig-style hash structure.
|
|
119
|
+
#
|
|
120
|
+
# @return [Hash] hash representation suitable for YAML serialization
|
|
121
|
+
def to_hash
|
|
122
|
+
cluster_data = {
|
|
123
|
+
"server" => server,
|
|
124
|
+
"insecure-skip-tls-verify" => !verify_ssl
|
|
125
|
+
}
|
|
126
|
+
cluster_data["certificate-authority"] = certificate_authority if certificate_authority
|
|
127
|
+
cluster_data["timeout"] = timeout if timeout
|
|
128
|
+
cluster_data["retry-count"] = retry_count if retry_count
|
|
129
|
+
cluster_data["retry-delay"] = retry_delay if retry_delay
|
|
130
|
+
cluster_data["max-retry-delay"] = max_retry_delay if max_retry_delay
|
|
131
|
+
cluster_data["retry-writes"] = retry_writes unless retry_writes.nil?
|
|
132
|
+
|
|
133
|
+
{
|
|
134
|
+
"name" => name,
|
|
135
|
+
"cluster" => cluster_data
|
|
136
|
+
}
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
private
|
|
140
|
+
|
|
141
|
+
# Validates retry/timeout settings.
|
|
142
|
+
#
|
|
143
|
+
# @raise [InvalidConfigError] if values are invalid
|
|
144
|
+
def validate_retry_settings!
|
|
145
|
+
validate_positive(:timeout, @timeout) if @timeout
|
|
146
|
+
validate_non_negative_integer(:retry_count, @retry_count) if @retry_count
|
|
147
|
+
validate_positive(:retry_delay, @retry_delay) if @retry_delay
|
|
148
|
+
validate_positive(:max_retry_delay, @max_retry_delay) if @max_retry_delay
|
|
149
|
+
|
|
150
|
+
if @retry_delay && @max_retry_delay && @max_retry_delay < @retry_delay
|
|
151
|
+
raise InvalidConfigError,
|
|
152
|
+
"max-retry-delay (#{@max_retry_delay}) must be >= retry-delay (#{@retry_delay})"
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# Validates that a value is a positive number.
|
|
157
|
+
#
|
|
158
|
+
# @param name [Symbol] attribute name for error message
|
|
159
|
+
# @param value [Object] value to validate
|
|
160
|
+
# @raise [InvalidConfigError] if value is not positive
|
|
161
|
+
def validate_positive(name, value)
|
|
162
|
+
return if value.is_a?(Numeric) && value.positive?
|
|
163
|
+
|
|
164
|
+
raise InvalidConfigError, "#{name} must be a positive number, got: #{value.inspect}"
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# Validates that a value is a non-negative integer.
|
|
168
|
+
#
|
|
169
|
+
# @param name [Symbol] attribute name for error message
|
|
170
|
+
# @param value [Object] value to validate
|
|
171
|
+
# @raise [InvalidConfigError] if value is not a non-negative integer
|
|
172
|
+
def validate_non_negative_integer(name, value)
|
|
173
|
+
return if value.is_a?(Integer) && value >= 0
|
|
174
|
+
|
|
175
|
+
raise InvalidConfigError, "#{name} must be a non-negative integer, got: #{value.inspect}"
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Config
|
|
5
|
+
module Models
|
|
6
|
+
# Represents a context linking a cluster to a user.
|
|
7
|
+
#
|
|
8
|
+
# Context is an immutable value object that binds together a cluster
|
|
9
|
+
# and user configuration, similar to kubectl contexts. It optionally
|
|
10
|
+
# includes a default node for operations.
|
|
11
|
+
#
|
|
12
|
+
# @example Creating a context
|
|
13
|
+
# context = Context.new(
|
|
14
|
+
# name: "production",
|
|
15
|
+
# cluster_ref: "pve-prod",
|
|
16
|
+
# user_ref: "admin",
|
|
17
|
+
# default_node: "pve1"
|
|
18
|
+
# )
|
|
19
|
+
#
|
|
20
|
+
# @example Creating from YAML config hash
|
|
21
|
+
# hash = {
|
|
22
|
+
# "name" => "prod",
|
|
23
|
+
# "context" => {
|
|
24
|
+
# "cluster" => "production",
|
|
25
|
+
# "user" => "admin-prod",
|
|
26
|
+
# "default-node" => "pve1"
|
|
27
|
+
# }
|
|
28
|
+
# }
|
|
29
|
+
# context = Context.from_hash(hash)
|
|
30
|
+
#
|
|
31
|
+
class Context
|
|
32
|
+
# @return [String] unique name identifying this context
|
|
33
|
+
attr_reader :name
|
|
34
|
+
|
|
35
|
+
# @return [String] reference to cluster name
|
|
36
|
+
attr_reader :cluster_ref
|
|
37
|
+
|
|
38
|
+
# @return [String] reference to user name
|
|
39
|
+
attr_reader :user_ref
|
|
40
|
+
|
|
41
|
+
# @return [String, nil] default node for operations
|
|
42
|
+
attr_reader :default_node
|
|
43
|
+
|
|
44
|
+
# Creates a new Context instance.
|
|
45
|
+
#
|
|
46
|
+
# @param name [String] unique name for this context
|
|
47
|
+
# @param cluster_ref [String] name of the cluster to use
|
|
48
|
+
# @param user_ref [String] name of the user to use
|
|
49
|
+
# @param default_node [String, nil] optional default node
|
|
50
|
+
def initialize(name:, cluster_ref:, user_ref:, default_node: nil)
|
|
51
|
+
@name = name
|
|
52
|
+
@cluster_ref = cluster_ref
|
|
53
|
+
@user_ref = user_ref
|
|
54
|
+
@default_node = default_node
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Creates a Context from a kubeconfig-style hash structure.
|
|
58
|
+
#
|
|
59
|
+
# @param hash [Hash] hash with "name" and "context" keys
|
|
60
|
+
# @return [Context] new context instance
|
|
61
|
+
#
|
|
62
|
+
# @example Hash structure
|
|
63
|
+
# {
|
|
64
|
+
# "name" => "prod",
|
|
65
|
+
# "context" => {
|
|
66
|
+
# "cluster" => "production",
|
|
67
|
+
# "user" => "admin-prod",
|
|
68
|
+
# "default-node" => "pve1"
|
|
69
|
+
# }
|
|
70
|
+
# }
|
|
71
|
+
def self.from_hash(hash)
|
|
72
|
+
context_data = hash["context"] || {}
|
|
73
|
+
|
|
74
|
+
new(
|
|
75
|
+
name: hash["name"],
|
|
76
|
+
cluster_ref: context_data["cluster"],
|
|
77
|
+
user_ref: context_data["user"],
|
|
78
|
+
default_node: context_data["default-node"]
|
|
79
|
+
)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Converts the context to a kubeconfig-style hash structure.
|
|
83
|
+
#
|
|
84
|
+
# @return [Hash] hash representation suitable for YAML serialization
|
|
85
|
+
def to_hash
|
|
86
|
+
context_data = {
|
|
87
|
+
"cluster" => cluster_ref,
|
|
88
|
+
"user" => user_ref
|
|
89
|
+
}
|
|
90
|
+
context_data["default-node"] = default_node if default_node
|
|
91
|
+
|
|
92
|
+
{
|
|
93
|
+
"name" => name,
|
|
94
|
+
"context" => context_data
|
|
95
|
+
}
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Config
|
|
5
|
+
module Models
|
|
6
|
+
# Represents the final resolved configuration ready for use.
|
|
7
|
+
#
|
|
8
|
+
# ResolvedConfig is an immutable value object containing all settings
|
|
9
|
+
# needed to connect to a Proxmox server. It is created by merging
|
|
10
|
+
# configuration from file, environment variables, and CLI options.
|
|
11
|
+
#
|
|
12
|
+
# @example Creating a resolved config with token auth
|
|
13
|
+
# config = ResolvedConfig.new(
|
|
14
|
+
# context_name: "production",
|
|
15
|
+
# server: "https://pve.example.com:8006",
|
|
16
|
+
# auth_type: :token,
|
|
17
|
+
# token_id: "root@pam!automation",
|
|
18
|
+
# token_secret: "secret-uuid"
|
|
19
|
+
# )
|
|
20
|
+
#
|
|
21
|
+
# @example Getting connection options for proxmox-api gem
|
|
22
|
+
# options = config.to_connection_options
|
|
23
|
+
# # => { server: "https://...", token: "root@pam!automation", ... }
|
|
24
|
+
#
|
|
25
|
+
class ResolvedConfig
|
|
26
|
+
# Default values for retry/timeout settings
|
|
27
|
+
DEFAULT_TIMEOUT = 30
|
|
28
|
+
DEFAULT_RETRY_COUNT = 3
|
|
29
|
+
DEFAULT_RETRY_DELAY = 1
|
|
30
|
+
DEFAULT_MAX_RETRY_DELAY = 30
|
|
31
|
+
DEFAULT_RETRY_WRITES = false
|
|
32
|
+
|
|
33
|
+
# @return [String] name of the active context
|
|
34
|
+
attr_reader :context_name
|
|
35
|
+
|
|
36
|
+
# @return [String] Proxmox server URL
|
|
37
|
+
attr_reader :server
|
|
38
|
+
|
|
39
|
+
# @return [Boolean] whether to verify SSL certificates
|
|
40
|
+
attr_reader :verify_ssl
|
|
41
|
+
|
|
42
|
+
# @return [String, nil] path to CA certificate file
|
|
43
|
+
attr_reader :certificate_authority
|
|
44
|
+
|
|
45
|
+
# @return [Symbol] authentication type (:token or :password)
|
|
46
|
+
attr_reader :auth_type
|
|
47
|
+
|
|
48
|
+
# @return [String, nil] API token ID
|
|
49
|
+
attr_reader :token_id
|
|
50
|
+
|
|
51
|
+
# @return [String, nil] API token secret
|
|
52
|
+
attr_reader :token_secret
|
|
53
|
+
|
|
54
|
+
# @return [String, nil] username for password auth
|
|
55
|
+
attr_reader :username
|
|
56
|
+
|
|
57
|
+
# @return [String, nil] password for password auth
|
|
58
|
+
attr_reader :password
|
|
59
|
+
|
|
60
|
+
# @return [String, nil] default node for operations
|
|
61
|
+
attr_reader :default_node
|
|
62
|
+
|
|
63
|
+
# @return [Integer] request timeout in seconds
|
|
64
|
+
attr_reader :timeout
|
|
65
|
+
|
|
66
|
+
# @return [Integer] maximum retry attempts
|
|
67
|
+
attr_reader :retry_count
|
|
68
|
+
|
|
69
|
+
# @return [Integer] base delay between retries in seconds
|
|
70
|
+
attr_reader :retry_delay
|
|
71
|
+
|
|
72
|
+
# @return [Integer] maximum delay cap for exponential backoff
|
|
73
|
+
attr_reader :max_retry_delay
|
|
74
|
+
|
|
75
|
+
# @return [Boolean] whether to retry write operations
|
|
76
|
+
attr_reader :retry_writes
|
|
77
|
+
|
|
78
|
+
# Creates a new ResolvedConfig instance.
|
|
79
|
+
#
|
|
80
|
+
# @param context_name [String] name of the active context
|
|
81
|
+
# @param server [String] Proxmox server URL
|
|
82
|
+
# @param auth_type [Symbol] :token or :password
|
|
83
|
+
# @param verify_ssl [Boolean] whether to verify SSL (default: true)
|
|
84
|
+
# @param certificate_authority [String, nil] path to CA certificate
|
|
85
|
+
# @param token_id [String, nil] API token ID (required for :token auth)
|
|
86
|
+
# @param token_secret [String, nil] API token secret (required for :token auth)
|
|
87
|
+
# @param username [String, nil] username (required for :password auth)
|
|
88
|
+
# @param password [String, nil] password (required for :password auth)
|
|
89
|
+
# @param default_node [String, nil] default node for operations
|
|
90
|
+
# @param timeout [Integer, nil] request timeout (default: 30)
|
|
91
|
+
# @param retry_count [Integer, nil] max retries (default: 3)
|
|
92
|
+
# @param retry_delay [Integer, nil] base delay (default: 1)
|
|
93
|
+
# @param max_retry_delay [Integer, nil] max delay cap (default: 30)
|
|
94
|
+
# @param retry_writes [Boolean, nil] retry writes (default: false)
|
|
95
|
+
def initialize(context_name:, server:, auth_type:, verify_ssl: true,
|
|
96
|
+
certificate_authority: nil, token_id: nil, token_secret: nil,
|
|
97
|
+
username: nil, password: nil, default_node: nil,
|
|
98
|
+
timeout: nil, retry_count: nil, retry_delay: nil,
|
|
99
|
+
max_retry_delay: nil, retry_writes: nil)
|
|
100
|
+
@context_name = context_name
|
|
101
|
+
@server = server
|
|
102
|
+
@verify_ssl = verify_ssl
|
|
103
|
+
@certificate_authority = certificate_authority
|
|
104
|
+
@auth_type = auth_type
|
|
105
|
+
@token_id = token_id
|
|
106
|
+
@token_secret = token_secret
|
|
107
|
+
@username = username
|
|
108
|
+
@password = password
|
|
109
|
+
@default_node = default_node
|
|
110
|
+
|
|
111
|
+
# Apply defaults for retry/timeout settings
|
|
112
|
+
@timeout = timeout || DEFAULT_TIMEOUT
|
|
113
|
+
@retry_count = retry_count || DEFAULT_RETRY_COUNT
|
|
114
|
+
@retry_delay = retry_delay || DEFAULT_RETRY_DELAY
|
|
115
|
+
@max_retry_delay = max_retry_delay || DEFAULT_MAX_RETRY_DELAY
|
|
116
|
+
@retry_writes = retry_writes.nil? ? DEFAULT_RETRY_WRITES : retry_writes
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Checks if this config uses API token authentication.
|
|
120
|
+
#
|
|
121
|
+
# @return [Boolean] true if auth_type is :token
|
|
122
|
+
def token_auth?
|
|
123
|
+
auth_type == :token
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Checks if this config uses password authentication.
|
|
127
|
+
#
|
|
128
|
+
# @return [Boolean] true if auth_type is :password
|
|
129
|
+
def password_auth?
|
|
130
|
+
auth_type == :password
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# Converts the config to options hash for proxmox-api gem.
|
|
134
|
+
#
|
|
135
|
+
# @return [Hash] options for ProxmoxAPI.new
|
|
136
|
+
#
|
|
137
|
+
# @example Token auth options
|
|
138
|
+
# {
|
|
139
|
+
# server: "https://pve.example.com:8006",
|
|
140
|
+
# token: "root@pam!automation",
|
|
141
|
+
# secret: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
|
|
142
|
+
# verify_ssl: false
|
|
143
|
+
# }
|
|
144
|
+
#
|
|
145
|
+
# @example Password auth options
|
|
146
|
+
# {
|
|
147
|
+
# server: "https://pve.example.com:8006",
|
|
148
|
+
# username: "root@pam",
|
|
149
|
+
# password: "secret",
|
|
150
|
+
# verify_ssl: true
|
|
151
|
+
# }
|
|
152
|
+
def to_connection_options
|
|
153
|
+
options = {
|
|
154
|
+
server: server,
|
|
155
|
+
verify_ssl: verify_ssl
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if token_auth?
|
|
159
|
+
options[:token] = token_id
|
|
160
|
+
options[:secret] = token_secret
|
|
161
|
+
else
|
|
162
|
+
options[:username] = username
|
|
163
|
+
options[:password] = password
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
options
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pvectl
|
|
4
|
+
module Config
|
|
5
|
+
module Models
|
|
6
|
+
# Represents user credentials for Proxmox API authentication.
|
|
7
|
+
#
|
|
8
|
+
# User is an immutable value object supporting two authentication methods:
|
|
9
|
+
# - API Token authentication (token_id + token_secret)
|
|
10
|
+
# - Username/Password authentication (username + password)
|
|
11
|
+
#
|
|
12
|
+
# @example Creating a user with token authentication
|
|
13
|
+
# user = User.new(
|
|
14
|
+
# name: "admin",
|
|
15
|
+
# token_id: "root@pam!automation",
|
|
16
|
+
# token_secret: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
|
17
|
+
# )
|
|
18
|
+
# user.token_auth? #=> true
|
|
19
|
+
#
|
|
20
|
+
# @example Creating a user with password authentication
|
|
21
|
+
# user = User.new(
|
|
22
|
+
# name: "admin",
|
|
23
|
+
# username: "root@pam",
|
|
24
|
+
# password: "secret"
|
|
25
|
+
# )
|
|
26
|
+
# user.password_auth? #=> true
|
|
27
|
+
#
|
|
28
|
+
class User
|
|
29
|
+
# Mask used to hide secrets in output
|
|
30
|
+
SECRET_MASK = "********"
|
|
31
|
+
|
|
32
|
+
# @return [String] unique name identifying this user
|
|
33
|
+
attr_reader :name
|
|
34
|
+
|
|
35
|
+
# @return [String, nil] API token ID (e.g., "root@pam!tokenid")
|
|
36
|
+
attr_reader :token_id
|
|
37
|
+
|
|
38
|
+
# @return [String, nil] API token secret (UUID format)
|
|
39
|
+
attr_reader :token_secret
|
|
40
|
+
|
|
41
|
+
# @return [String, nil] username for password auth (e.g., "root@pam")
|
|
42
|
+
attr_reader :username
|
|
43
|
+
|
|
44
|
+
# @return [String, nil] password for password auth
|
|
45
|
+
attr_reader :password
|
|
46
|
+
|
|
47
|
+
# Creates a new User instance.
|
|
48
|
+
#
|
|
49
|
+
# @param name [String] unique name for this user
|
|
50
|
+
# @param token_id [String, nil] API token ID
|
|
51
|
+
# @param token_secret [String, nil] API token secret
|
|
52
|
+
# @param username [String, nil] username for password auth
|
|
53
|
+
# @param password [String, nil] password for password auth
|
|
54
|
+
def initialize(name:, token_id: nil, token_secret: nil, username: nil, password: nil)
|
|
55
|
+
@name = name
|
|
56
|
+
@token_id = token_id
|
|
57
|
+
@token_secret = token_secret
|
|
58
|
+
@username = username
|
|
59
|
+
@password = password
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Checks if this user is configured for API token authentication.
|
|
63
|
+
#
|
|
64
|
+
# @return [Boolean] true if both token_id and token_secret are present
|
|
65
|
+
def token_auth?
|
|
66
|
+
!token_id.nil? && !token_id.empty? && !token_secret.nil? && !token_secret.empty?
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Checks if this user is configured for password authentication.
|
|
70
|
+
#
|
|
71
|
+
# @return [Boolean] true if both username and password are present
|
|
72
|
+
def password_auth?
|
|
73
|
+
!username.nil? && !username.empty? && !password.nil? && !password.empty?
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Checks if this user has valid credentials for authentication.
|
|
77
|
+
#
|
|
78
|
+
# @return [Boolean] true if token auth or password auth is configured
|
|
79
|
+
def valid?
|
|
80
|
+
token_auth? || password_auth?
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Creates a User from a kubeconfig-style hash structure.
|
|
84
|
+
#
|
|
85
|
+
# @param hash [Hash] hash with "name" and "user" keys
|
|
86
|
+
# @return [User] new user instance
|
|
87
|
+
#
|
|
88
|
+
# @example Hash structure for token auth
|
|
89
|
+
# {
|
|
90
|
+
# "name" => "admin",
|
|
91
|
+
# "user" => {
|
|
92
|
+
# "token-id" => "root@pam!token",
|
|
93
|
+
# "token-secret" => "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
|
94
|
+
# }
|
|
95
|
+
# }
|
|
96
|
+
def self.from_hash(hash)
|
|
97
|
+
user_data = hash["user"] || {}
|
|
98
|
+
|
|
99
|
+
new(
|
|
100
|
+
name: hash["name"],
|
|
101
|
+
token_id: user_data["token-id"],
|
|
102
|
+
token_secret: user_data["token-secret"],
|
|
103
|
+
username: user_data["username"],
|
|
104
|
+
password: user_data["password"]
|
|
105
|
+
)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Converts the user to a kubeconfig-style hash structure.
|
|
109
|
+
#
|
|
110
|
+
# @param mask_secrets [Boolean] whether to mask sensitive values
|
|
111
|
+
# @return [Hash] hash representation suitable for YAML serialization
|
|
112
|
+
def to_hash(mask_secrets: false)
|
|
113
|
+
user_data = {}
|
|
114
|
+
|
|
115
|
+
if token_auth?
|
|
116
|
+
user_data["token-id"] = token_id
|
|
117
|
+
user_data["token-secret"] = mask_secrets ? SECRET_MASK : token_secret
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
if password_auth?
|
|
121
|
+
user_data["username"] = username
|
|
122
|
+
user_data["password"] = mask_secrets ? SECRET_MASK : password
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
{
|
|
126
|
+
"name" => name,
|
|
127
|
+
"user" => user_data
|
|
128
|
+
}
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|