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.
Files changed (558) hide show
  1. checksums.yaml +7 -0
  2. data/.claude/rules/branch-before-changes.md +52 -0
  3. data/.claude/rules/documentation-updates.md +104 -0
  4. data/.claude/rules/git-workflow.md +84 -0
  5. data/.claude/rules/proxmox-api-docs.md +58 -0
  6. data/.claude/rules/rbs-signatures.md +80 -0
  7. data/.claude/rules/refactoring-as-design-option.md +35 -0
  8. data/.claude/scheduled_tasks.lock +1 -0
  9. data/.claude/settings.json +51 -0
  10. data/.mcp.json +8 -0
  11. data/.ruby-gemset +1 -0
  12. data/.ruby-version +1 -0
  13. data/CHANGELOG.md +138 -0
  14. data/CLAUDE.md +211 -0
  15. data/CODE_OF_CONDUCT.md +132 -0
  16. data/LICENSE.txt +21 -0
  17. data/README.md +143 -0
  18. data/Rakefile +8 -0
  19. data/docs/proxmox-api-update.sh +96 -0
  20. data/exe/pvectl +5 -0
  21. data/lib/pvectl/argv_preprocessor.rb +334 -0
  22. data/lib/pvectl/cli.rb +102 -0
  23. data/lib/pvectl/commands/apt.rb +389 -0
  24. data/lib/pvectl/commands/clone_container.rb +230 -0
  25. data/lib/pvectl/commands/clone_vm.rb +331 -0
  26. data/lib/pvectl/commands/cloudinit/command.rb +122 -0
  27. data/lib/pvectl/commands/cloudinit/dump.rb +94 -0
  28. data/lib/pvectl/commands/cloudinit/pending.rb +137 -0
  29. data/lib/pvectl/commands/cloudinit/regenerate.rb +79 -0
  30. data/lib/pvectl/commands/config/command.rb +65 -0
  31. data/lib/pvectl/commands/config/get_contexts.rb +68 -0
  32. data/lib/pvectl/commands/config/set_cluster.rb +103 -0
  33. data/lib/pvectl/commands/config/set_context.rb +136 -0
  34. data/lib/pvectl/commands/config/set_credentials.rb +181 -0
  35. data/lib/pvectl/commands/config/use_context.rb +69 -0
  36. data/lib/pvectl/commands/config/view.rb +67 -0
  37. data/lib/pvectl/commands/console.rb +93 -0
  38. data/lib/pvectl/commands/console_ct.rb +187 -0
  39. data/lib/pvectl/commands/console_vm.rb +187 -0
  40. data/lib/pvectl/commands/container_lifecycle_command.rb +77 -0
  41. data/lib/pvectl/commands/create_backup.rb +173 -0
  42. data/lib/pvectl/commands/create_container.rb +141 -0
  43. data/lib/pvectl/commands/create_resource_command.rb +244 -0
  44. data/lib/pvectl/commands/create_snapshot.rb +242 -0
  45. data/lib/pvectl/commands/create_vm.rb +267 -0
  46. data/lib/pvectl/commands/delete_backup.rb +139 -0
  47. data/lib/pvectl/commands/delete_command.rb +119 -0
  48. data/lib/pvectl/commands/delete_container.rb +30 -0
  49. data/lib/pvectl/commands/delete_snapshot.rb +248 -0
  50. data/lib/pvectl/commands/delete_vm.rb +127 -0
  51. data/lib/pvectl/commands/describe/command.rb +251 -0
  52. data/lib/pvectl/commands/edit_container.rb +56 -0
  53. data/lib/pvectl/commands/edit_dns.rb +149 -0
  54. data/lib/pvectl/commands/edit_hosts.rb +135 -0
  55. data/lib/pvectl/commands/edit_node.rb +54 -0
  56. data/lib/pvectl/commands/edit_resource_command.rb +180 -0
  57. data/lib/pvectl/commands/edit_vm.rb +154 -0
  58. data/lib/pvectl/commands/edit_volume.rb +189 -0
  59. data/lib/pvectl/commands/feature_command.rb +230 -0
  60. data/lib/pvectl/commands/feature_container.rb +21 -0
  61. data/lib/pvectl/commands/feature_vm.rb +94 -0
  62. data/lib/pvectl/commands/get/command.rb +360 -0
  63. data/lib/pvectl/commands/get/handlers/backups.rb +76 -0
  64. data/lib/pvectl/commands/get/handlers/capabilities.rb +107 -0
  65. data/lib/pvectl/commands/get/handlers/containers.rb +148 -0
  66. data/lib/pvectl/commands/get/handlers/disks.rb +107 -0
  67. data/lib/pvectl/commands/get/handlers/dns.rb +94 -0
  68. data/lib/pvectl/commands/get/handlers/hosts.rb +94 -0
  69. data/lib/pvectl/commands/get/handlers/nodes.rb +162 -0
  70. data/lib/pvectl/commands/get/handlers/services.rb +81 -0
  71. data/lib/pvectl/commands/get/handlers/snapshots.rb +97 -0
  72. data/lib/pvectl/commands/get/handlers/storage.rb +118 -0
  73. data/lib/pvectl/commands/get/handlers/subscription.rb +69 -0
  74. data/lib/pvectl/commands/get/handlers/tasks.rb +89 -0
  75. data/lib/pvectl/commands/get/handlers/templates.rb +175 -0
  76. data/lib/pvectl/commands/get/handlers/time.rb +118 -0
  77. data/lib/pvectl/commands/get/handlers/vms.rb +145 -0
  78. data/lib/pvectl/commands/get/handlers/volume.rb +134 -0
  79. data/lib/pvectl/commands/get/resource_handler.rb +63 -0
  80. data/lib/pvectl/commands/get/resource_registry.rb +18 -0
  81. data/lib/pvectl/commands/get/watch_loop.rb +129 -0
  82. data/lib/pvectl/commands/irreversible_command.rb +265 -0
  83. data/lib/pvectl/commands/logs/command.rb +275 -0
  84. data/lib/pvectl/commands/logs/handlers/journal.rb +46 -0
  85. data/lib/pvectl/commands/logs/handlers/syslog.rb +53 -0
  86. data/lib/pvectl/commands/logs/handlers/task_detail.rb +52 -0
  87. data/lib/pvectl/commands/logs/handlers/task_logs.rb +115 -0
  88. data/lib/pvectl/commands/logs/resource_handler.rb +46 -0
  89. data/lib/pvectl/commands/logs/resource_registry.rb +22 -0
  90. data/lib/pvectl/commands/migrate_command.rb +282 -0
  91. data/lib/pvectl/commands/migrate_container.rb +23 -0
  92. data/lib/pvectl/commands/migrate_vm.rb +122 -0
  93. data/lib/pvectl/commands/move_disk_command.rb +239 -0
  94. data/lib/pvectl/commands/move_disk_container.rb +21 -0
  95. data/lib/pvectl/commands/move_disk_vm.rb +127 -0
  96. data/lib/pvectl/commands/ping.rb +249 -0
  97. data/lib/pvectl/commands/pull.rb +342 -0
  98. data/lib/pvectl/commands/push.rb +352 -0
  99. data/lib/pvectl/commands/reset.rb +64 -0
  100. data/lib/pvectl/commands/resource_lifecycle_command.rb +277 -0
  101. data/lib/pvectl/commands/resource_registry.rb +73 -0
  102. data/lib/pvectl/commands/restart.rb +70 -0
  103. data/lib/pvectl/commands/restart_container.rb +18 -0
  104. data/lib/pvectl/commands/restore_backup.rb +236 -0
  105. data/lib/pvectl/commands/resume.rb +57 -0
  106. data/lib/pvectl/commands/rollback_snapshot.rb +228 -0
  107. data/lib/pvectl/commands/sendkey_vm.rb +205 -0
  108. data/lib/pvectl/commands/service.rb +293 -0
  109. data/lib/pvectl/commands/set_container.rb +50 -0
  110. data/lib/pvectl/commands/set_node.rb +52 -0
  111. data/lib/pvectl/commands/set_resource_command.rb +185 -0
  112. data/lib/pvectl/commands/set_vm.rb +136 -0
  113. data/lib/pvectl/commands/set_volume.rb +212 -0
  114. data/lib/pvectl/commands/shared_config_parsers.rb +126 -0
  115. data/lib/pvectl/commands/shared_flags.rb +155 -0
  116. data/lib/pvectl/commands/shutdown.rb +73 -0
  117. data/lib/pvectl/commands/shutdown_container.rb +18 -0
  118. data/lib/pvectl/commands/start.rb +79 -0
  119. data/lib/pvectl/commands/start_container.rb +18 -0
  120. data/lib/pvectl/commands/stop.rb +75 -0
  121. data/lib/pvectl/commands/stop_container.rb +18 -0
  122. data/lib/pvectl/commands/suspend.rb +64 -0
  123. data/lib/pvectl/commands/template_command.rb +205 -0
  124. data/lib/pvectl/commands/template_container.rb +27 -0
  125. data/lib/pvectl/commands/template_vm.rb +106 -0
  126. data/lib/pvectl/commands/top/command.rb +206 -0
  127. data/lib/pvectl/commands/top/handlers/containers.rb +61 -0
  128. data/lib/pvectl/commands/top/handlers/nodes.rb +61 -0
  129. data/lib/pvectl/commands/top/handlers/vms.rb +61 -0
  130. data/lib/pvectl/commands/top/resource_handler.rb +46 -0
  131. data/lib/pvectl/commands/top/resource_registry.rb +22 -0
  132. data/lib/pvectl/commands/unlink_disk_vm.rb +232 -0
  133. data/lib/pvectl/commands/vm_lifecycle_command.rb +77 -0
  134. data/lib/pvectl/commands/wakeonlan_node.rb +153 -0
  135. data/lib/pvectl/config/errors.rb +62 -0
  136. data/lib/pvectl/config/models/cluster.rb +180 -0
  137. data/lib/pvectl/config/models/context.rb +100 -0
  138. data/lib/pvectl/config/models/resolved_config.rb +171 -0
  139. data/lib/pvectl/config/models/user.rb +133 -0
  140. data/lib/pvectl/config/provider.rb +297 -0
  141. data/lib/pvectl/config/service.rb +300 -0
  142. data/lib/pvectl/config/store.rb +161 -0
  143. data/lib/pvectl/config/wizard.rb +309 -0
  144. data/lib/pvectl/config_serializer.rb +1034 -0
  145. data/lib/pvectl/connection/retry_handler.rb +161 -0
  146. data/lib/pvectl/connection.rb +157 -0
  147. data/lib/pvectl/console/terminal_session.rb +449 -0
  148. data/lib/pvectl/editor_session.rb +157 -0
  149. data/lib/pvectl/exit_codes.rb +43 -0
  150. data/lib/pvectl/formatters/base.rb +55 -0
  151. data/lib/pvectl/formatters/color_support.rb +90 -0
  152. data/lib/pvectl/formatters/json.rb +45 -0
  153. data/lib/pvectl/formatters/output_helper.rb +77 -0
  154. data/lib/pvectl/formatters/registry.rb +72 -0
  155. data/lib/pvectl/formatters/table.rb +235 -0
  156. data/lib/pvectl/formatters/wide.rb +93 -0
  157. data/lib/pvectl/formatters/yaml.rb +49 -0
  158. data/lib/pvectl/manifest_serializer.rb +142 -0
  159. data/lib/pvectl/models/apt_package.rb +107 -0
  160. data/lib/pvectl/models/backup.rb +173 -0
  161. data/lib/pvectl/models/base.rb +49 -0
  162. data/lib/pvectl/models/capability.rb +62 -0
  163. data/lib/pvectl/models/container.rb +205 -0
  164. data/lib/pvectl/models/container_operation_result.rb +27 -0
  165. data/lib/pvectl/models/dns_config.rb +54 -0
  166. data/lib/pvectl/models/hosts_file.rb +47 -0
  167. data/lib/pvectl/models/journal_entry.rb +16 -0
  168. data/lib/pvectl/models/network_interface.rb +85 -0
  169. data/lib/pvectl/models/node.rb +195 -0
  170. data/lib/pvectl/models/node_operation_result.rb +45 -0
  171. data/lib/pvectl/models/operation_result.rb +110 -0
  172. data/lib/pvectl/models/physical_disk.rb +193 -0
  173. data/lib/pvectl/models/service.rb +80 -0
  174. data/lib/pvectl/models/snapshot.rb +101 -0
  175. data/lib/pvectl/models/snapshot_description.rb +39 -0
  176. data/lib/pvectl/models/storage.rb +180 -0
  177. data/lib/pvectl/models/subscription.rb +87 -0
  178. data/lib/pvectl/models/syslog_entry.rb +17 -0
  179. data/lib/pvectl/models/task.rb +95 -0
  180. data/lib/pvectl/models/task_entry.rb +52 -0
  181. data/lib/pvectl/models/task_log_line.rb +17 -0
  182. data/lib/pvectl/models/time_config.rb +47 -0
  183. data/lib/pvectl/models/vm.rb +137 -0
  184. data/lib/pvectl/models/vm_operation_result.rb +27 -0
  185. data/lib/pvectl/models/volume.rb +133 -0
  186. data/lib/pvectl/models/volume_operation_result.rb +26 -0
  187. data/lib/pvectl/parsers/cloud_init_config.rb +92 -0
  188. data/lib/pvectl/parsers/disk_config.rb +97 -0
  189. data/lib/pvectl/parsers/lxc_mount_config.rb +98 -0
  190. data/lib/pvectl/parsers/lxc_net_config.rb +97 -0
  191. data/lib/pvectl/parsers/net_config.rb +95 -0
  192. data/lib/pvectl/parsers/smart_text.rb +42 -0
  193. data/lib/pvectl/plugin_loader.rb +157 -0
  194. data/lib/pvectl/presenters/apt_package.rb +99 -0
  195. data/lib/pvectl/presenters/backup.rb +128 -0
  196. data/lib/pvectl/presenters/base.rb +283 -0
  197. data/lib/pvectl/presenters/capability.rb +104 -0
  198. data/lib/pvectl/presenters/config/context.rb +80 -0
  199. data/lib/pvectl/presenters/container.rb +574 -0
  200. data/lib/pvectl/presenters/container_operation_result.rb +109 -0
  201. data/lib/pvectl/presenters/disk.rb +184 -0
  202. data/lib/pvectl/presenters/dns_config.rb +68 -0
  203. data/lib/pvectl/presenters/hosts_file.rb +61 -0
  204. data/lib/pvectl/presenters/journal_entry.rb +20 -0
  205. data/lib/pvectl/presenters/node.rb +762 -0
  206. data/lib/pvectl/presenters/node_operation_result.rb +50 -0
  207. data/lib/pvectl/presenters/operation_result.rb +61 -0
  208. data/lib/pvectl/presenters/service.rb +76 -0
  209. data/lib/pvectl/presenters/snapshot.rb +239 -0
  210. data/lib/pvectl/presenters/snapshot_operation_result.rb +125 -0
  211. data/lib/pvectl/presenters/storage.rb +329 -0
  212. data/lib/pvectl/presenters/subscription.rb +189 -0
  213. data/lib/pvectl/presenters/syslog_entry.rb +20 -0
  214. data/lib/pvectl/presenters/task_entry.rb +69 -0
  215. data/lib/pvectl/presenters/task_log_line.rb +20 -0
  216. data/lib/pvectl/presenters/template.rb +76 -0
  217. data/lib/pvectl/presenters/time_config.rb +86 -0
  218. data/lib/pvectl/presenters/top_container.rb +112 -0
  219. data/lib/pvectl/presenters/top_node.rb +115 -0
  220. data/lib/pvectl/presenters/top_presenter.rb +59 -0
  221. data/lib/pvectl/presenters/top_vm.rb +105 -0
  222. data/lib/pvectl/presenters/vm.rb +853 -0
  223. data/lib/pvectl/presenters/vm_operation_result.rb +109 -0
  224. data/lib/pvectl/presenters/volume.rb +136 -0
  225. data/lib/pvectl/presenters/volume_operation_result.rb +58 -0
  226. data/lib/pvectl/repositories/apt.rb +93 -0
  227. data/lib/pvectl/repositories/backup.rb +186 -0
  228. data/lib/pvectl/repositories/base.rb +110 -0
  229. data/lib/pvectl/repositories/capabilities.rb +96 -0
  230. data/lib/pvectl/repositories/container.rb +503 -0
  231. data/lib/pvectl/repositories/disk.rb +87 -0
  232. data/lib/pvectl/repositories/dns.rb +54 -0
  233. data/lib/pvectl/repositories/hosts.rb +63 -0
  234. data/lib/pvectl/repositories/journal.rb +23 -0
  235. data/lib/pvectl/repositories/node.rb +537 -0
  236. data/lib/pvectl/repositories/service.rb +139 -0
  237. data/lib/pvectl/repositories/snapshot.rb +133 -0
  238. data/lib/pvectl/repositories/storage.rb +302 -0
  239. data/lib/pvectl/repositories/subscription.rb +77 -0
  240. data/lib/pvectl/repositories/syslog.rb +25 -0
  241. data/lib/pvectl/repositories/task.rb +82 -0
  242. data/lib/pvectl/repositories/task_list.rb +30 -0
  243. data/lib/pvectl/repositories/task_log.rb +31 -0
  244. data/lib/pvectl/repositories/time_config.rb +53 -0
  245. data/lib/pvectl/repositories/vm.rb +616 -0
  246. data/lib/pvectl/repositories/volume.rb +306 -0
  247. data/lib/pvectl/selectors/base.rb +201 -0
  248. data/lib/pvectl/selectors/container.rb +116 -0
  249. data/lib/pvectl/selectors/disk.rb +59 -0
  250. data/lib/pvectl/selectors/vm.rb +116 -0
  251. data/lib/pvectl/selectors/volume.rb +59 -0
  252. data/lib/pvectl/services/backup.rb +209 -0
  253. data/lib/pvectl/services/clone_container.rb +260 -0
  254. data/lib/pvectl/services/clone_vm.rb +265 -0
  255. data/lib/pvectl/services/cloudinit.rb +96 -0
  256. data/lib/pvectl/services/console.rb +152 -0
  257. data/lib/pvectl/services/container_lifecycle.rb +124 -0
  258. data/lib/pvectl/services/create_container.rb +179 -0
  259. data/lib/pvectl/services/create_vm.rb +191 -0
  260. data/lib/pvectl/services/edit_container.rb +125 -0
  261. data/lib/pvectl/services/edit_dns.rb +159 -0
  262. data/lib/pvectl/services/edit_hosts.rb +78 -0
  263. data/lib/pvectl/services/edit_node.rb +147 -0
  264. data/lib/pvectl/services/edit_vm.rb +125 -0
  265. data/lib/pvectl/services/edit_volume.rb +224 -0
  266. data/lib/pvectl/services/get/resource_service.rb +98 -0
  267. data/lib/pvectl/services/move_disk.rb +132 -0
  268. data/lib/pvectl/services/pull_config.rb +94 -0
  269. data/lib/pvectl/services/push_config.rb +524 -0
  270. data/lib/pvectl/services/resize_volume.rb +253 -0
  271. data/lib/pvectl/services/resource_delete.rb +169 -0
  272. data/lib/pvectl/services/resource_migration.rb +170 -0
  273. data/lib/pvectl/services/sendkey.rb +108 -0
  274. data/lib/pvectl/services/service_lifecycle.rb +89 -0
  275. data/lib/pvectl/services/set_container.rb +128 -0
  276. data/lib/pvectl/services/set_node.rb +236 -0
  277. data/lib/pvectl/services/set_vm.rb +128 -0
  278. data/lib/pvectl/services/set_volume.rb +126 -0
  279. data/lib/pvectl/services/snapshot.rb +261 -0
  280. data/lib/pvectl/services/task_listing.rb +75 -0
  281. data/lib/pvectl/services/unlink_disk.rb +86 -0
  282. data/lib/pvectl/services/vm_lifecycle.rb +124 -0
  283. data/lib/pvectl/services/wakeonlan.rb +79 -0
  284. data/lib/pvectl/utils/resource_resolver.rb +80 -0
  285. data/lib/pvectl/version.rb +13 -0
  286. data/lib/pvectl/wizards/create_container.rb +105 -0
  287. data/lib/pvectl/wizards/create_vm.rb +98 -0
  288. data/lib/pvectl.rb +439 -0
  289. data/sig/external/gli.rbs +16 -0
  290. data/sig/external/proxmox_api.rbs +10 -0
  291. data/sig/pvectl/argv_preprocessor.rbs +53 -0
  292. data/sig/pvectl/cli.rbs +26 -0
  293. data/sig/pvectl/commands/apt.rbs +47 -0
  294. data/sig/pvectl/commands/clone_container.rbs +31 -0
  295. data/sig/pvectl/commands/clone_vm.rbs +33 -0
  296. data/sig/pvectl/commands/cloudinit/command.rbs +13 -0
  297. data/sig/pvectl/commands/cloudinit/dump.rbs +13 -0
  298. data/sig/pvectl/commands/cloudinit/pending.rbs +17 -0
  299. data/sig/pvectl/commands/cloudinit/regenerate.rbs +11 -0
  300. data/sig/pvectl/commands/config/command.rbs +9 -0
  301. data/sig/pvectl/commands/config/get_contexts.rbs +11 -0
  302. data/sig/pvectl/commands/config/set_cluster.rbs +11 -0
  303. data/sig/pvectl/commands/config/set_context.rbs +15 -0
  304. data/sig/pvectl/commands/config/set_credentials.rbs +15 -0
  305. data/sig/pvectl/commands/config/use_context.rbs +11 -0
  306. data/sig/pvectl/commands/config/view.rbs +11 -0
  307. data/sig/pvectl/commands/console.rbs +9 -0
  308. data/sig/pvectl/commands/console_ct.rbs +27 -0
  309. data/sig/pvectl/commands/console_vm.rbs +27 -0
  310. data/sig/pvectl/commands/container_lifecycle_command.rbs +25 -0
  311. data/sig/pvectl/commands/create_backup.rbs +29 -0
  312. data/sig/pvectl/commands/create_container.rbs +30 -0
  313. data/sig/pvectl/commands/create_resource_command.rbs +53 -0
  314. data/sig/pvectl/commands/create_snapshot.rbs +35 -0
  315. data/sig/pvectl/commands/create_vm.rbs +30 -0
  316. data/sig/pvectl/commands/delete_backup.rbs +25 -0
  317. data/sig/pvectl/commands/delete_command.rbs +45 -0
  318. data/sig/pvectl/commands/delete_container.rbs +11 -0
  319. data/sig/pvectl/commands/delete_snapshot.rbs +35 -0
  320. data/sig/pvectl/commands/delete_vm.rbs +13 -0
  321. data/sig/pvectl/commands/describe/command.rbs +27 -0
  322. data/sig/pvectl/commands/edit_container.rbs +17 -0
  323. data/sig/pvectl/commands/edit_dns.rbs +25 -0
  324. data/sig/pvectl/commands/edit_hosts.rbs +23 -0
  325. data/sig/pvectl/commands/edit_node.rbs +17 -0
  326. data/sig/pvectl/commands/edit_resource_command.rbs +35 -0
  327. data/sig/pvectl/commands/edit_vm.rbs +19 -0
  328. data/sig/pvectl/commands/edit_volume.rbs +24 -0
  329. data/sig/pvectl/commands/feature_command.rbs +43 -0
  330. data/sig/pvectl/commands/feature_container.rbs +10 -0
  331. data/sig/pvectl/commands/feature_vm.rbs +12 -0
  332. data/sig/pvectl/commands/get/command.rbs +42 -0
  333. data/sig/pvectl/commands/get/handlers/backups.rbs +23 -0
  334. data/sig/pvectl/commands/get/handlers/capabilities.rbs +29 -0
  335. data/sig/pvectl/commands/get/handlers/containers.rbs +35 -0
  336. data/sig/pvectl/commands/get/handlers/disks.rbs +27 -0
  337. data/sig/pvectl/commands/get/handlers/dns.rbs +25 -0
  338. data/sig/pvectl/commands/get/handlers/hosts.rbs +25 -0
  339. data/sig/pvectl/commands/get/handlers/nodes.rbs +33 -0
  340. data/sig/pvectl/commands/get/handlers/services.rbs +23 -0
  341. data/sig/pvectl/commands/get/handlers/snapshots.rbs +27 -0
  342. data/sig/pvectl/commands/get/handlers/storage.rbs +25 -0
  343. data/sig/pvectl/commands/get/handlers/subscription.rbs +25 -0
  344. data/sig/pvectl/commands/get/handlers/tasks.rbs +28 -0
  345. data/sig/pvectl/commands/get/handlers/templates.rbs +35 -0
  346. data/sig/pvectl/commands/get/handlers/time.rbs +29 -0
  347. data/sig/pvectl/commands/get/handlers/vms.rbs +35 -0
  348. data/sig/pvectl/commands/get/handlers/volume.rbs +27 -0
  349. data/sig/pvectl/commands/get/resource_handler.rbs +13 -0
  350. data/sig/pvectl/commands/get/resource_registry.rbs +8 -0
  351. data/sig/pvectl/commands/get/watch_loop.rbs +33 -0
  352. data/sig/pvectl/commands/irreversible_command.rbs +32 -0
  353. data/sig/pvectl/commands/logs/command.rbs +35 -0
  354. data/sig/pvectl/commands/logs/handlers/journal.rbs +21 -0
  355. data/sig/pvectl/commands/logs/handlers/syslog.rbs +21 -0
  356. data/sig/pvectl/commands/logs/handlers/task_detail.rbs +21 -0
  357. data/sig/pvectl/commands/logs/handlers/task_logs.rbs +35 -0
  358. data/sig/pvectl/commands/logs/resource_handler.rbs +11 -0
  359. data/sig/pvectl/commands/logs/resource_registry.rbs +8 -0
  360. data/sig/pvectl/commands/migrate_command.rbs +45 -0
  361. data/sig/pvectl/commands/migrate_container.rbs +11 -0
  362. data/sig/pvectl/commands/migrate_vm.rbs +13 -0
  363. data/sig/pvectl/commands/move_disk_command.rbs +43 -0
  364. data/sig/pvectl/commands/move_disk_container.rbs +11 -0
  365. data/sig/pvectl/commands/move_disk_vm.rbs +13 -0
  366. data/sig/pvectl/commands/ping.rbs +39 -0
  367. data/sig/pvectl/commands/pull.rbs +33 -0
  368. data/sig/pvectl/commands/push.rbs +32 -0
  369. data/sig/pvectl/commands/reset.rbs +11 -0
  370. data/sig/pvectl/commands/resource_lifecycle_command.rbs +55 -0
  371. data/sig/pvectl/commands/resource_registry.rbs +19 -0
  372. data/sig/pvectl/commands/restart.rbs +11 -0
  373. data/sig/pvectl/commands/restart_container.rbs +9 -0
  374. data/sig/pvectl/commands/restore_backup.rbs +27 -0
  375. data/sig/pvectl/commands/resume.rbs +11 -0
  376. data/sig/pvectl/commands/rollback_snapshot.rbs +31 -0
  377. data/sig/pvectl/commands/sendkey_vm.rbs +25 -0
  378. data/sig/pvectl/commands/service.rbs +38 -0
  379. data/sig/pvectl/commands/set_container.rbs +13 -0
  380. data/sig/pvectl/commands/set_node.rbs +13 -0
  381. data/sig/pvectl/commands/set_resource_command.rbs +25 -0
  382. data/sig/pvectl/commands/set_vm.rbs +15 -0
  383. data/sig/pvectl/commands/set_volume.rbs +24 -0
  384. data/sig/pvectl/commands/shared_config_parsers.rbs +19 -0
  385. data/sig/pvectl/commands/shared_flags.rbs +10 -0
  386. data/sig/pvectl/commands/shutdown.rbs +11 -0
  387. data/sig/pvectl/commands/shutdown_container.rbs +9 -0
  388. data/sig/pvectl/commands/start.rbs +11 -0
  389. data/sig/pvectl/commands/start_container.rbs +9 -0
  390. data/sig/pvectl/commands/stop.rbs +11 -0
  391. data/sig/pvectl/commands/stop_container.rbs +9 -0
  392. data/sig/pvectl/commands/suspend.rbs +11 -0
  393. data/sig/pvectl/commands/template_command.rbs +21 -0
  394. data/sig/pvectl/commands/template_container.rbs +10 -0
  395. data/sig/pvectl/commands/template_vm.rbs +12 -0
  396. data/sig/pvectl/commands/top/command.rbs +31 -0
  397. data/sig/pvectl/commands/top/handlers/containers.rbs +21 -0
  398. data/sig/pvectl/commands/top/handlers/nodes.rbs +21 -0
  399. data/sig/pvectl/commands/top/handlers/vms.rbs +21 -0
  400. data/sig/pvectl/commands/top/resource_handler.rbs +11 -0
  401. data/sig/pvectl/commands/top/resource_registry.rbs +8 -0
  402. data/sig/pvectl/commands/unlink_disk_vm.rbs +27 -0
  403. data/sig/pvectl/commands/vm_lifecycle_command.rbs +25 -0
  404. data/sig/pvectl/commands/wakeonlan_node.rbs +21 -0
  405. data/sig/pvectl/config/errors.rbs +24 -0
  406. data/sig/pvectl/config/models/cluster.rbs +39 -0
  407. data/sig/pvectl/config/models/context.rbs +23 -0
  408. data/sig/pvectl/config/models/resolved_config.rbs +51 -0
  409. data/sig/pvectl/config/models/user.rbs +31 -0
  410. data/sig/pvectl/config/provider.rbs +40 -0
  411. data/sig/pvectl/config/service.rbs +65 -0
  412. data/sig/pvectl/config/store.rbs +14 -0
  413. data/sig/pvectl/config/wizard.rbs +48 -0
  414. data/sig/pvectl/config_serializer.rbs +121 -0
  415. data/sig/pvectl/connection/retry_handler.rbs +31 -0
  416. data/sig/pvectl/connection.rbs +35 -0
  417. data/sig/pvectl/console/terminal_session.rbs +63 -0
  418. data/sig/pvectl/editor_session.rbs +33 -0
  419. data/sig/pvectl/exit_codes.rbs +19 -0
  420. data/sig/pvectl/formatters/base.rbs +13 -0
  421. data/sig/pvectl/formatters/color_support.rbs +13 -0
  422. data/sig/pvectl/formatters/json.rbs +7 -0
  423. data/sig/pvectl/formatters/output_helper.rbs +9 -0
  424. data/sig/pvectl/formatters/registry.rbs +13 -0
  425. data/sig/pvectl/formatters/table.rbs +25 -0
  426. data/sig/pvectl/formatters/wide.rbs +15 -0
  427. data/sig/pvectl/formatters/yaml.rbs +7 -0
  428. data/sig/pvectl/manifest_serializer.rbs +18 -0
  429. data/sig/pvectl/models/apt_package.rbs +26 -0
  430. data/sig/pvectl/models/backup.rbs +31 -0
  431. data/sig/pvectl/models/base.rbs +11 -0
  432. data/sig/pvectl/models/capability.rbs +16 -0
  433. data/sig/pvectl/models/container.rbs +44 -0
  434. data/sig/pvectl/models/container_operation_result.rbs +9 -0
  435. data/sig/pvectl/models/dns_config.rbs +15 -0
  436. data/sig/pvectl/models/hosts_file.rbs +13 -0
  437. data/sig/pvectl/models/journal_entry.rbs +10 -0
  438. data/sig/pvectl/models/network_interface.rbs +20 -0
  439. data/sig/pvectl/models/node.rbs +47 -0
  440. data/sig/pvectl/models/node_operation_result.rbs +12 -0
  441. data/sig/pvectl/models/operation_result.rbs +21 -0
  442. data/sig/pvectl/models/physical_disk.rbs +35 -0
  443. data/sig/pvectl/models/service.rbs +18 -0
  444. data/sig/pvectl/models/snapshot.rbs +21 -0
  445. data/sig/pvectl/models/snapshot_description.rbs +18 -0
  446. data/sig/pvectl/models/storage.rbs +39 -0
  447. data/sig/pvectl/models/subscription.rbs +24 -0
  448. data/sig/pvectl/models/syslog_entry.rbs +10 -0
  449. data/sig/pvectl/models/task.rbs +22 -0
  450. data/sig/pvectl/models/task_entry.rbs +24 -0
  451. data/sig/pvectl/models/task_log_line.rbs +10 -0
  452. data/sig/pvectl/models/time_config.rbs +12 -0
  453. data/sig/pvectl/models/vm.rbs +32 -0
  454. data/sig/pvectl/models/vm_operation_result.rbs +9 -0
  455. data/sig/pvectl/models/volume.rbs +29 -0
  456. data/sig/pvectl/models/volume_operation_result.rbs +9 -0
  457. data/sig/pvectl/parsers/cloud_init_config.rbs +15 -0
  458. data/sig/pvectl/parsers/disk_config.rbs +19 -0
  459. data/sig/pvectl/parsers/lxc_mount_config.rbs +19 -0
  460. data/sig/pvectl/parsers/lxc_net_config.rbs +19 -0
  461. data/sig/pvectl/parsers/net_config.rbs +19 -0
  462. data/sig/pvectl/parsers/smart_text.rbs +7 -0
  463. data/sig/pvectl/plugin_loader.rbs +25 -0
  464. data/sig/pvectl/presenters/apt_package.rbs +19 -0
  465. data/sig/pvectl/presenters/backup.rbs +25 -0
  466. data/sig/pvectl/presenters/base.rbs +41 -0
  467. data/sig/pvectl/presenters/capability.rbs +19 -0
  468. data/sig/pvectl/presenters/config/context.rbs +17 -0
  469. data/sig/pvectl/presenters/container.rbs +78 -0
  470. data/sig/pvectl/presenters/container_operation_result.rbs +19 -0
  471. data/sig/pvectl/presenters/disk.rbs +31 -0
  472. data/sig/pvectl/presenters/dns_config.rbs +13 -0
  473. data/sig/pvectl/presenters/hosts_file.rbs +13 -0
  474. data/sig/pvectl/presenters/journal_entry.rbs +11 -0
  475. data/sig/pvectl/presenters/node.rbs +118 -0
  476. data/sig/pvectl/presenters/node_operation_result.rbs +11 -0
  477. data/sig/pvectl/presenters/operation_result.rbs +17 -0
  478. data/sig/pvectl/presenters/service.rbs +15 -0
  479. data/sig/pvectl/presenters/snapshot.rbs +35 -0
  480. data/sig/pvectl/presenters/snapshot_operation_result.rbs +27 -0
  481. data/sig/pvectl/presenters/storage.rbs +59 -0
  482. data/sig/pvectl/presenters/subscription.rbs +36 -0
  483. data/sig/pvectl/presenters/syslog_entry.rbs +11 -0
  484. data/sig/pvectl/presenters/task_entry.rbs +21 -0
  485. data/sig/pvectl/presenters/task_log_line.rbs +11 -0
  486. data/sig/pvectl/presenters/template.rbs +15 -0
  487. data/sig/pvectl/presenters/time_config.rbs +19 -0
  488. data/sig/pvectl/presenters/top_container.rbs +17 -0
  489. data/sig/pvectl/presenters/top_node.rbs +17 -0
  490. data/sig/pvectl/presenters/top_presenter.rbs +13 -0
  491. data/sig/pvectl/presenters/top_vm.rbs +17 -0
  492. data/sig/pvectl/presenters/vm.rbs +91 -0
  493. data/sig/pvectl/presenters/vm_operation_result.rbs +19 -0
  494. data/sig/pvectl/presenters/volume.rbs +23 -0
  495. data/sig/pvectl/presenters/volume_operation_result.rbs +11 -0
  496. data/sig/pvectl/repositories/apt.rbs +17 -0
  497. data/sig/pvectl/repositories/backup.rbs +27 -0
  498. data/sig/pvectl/repositories/base.rbs +23 -0
  499. data/sig/pvectl/repositories/capabilities.rbs +20 -0
  500. data/sig/pvectl/repositories/container.rbs +63 -0
  501. data/sig/pvectl/repositories/disk.rbs +17 -0
  502. data/sig/pvectl/repositories/dns.rbs +13 -0
  503. data/sig/pvectl/repositories/hosts.rbs +13 -0
  504. data/sig/pvectl/repositories/journal.rbs +7 -0
  505. data/sig/pvectl/repositories/node.rbs +68 -0
  506. data/sig/pvectl/repositories/service.rbs +27 -0
  507. data/sig/pvectl/repositories/snapshot.rbs +19 -0
  508. data/sig/pvectl/repositories/storage.rbs +37 -0
  509. data/sig/pvectl/repositories/subscription.rbs +17 -0
  510. data/sig/pvectl/repositories/syslog.rbs +7 -0
  511. data/sig/pvectl/repositories/task.rbs +19 -0
  512. data/sig/pvectl/repositories/task_list.rbs +7 -0
  513. data/sig/pvectl/repositories/task_log.rbs +11 -0
  514. data/sig/pvectl/repositories/time_config.rbs +13 -0
  515. data/sig/pvectl/repositories/vm.rbs +85 -0
  516. data/sig/pvectl/repositories/volume.rbs +43 -0
  517. data/sig/pvectl/selectors/base.rbs +37 -0
  518. data/sig/pvectl/selectors/container.rbs +19 -0
  519. data/sig/pvectl/selectors/disk.rbs +13 -0
  520. data/sig/pvectl/selectors/vm.rbs +19 -0
  521. data/sig/pvectl/selectors/volume.rbs +13 -0
  522. data/sig/pvectl/services/backup.rbs +27 -0
  523. data/sig/pvectl/services/clone_container.rbs +35 -0
  524. data/sig/pvectl/services/clone_vm.rbs +35 -0
  525. data/sig/pvectl/services/cloudinit.rbs +19 -0
  526. data/sig/pvectl/services/console.rbs +23 -0
  527. data/sig/pvectl/services/container_lifecycle.rbs +26 -0
  528. data/sig/pvectl/services/create_container.rbs +64 -0
  529. data/sig/pvectl/services/create_vm.rbs +72 -0
  530. data/sig/pvectl/services/edit_container.rbs +17 -0
  531. data/sig/pvectl/services/edit_dns.rbs +23 -0
  532. data/sig/pvectl/services/edit_hosts.rbs +13 -0
  533. data/sig/pvectl/services/edit_node.rbs +21 -0
  534. data/sig/pvectl/services/edit_vm.rbs +17 -0
  535. data/sig/pvectl/services/edit_volume.rbs +18 -0
  536. data/sig/pvectl/services/get/resource_service.rbs +23 -0
  537. data/sig/pvectl/services/move_disk.rbs +21 -0
  538. data/sig/pvectl/services/pull_config.rbs +18 -0
  539. data/sig/pvectl/services/push_config.rbs +37 -0
  540. data/sig/pvectl/services/resize_volume.rbs +47 -0
  541. data/sig/pvectl/services/resource_delete.rbs +27 -0
  542. data/sig/pvectl/services/resource_migration.rbs +29 -0
  543. data/sig/pvectl/services/sendkey.rbs +19 -0
  544. data/sig/pvectl/services/service_lifecycle.rbs +17 -0
  545. data/sig/pvectl/services/set_container.rbs +14 -0
  546. data/sig/pvectl/services/set_node.rbs +23 -0
  547. data/sig/pvectl/services/set_vm.rbs +14 -0
  548. data/sig/pvectl/services/set_volume.rbs +12 -0
  549. data/sig/pvectl/services/snapshot.rbs +35 -0
  550. data/sig/pvectl/services/task_listing.rbs +13 -0
  551. data/sig/pvectl/services/unlink_disk.rbs +17 -0
  552. data/sig/pvectl/services/vm_lifecycle.rbs +26 -0
  553. data/sig/pvectl/services/wakeonlan.rbs +17 -0
  554. data/sig/pvectl/utils/resource_resolver.rbs +17 -0
  555. data/sig/pvectl/wizards/create_container.rbs +21 -0
  556. data/sig/pvectl/wizards/create_vm.rbs +21 -0
  557. data/sig/pvectl.rbs +9 -0
  558. metadata +675 -0
