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,162 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pvectl
4
+ module Commands
5
+ module Get
6
+ module Handlers
7
+ # Handler for listing Proxmox cluster nodes.
8
+ #
9
+ # Implements ResourceHandler interface for the "nodes" resource type.
10
+ # Uses Repositories::Node for data access and Presenters::Node for formatting.
11
+ #
12
+ # Supports filtering by status and sorting by various fields.
13
+ #
14
+ # @example Using via ResourceRegistry
15
+ # handler = ResourceRegistry.for("nodes")
16
+ # nodes = handler.list(filter: { status: "online" }, sort: "memory")
17
+ #
18
+ # @see Pvectl::Commands::Get::ResourceHandler Handler interface
19
+ # @see Pvectl::Repositories::Node Node repository
20
+ # @see Pvectl::Presenters::Node Node presenter
21
+ #
22
+ class Nodes
23
+ include ResourceHandler
24
+
25
+ # Sort field mappings.
26
+ # Negative values for descending sort (higher values first).
27
+ SORT_FIELDS = {
28
+ "name" => ->(n) { n.name },
29
+ "status" => ->(n) { n.status },
30
+ "cpu" => ->(n) { -(n.cpu || 0) },
31
+ "memory" => ->(n) { -(n.mem || 0) },
32
+ "disk" => ->(n) { -(n.disk || 0) },
33
+ "guests" => ->(n) { -n.guests_total },
34
+ "uptime" => ->(n) { -(n.uptime || 0) }
35
+ }.freeze
36
+
37
+ # Creates handler with optional repository for dependency injection.
38
+ #
39
+ # @param repository [Repositories::Node, nil] repository (default: create new)
40
+ def initialize(repository: nil)
41
+ @repository = repository
42
+ end
43
+
44
+ # Lists nodes with optional filtering and sorting.
45
+ #
46
+ # @param node [String, nil] not used for nodes (included for interface)
47
+ # @param name [String, nil] filter by exact node name
48
+ # @param args [Array<String>] unused, for interface compatibility
49
+ # @param storage [String, nil] unused, for interface compatibility
50
+ # @param filter [Hash, nil] filter criteria (e.g., { status: "online" })
51
+ # @param sort [String, nil] sort field (name, status, cpu, memory, disk, guests, uptime)
52
+ # @param include_details [Boolean] fetch extended details (version, load), default true
53
+ # @return [Array<Models::Node>] collection of Node models
54
+ def list(node: nil, name: nil, args: [], storage: nil, filter: nil, sort: nil, include_details: true, **_options)
55
+ nodes = repository.list(include_details: include_details)
56
+
57
+ # Filter by name
58
+ nodes = nodes.select { |n| n.name == name } if name
59
+
60
+ # Apply filters
61
+ nodes = apply_filters(nodes, filter) if filter
62
+
63
+ # Apply sorting
64
+ nodes = apply_sort(nodes, sort) if sort
65
+
66
+ nodes
67
+ end
68
+
69
+ # Returns presenter for nodes.
70
+ #
71
+ # @return [Presenters::Node] Node presenter instance
72
+ def presenter
73
+ Pvectl::Presenters::Node.new
74
+ end
75
+
76
+ # Describes a single node with comprehensive details.
77
+ #
78
+ # @param name [String] node name
79
+ # @param node [String, nil] unused, for API consistency
80
+ # @return [Models::Node] Node model with full details
81
+ # @raise [ArgumentError] if node name is invalid
82
+ # @raise [Pvectl::ResourceNotFoundError] if node not found
83
+ def describe(name:, node: nil, args: [], vmid: nil)
84
+ raise ArgumentError, "Invalid node name" unless valid_node_name?(name)
85
+
86
+ node = repository.describe(name)
87
+ raise Pvectl::ResourceNotFoundError, "Node not found: #{name}" if node.nil?
88
+
89
+ node
90
+ end
91
+
92
+ private
93
+
94
+ # Returns repository, creating it if necessary.
95
+ #
96
+ # @return [Repositories::Node] Node repository
97
+ def repository
98
+ @repository ||= build_repository
99
+ end
100
+
101
+ # Builds repository with connection from config.
102
+ #
103
+ # @return [Repositories::Node] configured Node repository
104
+ def build_repository
105
+ config_service = Pvectl::Config::Service.new
106
+ config_service.load
107
+ connection = Pvectl::Connection.new(config_service.current_config)
108
+ Pvectl::Repositories::Node.new(connection)
109
+ end
110
+
111
+ # Applies filter criteria to nodes collection.
112
+ #
113
+ # @param nodes [Array<Models::Node>] nodes to filter
114
+ # @param filter [Hash] filter criteria (e.g., { status: "online" })
115
+ # @return [Array<Models::Node>] filtered nodes
116
+ def apply_filters(nodes, filter)
117
+ filter.each do |key, value|
118
+ case key.to_s
119
+ when "status"
120
+ nodes = nodes.select { |n| n.status == value }
121
+ end
122
+ end
123
+ nodes
124
+ end
125
+
126
+ # Applies sorting to nodes collection.
127
+ #
128
+ # @param nodes [Array<Models::Node>] nodes to sort
129
+ # @param sort_field [String] field to sort by
130
+ # @return [Array<Models::Node>] sorted nodes
131
+ def apply_sort(nodes, sort_field)
132
+ sort_proc = SORT_FIELDS[sort_field.to_s]
133
+ return nodes unless sort_proc
134
+
135
+ nodes.sort_by(&sort_proc)
136
+ end
137
+
138
+ # Validates node name format.
139
+ #
140
+ # Proxmox node names are alphanumeric, can contain hyphens,
141
+ # must start with alphanumeric character, max 63 characters.
142
+ #
143
+ # @param name [String, nil] node name to validate
144
+ # @return [Boolean] true if valid
145
+ def valid_node_name?(name)
146
+ return false if name.nil? || name.empty?
147
+
148
+ # Proxmox node names: alphanumeric, can contain hyphens, max 63 chars
149
+ name.match?(/\A[a-zA-Z0-9][-a-zA-Z0-9]{0,62}\z/)
150
+ end
151
+ end
152
+ end
153
+ end
154
+ end
155
+ end
156
+
157
+ # Register handler with ResourceRegistry
158
+ Pvectl::Commands::Get::ResourceRegistry.register(
159
+ "nodes",
160
+ Pvectl::Commands::Get::Handlers::Nodes,
161
+ aliases: ["node"]
162
+ )
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pvectl
4
+ module Commands
5
+ module Get
6
+ module Handlers
7
+ # Handler for listing systemd services on Proxmox nodes.
8
+ #
9
+ # Implements ResourceHandler interface for the "services" resource type.
10
+ # Uses Repositories::Service for data access and Presenters::Service
11
+ # for formatting.
12
+ #
13
+ # When no node filter is supplied, lists services across all online
14
+ # nodes. The --node flag restricts the listing to a single node.
15
+ #
16
+ # @example Using via ResourceRegistry
17
+ # handler = ResourceRegistry.for("services")
18
+ # services = handler.list(node: "pve1")
19
+ #
20
+ # @see Pvectl::Repositories::Service Service repository
21
+ # @see Pvectl::Presenters::Service Service presenter
22
+ #
23
+ class Services
24
+ include ResourceHandler
25
+
26
+ # Creates handler with optional repository for dependency injection.
27
+ #
28
+ # @param repository [Repositories::Service, nil] repository (default: build new)
29
+ def initialize(repository: nil)
30
+ @repository = repository
31
+ end
32
+
33
+ # Lists services, optionally filtered by node and service name.
34
+ #
35
+ # @param node [String, nil] filter by node name
36
+ # @param name [String, nil] filter by service identifier (exact match)
37
+ # @param _options [Hash] additional CLI options (unused)
38
+ # @return [Array<Models::Service>] collection of Service models
39
+ def list(node: nil, name: nil, **_options)
40
+ services = repository.list(node: node)
41
+ services = services.select { |s| s.service == name } if name
42
+ services
43
+ end
44
+
45
+ # Returns presenter for services.
46
+ #
47
+ # @return [Presenters::Service] Service presenter instance
48
+ def presenter
49
+ Pvectl::Presenters::Service.new
50
+ end
51
+
52
+ private
53
+
54
+ # Returns repository, creating it lazily if not injected.
55
+ #
56
+ # @return [Repositories::Service] Service repository
57
+ def repository
58
+ @repository ||= build_repository
59
+ end
60
+
61
+ # Builds repository with connection from config.
62
+ #
63
+ # @return [Repositories::Service] configured Service repository
64
+ def build_repository
65
+ config_service = Pvectl::Config::Service.new
66
+ config_service.load
67
+ connection = Pvectl::Connection.new(config_service.current_config)
68
+ Pvectl::Repositories::Service.new(connection)
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
75
+
76
+ # Register handler with ResourceRegistry
77
+ Pvectl::Commands::Get::ResourceRegistry.register(
78
+ "services",
79
+ Pvectl::Commands::Get::Handlers::Services,
80
+ aliases: ["svc"]
81
+ )
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pvectl
4
+ module Commands
5
+ module Get
6
+ module Handlers
7
+ # Handler for listing and describing snapshots.
8
+ #
9
+ # Uses --vmid flag (repeatable) for VM/CT filtering and --node for node filtering.
10
+ # Without --vmid, operates cluster-wide.
11
+ #
12
+ # @example List snapshots for specific VMs
13
+ # handler.list(args: [], vmid: ["100", "101"])
14
+ #
15
+ # @example List all snapshots cluster-wide
16
+ # handler.list(args: [])
17
+ #
18
+ class Snapshots
19
+ include ResourceHandler
20
+
21
+ def initialize(service: nil)
22
+ @service = service
23
+ end
24
+
25
+ # Lists snapshots, optionally filtered by VMIDs and/or node.
26
+ #
27
+ # @param vmid [Array<String>, nil] VM/CT IDs from --vmid flag
28
+ # @param node [String, nil] node name from --node flag
29
+ # @param args [Array<String>] unused positional args
30
+ # @return [Array<Models::Snapshot>] collection of snapshot models
31
+ def list(node: nil, name: nil, args: [], storage: nil, vmid: nil, **_options)
32
+ parsed_vmids = parse_vmids(vmid)
33
+ service.list(parsed_vmids, node: node)
34
+ end
35
+
36
+ # Describes a snapshot by name.
37
+ #
38
+ # @param name [String] snapshot name to find
39
+ # @param vmid [Array<String>, nil] VM/CT IDs from --vmid flag
40
+ # @param node [String, nil] node name from --node flag
41
+ # @param args [Array<String>] unused positional args
42
+ # @return [Models::SnapshotDescription] snapshot description
43
+ def describe(name:, node: nil, args: [], vmid: nil, **_options)
44
+ parsed_vmids = parse_vmids(vmid)
45
+ service.describe(parsed_vmids, name, node: node)
46
+ end
47
+
48
+ # Returns presenter for snapshots.
49
+ #
50
+ # @return [Presenters::Snapshot] snapshot presenter instance
51
+ def presenter
52
+ Pvectl::Presenters::Snapshot.new
53
+ end
54
+
55
+ private
56
+
57
+ # Parses --vmid flag values to integer array.
58
+ #
59
+ # @param vmid [Array<String>, String, nil] raw vmid values
60
+ # @return [Array<Integer>] parsed VMIDs (empty array if nil)
61
+ def parse_vmids(vmid)
62
+ return [] if vmid.nil?
63
+
64
+ Array(vmid).map(&:to_i)
65
+ end
66
+
67
+ def service
68
+ @service ||= build_service
69
+ end
70
+
71
+ def build_service
72
+ config_service = Pvectl::Config::Service.new
73
+ config_service.load
74
+ connection = Pvectl::Connection.new(config_service.current_config)
75
+
76
+ snapshot_repo = Pvectl::Repositories::Snapshot.new(connection)
77
+ resolver = Pvectl::Utils::ResourceResolver.new(connection)
78
+ task_repo = Pvectl::Repositories::Task.new(connection)
79
+
80
+ Pvectl::Services::Snapshot.new(
81
+ snapshot_repo: snapshot_repo,
82
+ resource_resolver: resolver,
83
+ task_repo: task_repo
84
+ )
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
91
+
92
+ # Register handler with ResourceRegistry
93
+ Pvectl::Commands::Get::ResourceRegistry.register(
94
+ "snapshots",
95
+ Pvectl::Commands::Get::Handlers::Snapshots,
96
+ aliases: ["snapshot", "snap"]
97
+ )
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pvectl
4
+ module Commands
5
+ module Get
6
+ module Handlers
7
+ # Handler for listing Proxmox cluster storage pools.
8
+ #
9
+ # Implements ResourceHandler interface for the "storages" resource type
10
+ # (with "storage" and "stor" as aliases).
11
+ # Uses Repositories::Storage for data access and Presenters::Storage for formatting.
12
+ #
13
+ # @example Using via ResourceRegistry
14
+ # handler = ResourceRegistry.for("storages")
15
+ # storage_pools = handler.list(node: "pve1")
16
+ #
17
+ # @see Pvectl::Commands::Get::ResourceHandler Handler interface
18
+ # @see Pvectl::Repositories::Storage Storage repository
19
+ # @see Pvectl::Presenters::Storage Storage presenter
20
+ #
21
+ class Storage
22
+ include ResourceHandler
23
+
24
+ # Creates handler with optional repository for dependency injection.
25
+ #
26
+ # @param repository [Repositories::Storage, nil] repository (default: create new)
27
+ def initialize(repository: nil)
28
+ @repository = repository
29
+ end
30
+
31
+ # Lists storage pools with optional filtering.
32
+ #
33
+ # @param node [String, nil] filter by node name
34
+ # @param name [String, nil] filter by storage name
35
+ # @param args [Array<String>] unused, for interface compatibility
36
+ # @param storage [String, nil] unused, for interface compatibility (storage is filtered via name)
37
+ # @return [Array<Models::Storage>] collection of Storage models
38
+ def list(node: nil, name: nil, args: [], storage: nil, **_options)
39
+ storage_pools = repository.list(node: node)
40
+ storage_pools = storage_pools.select { |s| s.name == name } if name
41
+ storage_pools
42
+ end
43
+
44
+ # Returns presenter for storage pools.
45
+ #
46
+ # @return [Presenters::Storage] Storage presenter instance
47
+ def presenter
48
+ Pvectl::Presenters::Storage.new
49
+ end
50
+
51
+ # Describes a single storage pool by name.
52
+ #
53
+ # For local storage (exists on multiple nodes):
54
+ # - Without node: returns array of instances (which nodes have it)
55
+ # - With node: returns full describe for that specific node
56
+ #
57
+ # For shared storage: returns full describe (single instance).
58
+ #
59
+ # @param name [String] storage name
60
+ # @param node [String, nil] filter by node name (required for local storage)
61
+ # @return [Models::Storage, Array<Models::Storage>] Storage model or array of instances
62
+ # @raise [ArgumentError] if storage name is invalid
63
+ # @raise [Pvectl::ResourceNotFoundError] if storage not found
64
+ def describe(name:, node: nil, args: [], vmid: nil)
65
+ raise ArgumentError, "Invalid storage name" if name.nil? || name.empty?
66
+
67
+ # Check if storage exists on multiple nodes (local storage)
68
+ instances = repository.list_instances(name)
69
+ raise Pvectl::ResourceNotFoundError, "Storage not found: #{name}" if instances.empty?
70
+
71
+ if instances.size > 1 && node.nil?
72
+ # Return list of instances instead of single describe
73
+ return instances
74
+ end
75
+
76
+ # Single instance or node specified - full describe
77
+ storage = repository.describe(name, node: node)
78
+ unless storage
79
+ if node
80
+ raise Pvectl::ResourceNotFoundError, "Storage '#{name}' not found on node '#{node}'"
81
+ else
82
+ raise Pvectl::ResourceNotFoundError, "Storage not found: #{name}"
83
+ end
84
+ end
85
+
86
+ storage
87
+ end
88
+
89
+ private
90
+
91
+ # Returns repository, creating it if necessary.
92
+ #
93
+ # @return [Repositories::Storage] Storage repository
94
+ def repository
95
+ @repository ||= build_repository
96
+ end
97
+
98
+ # Builds repository with connection from config.
99
+ #
100
+ # @return [Repositories::Storage] configured Storage repository
101
+ def build_repository
102
+ config_service = Pvectl::Config::Service.new
103
+ config_service.load
104
+ connection = Pvectl::Connection.new(config_service.current_config)
105
+ Pvectl::Repositories::Storage.new(connection)
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
112
+
113
+ # Register handler with ResourceRegistry
114
+ Pvectl::Commands::Get::ResourceRegistry.register(
115
+ "storages",
116
+ Pvectl::Commands::Get::Handlers::Storage,
117
+ aliases: ["storage", "stor"]
118
+ )
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pvectl
4
+ module Commands
5
+ module Get
6
+ module Handlers
7
+ # Handler for `pvectl get subscription`.
8
+ #
9
+ # Aggregates subscription records across cluster nodes via
10
+ # Repositories::Subscription. Supports filtering to a single node
11
+ # with `--node`.
12
+ #
13
+ # @see Pvectl::Repositories::Subscription
14
+ # @see Pvectl::Presenters::Subscription
15
+ #
16
+ class Subscription
17
+ include ResourceHandler
18
+
19
+ # @param repository [Repositories::Subscription, nil]
20
+ def initialize(repository: nil)
21
+ @repository = repository
22
+ end
23
+
24
+ # @param node [String, nil] limit to a single node
25
+ # @return [Array<Models::Subscription>]
26
+ def list(node: nil, name: nil, args: [], storage: nil, **_options)
27
+ repository.list(node: node)
28
+ end
29
+
30
+ # @return [Presenters::Subscription]
31
+ def presenter
32
+ Pvectl::Presenters::Subscription.new
33
+ end
34
+
35
+ # @param name [String] node name to describe
36
+ # @return [Models::Subscription]
37
+ # @raise [Pvectl::ResourceNotFoundError] when the record cannot be fetched
38
+ def describe(name:, node: nil, args: [], vmid: nil)
39
+ raise ArgumentError, "Invalid node name" if name.nil? || name.empty?
40
+
41
+ record = repository.get(name)
42
+ raise Pvectl::ResourceNotFoundError, "Subscription not found for node: #{name}" if record.nil?
43
+
44
+ record
45
+ end
46
+
47
+ private
48
+
49
+ def repository
50
+ @repository ||= build_repository
51
+ end
52
+
53
+ def build_repository
54
+ config_service = Pvectl::Config::Service.new
55
+ config_service.load
56
+ connection = Pvectl::Connection.new(config_service.current_config)
57
+ Pvectl::Repositories::Subscription.new(connection)
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ Pvectl::Commands::Get::ResourceRegistry.register(
66
+ "subscription",
67
+ Pvectl::Commands::Get::Handlers::Subscription,
68
+ aliases: ["subscriptions", "sub"]
69
+ )
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pvectl
4
+ module Commands
5
+ module Get
6
+ module Handlers
7
+ # Handler for listing Proxmox tasks (async operations).
8
+ #
9
+ # Implements ResourceHandler interface for the "tasks" resource type.
10
+ # Delegates to Services::TaskListing for multi-node task listing.
11
+ #
12
+ # @example Using via ResourceRegistry
13
+ # handler = ResourceRegistry.for("tasks")
14
+ # tasks = handler.list(node: "pve1", limit: 20)
15
+ # presenter = handler.presenter
16
+ #
17
+ # @see Pvectl::Services::TaskListing Shared task listing service
18
+ # @see Pvectl::Presenters::TaskEntry Task entry presenter
19
+ #
20
+ class Tasks
21
+ include ResourceHandler
22
+
23
+ # Creates handler with optional service for dependency injection.
24
+ #
25
+ # @param service [Services::TaskListing, nil] task listing service
26
+ def initialize(service: nil)
27
+ @service = service
28
+ end
29
+
30
+ # Lists tasks with optional filtering.
31
+ #
32
+ # @param node [String, nil] filter by node name (nil = all nodes)
33
+ # @param name [String, nil] unused, for interface compatibility
34
+ # @param limit [Integer] max entries (default 50)
35
+ # @param since [String, nil] start time filter
36
+ # @param until_time [String, nil] end time filter
37
+ # @param type_filter [String, nil] task type filter
38
+ # @param status_filter [String, nil] status filter
39
+ # @return [Array<Models::TaskEntry>] task entries
40
+ def list(node: nil, name: nil, limit: 50, since: nil, until_time: nil,
41
+ type_filter: nil, status_filter: nil, **_options)
42
+ service.list(
43
+ node: node, vmid: nil, limit: limit, since: since,
44
+ until_time: until_time, type_filter: type_filter,
45
+ status_filter: status_filter
46
+ )
47
+ end
48
+
49
+ # Returns presenter for task entries.
50
+ #
51
+ # @return [Presenters::TaskEntry] task entry presenter instance
52
+ def presenter
53
+ Pvectl::Presenters::TaskEntry.new
54
+ end
55
+
56
+ private
57
+
58
+ # Returns service, creating it if necessary.
59
+ #
60
+ # @return [Services::TaskListing] task listing service
61
+ def service
62
+ @service ||= build_service
63
+ end
64
+
65
+ # Builds service with repositories from config.
66
+ #
67
+ # @return [Services::TaskListing] configured service
68
+ def build_service
69
+ config_service = Pvectl::Config::Service.new
70
+ config_service.load
71
+ connection = Pvectl::Connection.new(config_service.current_config)
72
+
73
+ Pvectl::Services::TaskListing.new(
74
+ task_list_repository: Pvectl::Repositories::TaskList.new(connection),
75
+ node_repository: Pvectl::Repositories::Node.new(connection)
76
+ )
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+
84
+ # Register handler with ResourceRegistry
85
+ Pvectl::Commands::Get::ResourceRegistry.register(
86
+ "tasks",
87
+ Pvectl::Commands::Get::Handlers::Tasks,
88
+ aliases: ["task"]
89
+ )