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,251 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pvectl
4
+ module Commands
5
+ module Describe
6
+ # Dispatcher for the `pvectl describe <resource_type> <name>` command.
7
+ #
8
+ # Uses EXISTING Get infrastructure:
9
+ # - Commands::Get::ResourceRegistry for handler lookup
10
+ # - Services::Get::ResourceService for orchestration
11
+ # - Handlers call describe() instead of list()
12
+ #
13
+ # @example Basic usage
14
+ # Commands::Describe::Command.execute("node", "pve1", options, global_options)
15
+ #
16
+ class Command
17
+ # Registers the describe command with the CLI.
18
+ #
19
+ # @param cli [GLI::App] the CLI application object
20
+ # @return [void]
21
+ def self.register(cli)
22
+ cli.desc "Show detailed information about a resource"
23
+ cli.long_desc <<~HELP
24
+ Show detailed information about a specific resource. Displays all
25
+ configuration details, runtime status, and related resources in
26
+ structured, labeled sections.
27
+
28
+ Unlike 'get' which lists many resources in a table, 'describe' shows
29
+ everything known about a single resource in a readable format.
30
+ Unknown or future Proxmox config keys appear in an "Additional
31
+ Configuration" catch-all section, so new API fields are never hidden.
32
+
33
+ RESOURCE TYPES
34
+ node NAME Full node diagnostics (CPU, memory, storage, services)
35
+ vm VMID Comprehensive VM configuration (see VM SECTIONS below)
36
+ container VMID Comprehensive container configuration (see CT SECTIONS below)
37
+ storage NAME Storage pool info, content types, usage
38
+ snapshot NAME Snapshot metadata and snapshot tree (use --vmid)
39
+ volume TYPE ID DISK Virtual disk details (e.g., describe volume vm 100 scsi0)
40
+
41
+ VM SECTIONS (matches PVE web UI tabs)
42
+ Summary HA state, CPU/memory usage, bootdisk size, uptime,
43
+ QEMU version, machine type, network/disk I/O
44
+ Block Device Statistics
45
+ Per-disk I/O counters (read/written bytes, IOPS)
46
+ for running VMs
47
+ Hardware Memory (with balloon details: actual, max, free
48
+ and total inside guest when ballooning active),
49
+ balloon, processors, BIOS, machine, display,
50
+ SCSI controller, EFI/TPM, disks, network, USB/PCI,
51
+ serial ports, audio
52
+ Cloud-Init Type, user, DNS, SSH keys, IP config
53
+ Options Start at boot, startup order, OS type, boot order,
54
+ tablet, hotplug, ACPI, KVM, freeze, localtime,
55
+ NUMA, QEMU guest agent, protection, firewall,
56
+ hookscript
57
+ Firewall Enable, input/output policies, aliases, IP sets
58
+ Firewall Rules Per-rule table (ENABLED, TYPE, ACTION, PROTO,
59
+ SOURCE, DEST, COMMENT)
60
+ Task History Recent operations (type, status, date, duration, user)
61
+ Snapshots Name, date, VM state, description
62
+ Pending Configuration changes awaiting reboot
63
+ Additional Catch-all for unrecognized config keys
64
+
65
+ CT SECTIONS (matches PVE web UI tabs)
66
+ Summary CPU/memory/swap/rootfs usage, uptime, PID, network I/O
67
+ Resources Memory, swap, cores, root filesystem, mountpoints
68
+ Network Interfaces with bridge, IP, MAC
69
+ DNS Nameserver, search domain
70
+ Options Start at boot, startup order, OS type, architecture,
71
+ unprivileged, features, console mode, TTY, protection,
72
+ hookscript
73
+ Firewall Enable, input/output policies, aliases, IP sets
74
+ Firewall Rules Per-rule table (ENABLED, TYPE, ACTION, PROTO,
75
+ SOURCE, DEST, COMMENT)
76
+ Task History Recent operations (type, status, date, duration, user)
77
+ Snapshots Name, date, description
78
+ High Avail. HA state and group
79
+ Additional Catch-all for unrecognized config keys
80
+
81
+ EXAMPLES
82
+ Full node diagnostics:
83
+ $ pvectl describe node pve1
84
+
85
+ VM details — all configuration sections:
86
+ $ pvectl describe vm 100
87
+
88
+ Container details — all configuration sections:
89
+ $ pvectl describe container 200
90
+
91
+ Storage pool information (node-specific):
92
+ $ pvectl describe storage local-lvm --node pve1
93
+
94
+ Snapshot metadata for a specific VM:
95
+ $ pvectl describe snapshot before-upgrade --vmid 100
96
+
97
+ Snapshot search across multiple VMs:
98
+ $ pvectl describe snapshot before-upgrade --vmid 100 --vmid 101
99
+
100
+ Snapshot search cluster-wide (all VMs and containers):
101
+ $ pvectl describe snapshot before-upgrade
102
+
103
+ Virtual disk details:
104
+ $ pvectl describe volume vm 100 scsi0
105
+
106
+ Container rootfs:
107
+ $ pvectl describe volume ct 200 rootfs
108
+
109
+ NOTES
110
+ For local storage, --node is required because local storage exists
111
+ independently on each node.
112
+
113
+ Snapshot describe shows a visual tree of all snapshots for the
114
+ matching VMs, highlighting the described snapshot.
115
+
116
+ VM and container describe output includes ALL configuration from
117
+ the Proxmox API. Any fields not recognized by the presenter are
118
+ grouped in the "Additional Configuration" section at the end.
119
+
120
+ SEE ALSO
121
+ pvectl help get List resources in table format
122
+ pvectl help get volume List virtual disks attached to VMs/containers
123
+ pvectl help logs Show task history and logs
124
+ HELP
125
+ cli.arg_name "RESOURCE_TYPE NAME"
126
+ cli.command :describe do |c|
127
+ c.desc "Filter by node name (required for local storage)"
128
+ c.flag [:node], arg_name: "NODE"
129
+
130
+ c.desc "Filter by VM/CT ID (repeatable)"
131
+ c.flag [:vmid], arg_name: "VMID", multiple: true
132
+
133
+ c.action do |global_options, options, args|
134
+ resource_type = args[0]
135
+ resource_name = args[1]
136
+ extra_args = args[2..] || []
137
+ exit_code = execute(resource_type, resource_name, options, global_options, extra_args: extra_args)
138
+ exit exit_code if exit_code != 0
139
+ end
140
+ end
141
+ end
142
+
143
+ # Executes the describe command.
144
+ #
145
+ # @param resource_type [String, nil] type of resource (e.g., "node")
146
+ # @param resource_name [String, nil] name of resource to describe
147
+ # @param options [Hash] command-specific options
148
+ # @param global_options [Hash] global CLI options
149
+ # @return [Integer] exit code
150
+ def self.execute(resource_type, resource_name, options, global_options, extra_args: [])
151
+ new(resource_type, resource_name, options, global_options, extra_args: extra_args).execute
152
+ end
153
+
154
+ # Creates a new Describe command instance.
155
+ #
156
+ # @param resource_type [String, nil] type of resource
157
+ # @param resource_name [String, nil] name of resource to describe
158
+ # @param options [Hash] command options
159
+ # @param global_options [Hash] global CLI options
160
+ # @param registry [Class] registry class for dependency injection
161
+ def initialize(resource_type, resource_name, options, global_options,
162
+ extra_args: [], registry: Get::ResourceRegistry)
163
+ @resource_type = resource_type
164
+ @resource_name = resource_name
165
+ @options = options
166
+ @global_options = global_options
167
+ @extra_args = extra_args
168
+ @registry = registry
169
+ end
170
+
171
+ # Executes the describe operation.
172
+ #
173
+ # @return [Integer] exit code
174
+ def execute
175
+ return missing_resource_type_error if @resource_type.nil?
176
+ return missing_resource_name_error if @resource_name.nil?
177
+
178
+ handler = @registry.for(@resource_type)
179
+ return unknown_resource_error unless handler
180
+
181
+ run_describe(handler)
182
+ ExitCodes::SUCCESS
183
+ rescue Pvectl::ResourceNotFoundError => e
184
+ $stderr.puts "Error: #{e.message}"
185
+ ExitCodes::NOT_FOUND
186
+ rescue Timeout::Error => e
187
+ $stderr.puts "Error: #{e.message}"
188
+ ExitCodes::CONNECTION_ERROR
189
+ rescue Errno::ECONNREFUSED => e
190
+ $stderr.puts "Error: #{e.message}"
191
+ ExitCodes::CONNECTION_ERROR
192
+ rescue SocketError => e
193
+ $stderr.puts "Error: #{e.message}"
194
+ ExitCodes::CONNECTION_ERROR
195
+ end
196
+
197
+ private
198
+
199
+ # Outputs error for missing resource type argument.
200
+ #
201
+ # @return [Integer] USAGE_ERROR exit code
202
+ def missing_resource_type_error
203
+ $stderr.puts "Error: resource type is required"
204
+ $stderr.puts "Usage: pvectl describe RESOURCE_TYPE NAME"
205
+ ExitCodes::USAGE_ERROR
206
+ end
207
+
208
+ # Outputs error for missing resource name argument.
209
+ #
210
+ # @return [Integer] USAGE_ERROR exit code
211
+ def missing_resource_name_error
212
+ $stderr.puts "Error: resource name is required"
213
+ $stderr.puts "Usage: pvectl describe #{@resource_type} NAME"
214
+ ExitCodes::USAGE_ERROR
215
+ end
216
+
217
+ # Outputs error for unknown resource type.
218
+ #
219
+ # @return [Integer] USAGE_ERROR exit code
220
+ def unknown_resource_error
221
+ $stderr.puts "Unknown resource type: #{@resource_type}"
222
+ ExitCodes::USAGE_ERROR
223
+ end
224
+
225
+ # Runs the describe operation with the given handler.
226
+ #
227
+ # @param handler [ResourceHandler] the resource handler
228
+ # @return [void]
229
+ def run_describe(handler)
230
+ service = Services::Get::ResourceService.new(
231
+ handler: handler,
232
+ format: @global_options[:output] || "table",
233
+ color_enabled: determine_color_enabled
234
+ )
235
+ output = service.describe(name: @resource_name, node: @options[:node], args: @extra_args, vmid: @options[:vmid])
236
+ puts output
237
+ end
238
+
239
+ # Determines if color output should be enabled.
240
+ #
241
+ # @return [Boolean] true if color should be enabled
242
+ def determine_color_enabled
243
+ explicit = @global_options[:color]
244
+ return explicit unless explicit.nil?
245
+
246
+ $stdout.tty?
247
+ end
248
+ end
249
+ end
250
+ end
251
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pvectl
4
+ module Commands
5
+ # Handler for the `pvectl edit container` command.
6
+ #
7
+ # Includes EditResourceCommand for shared workflow and overrides
8
+ # template methods with container-specific behavior.
9
+ #
10
+ # @example Basic usage
11
+ # pvectl edit container 200
12
+ #
13
+ # @example With custom editor
14
+ # pvectl edit container 200 --editor nano
15
+ #
16
+ # @example Dry-run mode
17
+ # pvectl edit container 200 --dry-run
18
+ #
19
+ class EditContainer
20
+ include EditResourceCommand
21
+
22
+ private
23
+
24
+ # @return [String] human label for container resources
25
+ def resource_label
26
+ "container"
27
+ end
28
+
29
+ # @return [String] human label for container IDs
30
+ def resource_id_label
31
+ "CTID"
32
+ end
33
+
34
+ # Builds execution parameters from a container ID.
35
+ #
36
+ # @param resource_id [String] CTID (converted to Integer)
37
+ # @return [Hash] parameters for the edit service
38
+ def execute_params(resource_id)
39
+ { ctid: resource_id.to_i }
40
+ end
41
+
42
+ # Builds the container edit service.
43
+ #
44
+ # @param connection [Connection] API connection
45
+ # @return [Services::EditContainer] container edit service
46
+ def build_edit_service(connection)
47
+ ct_repo = Pvectl::Repositories::Container.new(connection)
48
+ Pvectl::Services::EditContainer.new(
49
+ container_repository: ct_repo,
50
+ editor_session: build_editor_session,
51
+ options: service_options
52
+ )
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,149 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pvectl
4
+ module Commands
5
+ # Handler for the `pvectl edit dns` command.
6
+ #
7
+ # Opens the DNS resolver configuration for a node in a YAML editor.
8
+ # On save, applies the changes via PUT /nodes/{node}/dns.
9
+ #
10
+ # The node identifier may be supplied either as a positional argument
11
+ # (matching `pvectl edit node NAME` semantics) or via the --node flag.
12
+ #
13
+ # @example Basic usage
14
+ # pvectl edit dns pve1
15
+ # pvectl edit dns --node pve1
16
+ #
17
+ # @example Dry-run mode
18
+ # pvectl edit dns pve1 --dry-run
19
+ #
20
+ class EditDns
21
+ # Executes the edit dns command.
22
+ #
23
+ # @param args [Array<String>] command arguments (positional NODE)
24
+ # @param options [Hash] command options (:node, :editor, :"dry-run")
25
+ # @param global_options [Hash] global CLI options
26
+ # @return [Integer] exit code
27
+ def self.execute(args, options, global_options)
28
+ new(args, options, global_options).execute
29
+ end
30
+
31
+ # Initializes the command.
32
+ #
33
+ # @param args [Array<String>] command arguments
34
+ # @param options [Hash] command options
35
+ # @param global_options [Hash] global CLI options
36
+ def initialize(args, options, global_options)
37
+ @args = args
38
+ @options = options
39
+ @global_options = global_options
40
+ end
41
+
42
+ # Executes the edit flow.
43
+ #
44
+ # @return [Integer] exit code
45
+ def execute
46
+ node_name = @args.first || @options[:node]
47
+ return usage_error("NODE is required (positional argument or --node flag)") unless node_name && !node_name.empty?
48
+
49
+ load_config
50
+ connection = Pvectl::Connection.new(@config)
51
+ service = build_edit_service(connection)
52
+ result = service.execute(node_name: node_name)
53
+
54
+ if result.nil?
55
+ $stdout.puts "Edit cancelled, no changes made."
56
+ return ExitCodes::SUCCESS
57
+ end
58
+
59
+ if result.successful?
60
+ display_diff(result)
61
+ if @options[:"dry-run"]
62
+ $stdout.puts "(dry-run mode — no changes applied)"
63
+ else
64
+ $stdout.puts "DNS configuration for node #{node_name} updated successfully."
65
+ end
66
+ ExitCodes::SUCCESS
67
+ else
68
+ $stderr.puts "Error: #{result.error}"
69
+ ExitCodes::GENERAL_ERROR
70
+ end
71
+ rescue Pvectl::Config::ConfigNotFoundError,
72
+ Pvectl::Config::InvalidConfigError,
73
+ Pvectl::Config::ContextNotFoundError,
74
+ Pvectl::Config::ClusterNotFoundError,
75
+ Pvectl::Config::UserNotFoundError
76
+ raise
77
+ rescue StandardError => e
78
+ $stderr.puts "Error: #{e.message}"
79
+ ExitCodes::GENERAL_ERROR
80
+ end
81
+
82
+ private
83
+
84
+ # Builds the EditDns service with a connection.
85
+ #
86
+ # @param connection [Connection] API connection
87
+ # @return [Services::EditDns]
88
+ def build_edit_service(connection)
89
+ dns_repo = Pvectl::Repositories::Dns.new(connection)
90
+ Pvectl::Services::EditDns.new(
91
+ dns_repository: dns_repo,
92
+ editor_session: build_editor_session,
93
+ options: service_options
94
+ )
95
+ end
96
+
97
+ # Displays a formatted diff from the operation result.
98
+ #
99
+ # @param result [Models::NodeOperationResult] operation result with diff
100
+ # @return [void]
101
+ def display_diff(result)
102
+ diff = result.resource&.dig(:diff)
103
+ return unless diff
104
+ return if diff[:changed].empty? && diff[:added].empty? && diff[:removed].empty?
105
+
106
+ $stdout.puts "\nChanges:"
107
+ $stdout.puts Pvectl::ConfigSerializer.format_diff(diff)
108
+ $stdout.puts ""
109
+ end
110
+
111
+ # Loads configuration from file or environment.
112
+ #
113
+ # @return [void]
114
+ def load_config
115
+ service = Pvectl::Config::Service.new
116
+ service.load(config: @global_options[:config])
117
+ @config = service.current_config
118
+ end
119
+
120
+ # Builds service options from CLI options.
121
+ #
122
+ # @return [Hash] service options
123
+ def service_options
124
+ opts = {}
125
+ opts[:dry_run] = true if @options[:"dry-run"]
126
+ opts
127
+ end
128
+
129
+ # Builds an editor session from --editor option.
130
+ #
131
+ # @return [EditorSession, nil] editor session or nil if no --editor flag
132
+ def build_editor_session
133
+ editor_cmd = @options[:editor]
134
+ return nil unless editor_cmd
135
+
136
+ Pvectl::EditorSession.new(editor: ->(path) { system(editor_cmd, path) })
137
+ end
138
+
139
+ # Outputs usage error and returns exit code.
140
+ #
141
+ # @param message [String] error message
142
+ # @return [Integer] exit code
143
+ def usage_error(message)
144
+ $stderr.puts "Error: #{message}"
145
+ ExitCodes::USAGE_ERROR
146
+ end
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,135 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pvectl
4
+ module Commands
5
+ # Handler for the `pvectl edit hosts` command.
6
+ #
7
+ # Opens /etc/hosts for a node in the user's editor. On save, POSTs the
8
+ # new content back via /nodes/{node}/hosts with the original digest for
9
+ # optimistic concurrency control.
10
+ #
11
+ # The node identifier may be supplied either as a positional argument
12
+ # (matching `pvectl edit node NAME` semantics) or via the --node flag.
13
+ #
14
+ # @example Basic usage
15
+ # pvectl edit hosts pve1
16
+ # pvectl edit hosts --node pve1
17
+ #
18
+ # @example Dry-run mode
19
+ # pvectl edit hosts pve1 --dry-run
20
+ #
21
+ class EditHosts
22
+ # Executes the edit hosts command.
23
+ #
24
+ # @param args [Array<String>] command arguments (positional NODE)
25
+ # @param options [Hash] command options (:node, :editor, :"dry-run")
26
+ # @param global_options [Hash] global CLI options
27
+ # @return [Integer] exit code
28
+ def self.execute(args, options, global_options)
29
+ new(args, options, global_options).execute
30
+ end
31
+
32
+ # Initializes the command.
33
+ #
34
+ # @param args [Array<String>] command arguments
35
+ # @param options [Hash] command options
36
+ # @param global_options [Hash] global CLI options
37
+ def initialize(args, options, global_options)
38
+ @args = args
39
+ @options = options
40
+ @global_options = global_options
41
+ end
42
+
43
+ # Executes the edit flow.
44
+ #
45
+ # @return [Integer] exit code
46
+ def execute
47
+ node_name = @args.first || @options[:node]
48
+ return usage_error("NODE is required (positional argument or --node flag)") if node_name.nil? || node_name.empty?
49
+
50
+ load_config
51
+ connection = Pvectl::Connection.new(@config)
52
+ service = build_edit_service(connection)
53
+ result = service.execute(node_name: node_name)
54
+
55
+ if result.nil?
56
+ $stdout.puts "Edit cancelled, no changes made."
57
+ return ExitCodes::SUCCESS
58
+ end
59
+
60
+ if result.successful?
61
+ if @options[:"dry-run"]
62
+ $stdout.puts "(dry-run mode — no changes applied)"
63
+ else
64
+ $stdout.puts "/etc/hosts on node #{node_name} updated successfully."
65
+ end
66
+ ExitCodes::SUCCESS
67
+ else
68
+ $stderr.puts "Error: #{result.error}"
69
+ ExitCodes::GENERAL_ERROR
70
+ end
71
+ rescue Pvectl::Config::ConfigNotFoundError,
72
+ Pvectl::Config::InvalidConfigError,
73
+ Pvectl::Config::ContextNotFoundError,
74
+ Pvectl::Config::ClusterNotFoundError,
75
+ Pvectl::Config::UserNotFoundError
76
+ raise
77
+ rescue StandardError => e
78
+ $stderr.puts "Error: #{e.message}"
79
+ ExitCodes::GENERAL_ERROR
80
+ end
81
+
82
+ private
83
+
84
+ # Builds the EditHosts service with a connection.
85
+ #
86
+ # @param connection [Connection] API connection
87
+ # @return [Services::EditHosts]
88
+ def build_edit_service(connection)
89
+ hosts_repo = Pvectl::Repositories::Hosts.new(connection)
90
+ Pvectl::Services::EditHosts.new(
91
+ hosts_repository: hosts_repo,
92
+ editor_session: build_editor_session,
93
+ options: service_options
94
+ )
95
+ end
96
+
97
+ # Loads configuration from file or environment.
98
+ #
99
+ # @return [void]
100
+ def load_config
101
+ service = Pvectl::Config::Service.new
102
+ service.load(config: @global_options[:config])
103
+ @config = service.current_config
104
+ end
105
+
106
+ # Builds service options from CLI options.
107
+ #
108
+ # @return [Hash] service options
109
+ def service_options
110
+ opts = {}
111
+ opts[:dry_run] = true if @options[:"dry-run"]
112
+ opts
113
+ end
114
+
115
+ # Builds an editor session from --editor option.
116
+ #
117
+ # @return [EditorSession, nil] editor session or nil if no --editor flag
118
+ def build_editor_session
119
+ editor_cmd = @options[:editor]
120
+ return nil unless editor_cmd
121
+
122
+ Pvectl::EditorSession.new(editor: ->(path) { system(editor_cmd, path) })
123
+ end
124
+
125
+ # Outputs usage error and returns exit code.
126
+ #
127
+ # @param message [String] error message
128
+ # @return [Integer] exit code
129
+ def usage_error(message)
130
+ $stderr.puts "Error: #{message}"
131
+ ExitCodes::USAGE_ERROR
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pvectl
4
+ module Commands
5
+ # Handler for the `pvectl edit node` command.
6
+ #
7
+ # Includes EditResourceCommand for shared workflow and overrides
8
+ # template methods with node-specific behavior.
9
+ #
10
+ # @example Basic usage
11
+ # pvectl edit node pve1
12
+ #
13
+ # @example Dry-run mode
14
+ # pvectl edit node pve1 --dry-run
15
+ #
16
+ class EditNode
17
+ include EditResourceCommand
18
+
19
+ private
20
+
21
+ # @return [String] human label for node resources
22
+ def resource_label
23
+ "node"
24
+ end
25
+
26
+ # @return [String] human label for node IDs
27
+ def resource_id_label
28
+ "NODE"
29
+ end
30
+
31
+ # Builds execution parameters from a node name.
32
+ # Node uses string name (not integer ID).
33
+ #
34
+ # @param resource_id [String] node name
35
+ # @return [Hash] parameters for the edit service
36
+ def execute_params(resource_id)
37
+ { node_name: resource_id }
38
+ end
39
+
40
+ # Builds the node edit service.
41
+ #
42
+ # @param connection [Connection] API connection
43
+ # @return [Services::EditNode] node edit service
44
+ def build_edit_service(connection)
45
+ node_repo = Pvectl::Repositories::Node.new(connection)
46
+ Pvectl::Services::EditNode.new(
47
+ node_repository: node_repo,
48
+ editor_session: build_editor_session,
49
+ options: service_options
50
+ )
51
+ end
52
+ end
53
+ end
54
+ end