@@ -0,0 +1,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pvectl
4
+ module Commands
5
+ # Delete-specific functionality built on IrreversibleCommand.
6
+ #
7
+ # Adds delete-specific behavior:
8
+ # - Confirmation message mentioning disk destruction
9
+ # - --keep-disks and --purge options in service_options
10
+ # - Delegates to Services::ResourceDelete
11
+ #
12
+ # @example Including in a command class
13
+ # class DeleteVm
14
+ # include DeleteCommand
15
+ # RESOURCE_TYPE = :vm
16
+ # SUPPORTED_RESOURCES = %w[vm].freeze
17
+ # end
18
+ #
19
+ module DeleteCommand
20
+ include IrreversibleCommand
21
+
22
+ # Hook called when module is included.
23
+ #
24
+ # @param base [Class] the class including this module
25
+ def self.included(base)
26
+ base.extend(IrreversibleCommand::ClassMethods)
27
+ end
28
+
29
+ private
30
+
31
+ # Returns confirmation message for delete operation.
32
+ #
33
+ # @param resources [Array] resources to delete
34
+ # @return [String] confirmation message
35
+ def confirm_message(resources)
36
+ type_name = resource_type_symbol == :vm ? "VM" : "container"
37
+ type_plural = resource_type_symbol == :vm ? "VMs" : "containers"
38
+
39
+ if resources.size == 1
40
+ r = resources.first
41
+ "You are about to delete #{type_name} #{r.vmid} (#{r.name || 'unnamed'}) on #{r.node}."
42
+ else
43
+ lines = ["You are about to delete #{resources.size} #{type_plural}:"]
44
+ resources.each { |r| lines << " - #{r.vmid} (#{r.name || 'unnamed'}) on #{r.node}" }
45
+ lines.join("\n")
46
+ end
47
+ end
48
+
49
+ # Returns irreversibility warning for delete.
50
+ #
51
+ # @return [String] warning text
52
+ def irreversibility_warning
53
+ type_plural = resource_type_symbol == :vm ? "VMs" : "containers"
54
+ if @options[:"keep-disks"]
55
+ "This action is IRREVERSIBLE. Disks will be preserved."
56
+ else
57
+ "This action is IRREVERSIBLE and will destroy the #{type_plural} and their disks."
58
+ end
59
+ end
60
+
61
+ # Confirms delete operation — always required (uses --yes flag, not --force).
62
+ #
63
+ # @param resources [Array] Resources to delete
64
+ # @return [Boolean] true if operation should proceed
65
+ def confirm_operation(resources)
66
+ return true if @options[:yes]
67
+
68
+ $stdout.puts confirm_message(resources)
69
+ $stdout.puts ""
70
+ $stdout.puts irreversibility_warning
71
+ $stdout.print "Proceed? [y/N]: "
72
+
73
+ response = $stdin.gets&.strip&.downcase
74
+ %w[y yes].include?(response)
75
+ end
76
+
77
+ # Performs the delete service call.
78
+ #
79
+ # @param resources [Array] resources to delete
80
+ # @param connection [Connection] API connection
81
+ # @return [Array<Models::OperationResult>] results
82
+ def perform_service_call(resources, connection)
83
+ vm_repo = Pvectl::Repositories::Vm.new(connection)
84
+ container_repo = Pvectl::Repositories::Container.new(connection)
85
+ task_repo = Pvectl::Repositories::Task.new(connection)
86
+
87
+ service = Pvectl::Services::ResourceDelete.new(
88
+ vm_repository: vm_repo,
89
+ container_repository: container_repo,
90
+ task_repository: task_repo,
91
+ options: service_options
92
+ )
93
+
94
+ service.execute(resource_type_symbol, resources)
95
+ end
96
+
97
+ # Builds presenter for delete results.
98
+ #
99
+ # @return [Presenters::Base] presenter
100
+ def build_presenter
101
+ if resource_type_symbol == :vm
102
+ Pvectl::Presenters::VmOperationResult.new
103
+ else
104
+ Pvectl::Presenters::ContainerOperationResult.new
105
+ end
106
+ end
107
+
108
+ # Builds service options with delete-specific flags.
109
+ #
110
+ # @return [Hash] service options
111
+ def service_options
112
+ opts = super
113
+ opts[:keep_disks] = true if @options[:"keep-disks"]
114
+ opts[:purge] = true if @options[:purge]
115
+ opts
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pvectl
4
+ module Commands
5
+ # Handler for the `pvectl delete container` command.
6
+ #
7
+ # Deletes one or more LXC containers from the cluster.
8
+ # Always requires confirmation (--yes to skip).
9
+ # Running containers must be stopped first or use --force.
10
+ #
11
+ # @example Delete a single container
12
+ # pvectl delete container 200 --yes
13
+ #
14
+ # @example Delete using ct alias
15
+ # pvectl delete ct 200 --yes
16
+ #
17
+ # @example Delete multiple containers
18
+ # pvectl delete container 200 201 202 --yes
19
+ #
20
+ # @example Force delete running container
21
+ # pvectl delete container 200 --force --yes
22
+ #
23
+ class DeleteContainer
24
+ include DeleteCommand
25
+
26
+ RESOURCE_TYPE = :container
27
+ SUPPORTED_RESOURCES = %w[container ct].freeze
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,248 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pvectl
4
+ module Commands
5
+ # Handler for the `pvectl delete snapshot` sub-command.
6
+ #
7
+ # Deletes snapshots from VMs/containers. Snapshot name is the first
8
+ # positional argument, or use --all to delete ALL snapshots.
9
+ # VMIDs are specified via --vmid flag. Without --vmid, operates cluster-wide.
10
+ #
11
+ # @example Delete named snapshot
12
+ # pvectl delete snapshot before-upgrade --vmid 100 --yes
13
+ #
14
+ # @example Delete all snapshots from a VM
15
+ # pvectl delete snapshot --all --vmid 100 --yes
16
+ #
17
+ # @example Delete named snapshot cluster-wide
18
+ # pvectl delete snapshot before-upgrade --yes
19
+ #
20
+ class DeleteSnapshot
21
+ VMID_PATTERN = /\A[1-9]\d{0,8}\z/
22
+
23
+ # Registers as a sub-command under the parent delete command.
24
+ #
25
+ # @param parent [GLI::Command] the parent delete command
26
+ # @return [void]
27
+ def self.register_subcommand(parent)
28
+ parent.desc "Delete snapshots from VMs or containers"
29
+ parent.long_desc <<~HELP
30
+ Delete snapshots from VMs and containers.
31
+
32
+ EXAMPLES
33
+ Delete a specific snapshot from a VM:
34
+ $ pvectl delete snapshot before-upgrade --vmid 100 --yes
35
+
36
+ Delete a snapshot from all VMs that have it:
37
+ $ pvectl delete snapshot before-upgrade --yes
38
+
39
+ Delete ALL snapshots from a specific VM:
40
+ $ pvectl delete snapshot --all --vmid 100 --yes
41
+
42
+ Delete ALL snapshots cluster-wide:
43
+ $ pvectl delete snapshot --all --yes
44
+
45
+ NOTES
46
+ Snapshot deletion is irreversible.
47
+
48
+ --all deletes every snapshot, not just the named one. Use with
49
+ extreme caution, especially without --vmid.
50
+
51
+ SEE ALSO
52
+ pvectl help create snapshot Create snapshots
53
+ pvectl help rollback Rollback to a snapshot
54
+ pvectl help get snapshots List existing snapshots
55
+ HELP
56
+ parent.command :snapshot do |s|
57
+ s.desc "VM/CT ID (repeatable)"
58
+ s.flag [:vmid], arg_name: "VMID", multiple: true
59
+
60
+ s.action do |global_options, options, args|
61
+ exit_code = execute(args, options, global_options)
62
+ exit exit_code if exit_code != 0
63
+ end
64
+ end
65
+ end
66
+
67
+ # Executes the delete snapshot command.
68
+ #
69
+ # @param args [Array<String>] positional args (snapshot name)
70
+ # @param options [Hash] command options
71
+ # @param global_options [Hash] global CLI options
72
+ # @return [Integer] exit code
73
+ def self.execute(args, options, global_options)
74
+ new(args, options, global_options).execute
75
+ end
76
+
77
+ # Initializes a delete snapshot command.
78
+ #
79
+ # @param args [Array<String>] positional args (snapshot name)
80
+ # @param options [Hash] command options
81
+ # @param global_options [Hash] global CLI options
82
+ def initialize(args, options, global_options)
83
+ @args = Array(args)
84
+ @options = options
85
+ @global_options = global_options
86
+ @snapshot_name = @args.first
87
+ @vmids = parse_vmids(options[:vmid])
88
+ @node = options[:node]
89
+ @delete_all = options[:all] || false
90
+ end
91
+
92
+ # Executes the delete snapshot command.
93
+ #
94
+ # @return [Integer] exit code
95
+ def execute
96
+ return usage_error("Snapshot name or --all required") if @snapshot_name.nil? && !@delete_all
97
+ return usage_error("Cannot use --all with snapshot name") if @snapshot_name && @delete_all
98
+ return usage_error("Invalid VMID: #{invalid_vmid}") if invalid_vmid
99
+
100
+ return ExitCodes::SUCCESS unless confirm_operation
101
+
102
+ perform_operation
103
+ end
104
+
105
+ private
106
+
107
+ # Parses --vmid flag values to integer array.
108
+ #
109
+ # @param vmid_values [Array<String>, nil] raw vmid values
110
+ # @return [Array<Integer>] parsed VMIDs
111
+ def parse_vmids(vmid_values)
112
+ return [] if vmid_values.nil? || vmid_values.empty?
113
+
114
+ Array(vmid_values).map(&:to_i)
115
+ end
116
+
117
+ # Finds first invalid VMID in options.
118
+ #
119
+ # @return [String, nil] invalid VMID value or nil
120
+ def invalid_vmid
121
+ return nil if @options[:vmid].nil? || @options[:vmid].empty?
122
+
123
+ Array(@options[:vmid]).find { |v| !VMID_PATTERN.match?(v.to_s) }
124
+ end
125
+
126
+ # Confirms operation with user prompt.
127
+ #
128
+ # @return [Boolean] true if operation should proceed
129
+ def confirm_operation
130
+ return true if @options[:yes]
131
+
132
+ if @delete_all
133
+ if @vmids.empty?
134
+ $stdout.puts "You are about to delete ALL snapshots from ALL VMs/CTs in the cluster."
135
+ else
136
+ $stdout.puts "You are about to delete ALL snapshots from #{@vmids.size} VMs:"
137
+ @vmids.each { |vmid| $stdout.puts " - #{vmid}" }
138
+ end
139
+ else
140
+ if @vmids.empty?
141
+ $stdout.puts "You are about to delete snapshot '#{@snapshot_name}' from ALL VMs/CTs in the cluster."
142
+ elsif @vmids.size == 1
143
+ $stdout.puts "You are about to delete snapshot '#{@snapshot_name}' from VM #{@vmids.first}."
144
+ else
145
+ $stdout.puts "You are about to delete snapshot '#{@snapshot_name}' from #{@vmids.size} VMs:"
146
+ @vmids.each { |vmid| $stdout.puts " - #{vmid}" }
147
+ end
148
+ end
149
+ $stdout.puts ""
150
+ $stdout.print "Proceed? [y/N]: "
151
+
152
+ response = $stdin.gets&.strip&.downcase
153
+ %w[y yes].include?(response)
154
+ end
155
+
156
+ # Performs the snapshot deletion operation.
157
+ #
158
+ # @return [Integer] exit code
159
+ def perform_operation
160
+ load_config
161
+ connection = Pvectl::Connection.new(@config)
162
+
163
+ snapshot_repo = Pvectl::Repositories::Snapshot.new(connection)
164
+ resolver = Pvectl::Utils::ResourceResolver.new(connection)
165
+ task_repo = Pvectl::Repositories::Task.new(connection)
166
+
167
+ service = Pvectl::Services::Snapshot.new(
168
+ snapshot_repo: snapshot_repo,
169
+ resource_resolver: resolver,
170
+ task_repo: task_repo,
171
+ options: service_options
172
+ )
173
+
174
+ results = if @delete_all
175
+ service.delete_all(@vmids, node: @node, force: @options[:force] || false)
176
+ else
177
+ service.delete(@vmids, @snapshot_name, force: @options[:force] || false, node: @node)
178
+ end
179
+
180
+ output_results(results)
181
+ determine_exit_code(results)
182
+ rescue Pvectl::Config::ConfigNotFoundError,
183
+ Pvectl::Config::InvalidConfigError,
184
+ Pvectl::Config::ContextNotFoundError,
185
+ Pvectl::Config::ClusterNotFoundError,
186
+ Pvectl::Config::UserNotFoundError
187
+ raise
188
+ rescue StandardError => e
189
+ $stderr.puts "Error: #{e.message}"
190
+ ExitCodes::GENERAL_ERROR
191
+ end
192
+
193
+ # Loads configuration.
194
+ #
195
+ # @return [void]
196
+ def load_config
197
+ service = Pvectl::Config::Service.new
198
+ service.load(config: @global_options[:config])
199
+ @config = service.current_config
200
+ end
201
+
202
+ # Builds service options.
203
+ #
204
+ # @return [Hash] service options
205
+ def service_options
206
+ opts = {}
207
+ opts[:timeout] = @options[:timeout] if @options[:timeout]
208
+ opts[:async] = true if @options[:async]
209
+ opts[:fail_fast] = true if @options[:"fail-fast"]
210
+ opts
211
+ end
212
+
213
+ # Outputs operation results.
214
+ #
215
+ # @param results [Array<Models::OperationResult>] results
216
+ # @return [void]
217
+ def output_results(results)
218
+ presenter = Pvectl::Presenters::SnapshotOperationResult.new
219
+ format = @global_options[:output] || "table"
220
+ color_flag = @global_options[:color]
221
+
222
+ formatter = Pvectl::Formatters::Registry.for(format)
223
+ output = formatter.format(results, presenter, color: color_flag)
224
+ puts output
225
+ end
226
+
227
+ # Determines exit code.
228
+ #
229
+ # @param results [Array<Models::OperationResult>] results
230
+ # @return [Integer] exit code
231
+ def determine_exit_code(results)
232
+ return ExitCodes::SUCCESS if results.all?(&:successful?)
233
+ return ExitCodes::SUCCESS if results.all?(&:pending?)
234
+
235
+ ExitCodes::GENERAL_ERROR
236
+ end
237
+
238
+ # Outputs usage error.
239
+ #
240
+ # @param message [String] error message
241
+ # @return [Integer] exit code
242
+ def usage_error(message)
243
+ $stderr.puts "Error: #{message}"
244
+ ExitCodes::USAGE_ERROR
245
+ end
246
+ end
247
+ end
248
+ end
@@ -0,0 +1,127 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pvectl
4
+ module Commands
5
+ # Handler for the `pvectl delete vm` command.
6
+ #
7
+ # Deletes one or more virtual machines from the cluster.
8
+ # Always requires confirmation (--yes to skip).
9
+ # Running VMs must be stopped first or use --force.
10
+ #
11
+ # @example Delete a single VM
12
+ # pvectl delete vm 100 --yes
13
+ #
14
+ # @example Delete multiple VMs
15
+ # pvectl delete vm 100 101 102 --yes
16
+ #
17
+ # @example Force delete running VM
18
+ # pvectl delete vm 100 --force --yes
19
+ #
20
+ # @example Keep disks after deletion
21
+ # pvectl delete vm 100 --keep-disks --yes
22
+ #
23
+ class DeleteVm
24
+ include DeleteCommand
25
+
26
+ # Registers the delete command with the CLI.
27
+ #
28
+ # @param cli [GLI::App] the CLI application object
29
+ # @return [void]
30
+ def self.register(cli)
31
+ cli.desc "Delete a resource"
32
+ cli.long_desc <<~HELP
33
+ Delete virtual machines, containers, snapshots, or backups.
34
+
35
+ Destructive operations require confirmation (--yes flag or interactive
36
+ prompt). Use --force to stop running resources before deletion.
37
+
38
+ SUBCOMMANDS
39
+ delete vm ID... Delete virtual machines
40
+ delete container ID... Delete LXC containers
41
+ delete snapshot NAME Delete snapshots (see: pvectl help delete snapshot)
42
+ delete backup VOLID... Delete backup volumes
43
+
44
+ EXAMPLES
45
+ Delete a stopped VM:
46
+ $ pvectl delete vm 100 --yes
47
+
48
+ Force-delete a running VM (stops it first):
49
+ $ pvectl delete vm 100 --force --yes
50
+
51
+ Delete VM but keep its disks:
52
+ $ pvectl delete vm 100 --keep-disks --yes
53
+
54
+ Delete a backup by volume ID:
55
+ $ pvectl delete backup local:backup/vzdump-qemu-100-2026_01_01.vma.zst --yes
56
+
57
+ NOTES
58
+ Deletion is irreversible. Always verify the resource ID before confirming.
59
+
60
+ --force stops a running VM/container before deleting.
61
+ --purge removes the resource from replication and backup jobs.
62
+
63
+ SEE ALSO
64
+ pvectl help get List resources to find IDs
65
+ pvectl help create Create new resources
66
+ HELP
67
+ cli.arg_name "RESOURCE_TYPE [ID...] [NAME]"
68
+ cli.command :delete do |c|
69
+ c.desc "Skip confirmation prompt (REQUIRED for destructive operations)"
70
+ c.switch [:yes, :y], negatable: false
71
+
72
+ c.desc "Force stop running VM/container before deletion"
73
+ c.switch [:force, :f], negatable: false
74
+
75
+ c.desc "Keep disks (do not destroy)"
76
+ c.switch [:"keep-disks"], negatable: false
77
+
78
+ c.desc "Remove from HA, replication, and backups"
79
+ c.switch [:purge], negatable: false
80
+
81
+ c.desc "Select all resources of this type"
82
+ c.switch [:all, :A], negatable: false
83
+
84
+ c.desc "Filter by node name"
85
+ c.flag [:node, :n], arg_name: "NODE"
86
+
87
+ c.desc "Filter by selector (e.g., status=running,tags=prod)"
88
+ c.flag [:l, :selector], arg_name: "SELECTOR", multiple: true
89
+
90
+ c.desc "Timeout in seconds for sync operations"
91
+ c.flag [:timeout], type: Integer, arg_name: "SECONDS"
92
+
93
+ c.desc "Force async mode (return task ID immediately)"
94
+ c.switch [:async], negatable: false
95
+
96
+ c.desc "Stop on first error (default: continue and report all)"
97
+ c.switch [:"fail-fast"], negatable: false
98
+
99
+ # Sub-commands
100
+ DeleteSnapshot.register_subcommand(c)
101
+
102
+ c.action do |global_options, options, args|
103
+ resource_type = args.shift
104
+
105
+ exit_code = case resource_type
106
+ when "vm"
107
+ Commands::DeleteVm.execute(resource_type, args, options, global_options)
108
+ when "container", "ct"
109
+ Commands::DeleteContainer.execute(resource_type, args, options, global_options)
110
+ when "backup"
111
+ Commands::DeleteBackup.execute(resource_type, args, options, global_options)
112
+ else
113
+ $stderr.puts "Error: Unknown resource type: #{resource_type}"
114
+ $stderr.puts "Valid types: vm, container, backup (or use: delete snapshot)"
115
+ ExitCodes::USAGE_ERROR
116
+ end
117
+
118
+ exit exit_code if exit_code != 0
119
+ end
120
+ end
121
+ end
122
+
123
+ RESOURCE_TYPE = :vm
124
+ SUPPORTED_RESOURCES = %w[vm].freeze
125
+ end
126
+ end
127
+ end