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