zen-cli 0.1.2__tar.gz → 0.1.5__tar.gz

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 (216) hide show
  1. {zen_cli-0.1.2 → zen_cli-0.1.5}/PKG-INFO +21 -7
  2. {zen_cli-0.1.2 → zen_cli-0.1.5}/README.md +19 -5
  3. {zen_cli-0.1.2 → zen_cli-0.1.5}/pyproject.toml +9 -3
  4. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/api.py +2 -64
  5. zen_cli-0.1.2/src/zen_cli/cmds/auth/status.py → zen_cli-0.1.5/src/zen_cli/cmds/auth/details.py +2 -2
  6. zen_cli-0.1.5/src/zen_cli/cmds/auth/status.py +17 -0
  7. zen_cli-0.1.5/src/zen_cli/cmds/credential/create.py +13 -0
  8. zen_cli-0.1.5/src/zen_cli/cmds/credential/delete.py +27 -0
  9. zen_cli-0.1.5/src/zen_cli/cmds/deployment/create.py +19 -0
  10. zen_cli-0.1.5/src/zen_cli/cmds/deployment/delete.py +28 -0
  11. zen_cli-0.1.5/src/zen_cli/cmds/entitlement/create.py +13 -0
  12. zen_cli-0.1.5/src/zen_cli/cmds/entitlement/delete.py +27 -0
  13. zen_cli-0.1.5/src/zen_cli/cmds/group/create.py +13 -0
  14. zen_cli-0.1.5/src/zen_cli/cmds/group/delete.py +33 -0
  15. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/login.py +17 -6
  16. zen_cli-0.1.5/src/zen_cli/cmds/network/create.py +13 -0
  17. zen_cli-0.1.5/src/zen_cli/cmds/network/delete.py +34 -0
  18. zen_cli-0.1.5/src/zen_cli/cmds/org/create.py +13 -0
  19. zen_cli-0.1.5/src/zen_cli/cmds/pool/create.py +13 -0
  20. zen_cli-0.1.5/src/zen_cli/cmds/provider/create.py +13 -0
  21. zen_cli-0.1.5/src/zen_cli/cmds/provider/delete.py +27 -0
  22. zen_cli-0.1.5/src/zen_cli/cmds/sag/create.py +13 -0
  23. zen_cli-0.1.5/src/zen_cli/cmds/sag/delete.py +34 -0
  24. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/ctxp/_init.py +0 -7
  25. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/ctxp/cmd_util.py +1 -1
  26. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/ctxp/logger.py +1 -1
  27. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/service/broker/entitlement.py +8 -0
  28. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/service/broker/pool_group.py +11 -0
  29. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/service/cockpit/network.py +11 -0
  30. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/service/cockpit/pool.py +4 -0
  31. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/service/cockpit/provider.py +8 -0
  32. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/service/cockpit/sag.py +11 -0
  33. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/service/credential.py +8 -0
  34. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/service/deployment.py +14 -0
  35. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/service/org.py +9 -0
  36. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/sglib/auth.py +29 -5
  37. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/sglib/csp.py +2 -2
  38. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/sglib/ez_client.py +1 -1
  39. zen_cli-0.1.5/src/zen_cli/support/auth.py +63 -0
  40. zen_cli-0.1.5/src/zen_cli/support/payload.py +123 -0
  41. zen_cli-0.1.5/src/zen_cli/support/test_utils.py +155 -0
  42. zen_cli-0.1.5/tests/blackbox/__init__.py +0 -0
  43. zen_cli-0.1.5/tests/blackbox/test_api.py +9 -0
  44. zen_cli-0.1.5/tests/blackbox/test_auth.py +20 -0
  45. zen_cli-0.1.5/tests/blackbox/test_completion.py +8 -0
  46. zen_cli-0.1.5/tests/blackbox/test_context.py +17 -0
  47. zen_cli-0.1.5/tests/blackbox/test_credential.py +11 -0
  48. zen_cli-0.1.5/tests/blackbox/test_deployment.py +11 -0
  49. zen_cli-0.1.5/tests/blackbox/test_entitlement.py +11 -0
  50. zen_cli-0.1.5/tests/blackbox/test_errors.py +88 -0
  51. zen_cli-0.1.5/tests/blackbox/test_group.py +11 -0
  52. zen_cli-0.1.5/tests/blackbox/test_io.py +88 -0
  53. zen_cli-0.1.5/tests/blackbox/test_login.py +27 -0
  54. zen_cli-0.1.5/tests/blackbox/test_logout.py +6 -0
  55. zen_cli-0.1.5/tests/blackbox/test_mcp.py +8 -0
  56. zen_cli-0.1.5/tests/blackbox/test_network.py +11 -0
  57. zen_cli-0.1.5/tests/blackbox/test_org.py +23 -0
  58. zen_cli-0.1.5/tests/blackbox/test_pool.py +33 -0
  59. zen_cli-0.1.5/tests/blackbox/test_profile.py +55 -0
  60. zen_cli-0.1.5/tests/blackbox/test_provider.py +11 -0
  61. zen_cli-0.1.5/tests/blackbox/test_root.py +14 -0
  62. zen_cli-0.1.5/tests/blackbox/test_sag.py +11 -0
  63. zen_cli-0.1.5/tests/blackbox/test_task.py +8 -0
  64. zen_cli-0.1.5/tests/blackbox/test_vm.py +8 -0
  65. zen_cli-0.1.5/tests/blackbox/util.py +31 -0
  66. zen_cli-0.1.5/tests/test_auth_status.py +26 -0
  67. {zen_cli-0.1.2 → zen_cli-0.1.5}/tests/test_cli.py +48 -1
  68. {zen_cli-0.1.2 → zen_cli-0.1.5}/tests/test_device_login.py +6 -1
  69. zen_cli-0.1.5/tests/test_payload.py +57 -0
  70. zen_cli-0.1.2/src/zen_cli/support/auth.py +0 -18
  71. {zen_cli-0.1.2 → zen_cli-0.1.5}/.gitignore +0 -0
  72. {zen_cli-0.1.2 → zen_cli-0.1.5}/LICENSE +0 -0
  73. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/__init__.py +0 -0
  74. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/__main__.py +0 -0
  75. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cli.py +0 -0
  76. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/activity/__init__.py +0 -0
  77. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/activity/get.py +0 -0
  78. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/activity/list.py +0 -0
  79. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/auth/__init__.py +0 -0
  80. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/auth/refresh.py +0 -0
  81. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/auth/token.py +0 -0
  82. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/completion.py +0 -0
  83. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/credential/__init__.py +0 -0
  84. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/credential/get.py +0 -0
  85. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/credential/list.py +0 -0
  86. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/deployment/__init__.py +0 -0
  87. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/deployment/get.py +0 -0
  88. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/deployment/list.py +0 -0
  89. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/entitlement/__init__.py +0 -0
  90. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/entitlement/get.py +0 -0
  91. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/entitlement/list.py +0 -0
  92. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/group/__init__.py +0 -0
  93. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/group/get.py +0 -0
  94. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/group/list.py +0 -0
  95. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/logout.py +0 -0
  96. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/mcp.py +0 -0
  97. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/network/__init__.py +0 -0
  98. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/network/get.py +0 -0
  99. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/network/list.py +0 -0
  100. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/notification/__init__.py +0 -0
  101. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/notification/get.py +0 -0
  102. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/notification/list.py +0 -0
  103. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/org/__init__.py +0 -0
  104. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/org/get.py +0 -0
  105. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/org/list.py +0 -0
  106. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/org/use.py +0 -0
  107. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/pool/__init__.py +0 -0
  108. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/pool/delete.py +0 -0
  109. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/pool/get.py +0 -0
  110. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/pool/list.py +0 -0
  111. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/pool/use.py +0 -0
  112. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/profile/__init__.py +0 -0
  113. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/profile/init.py +0 -0
  114. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/provider/__init__.py +0 -0
  115. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/provider/get.py +0 -0
  116. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/provider/list.py +0 -0
  117. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/sag/__init__.py +0 -0
  118. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/sag/get.py +0 -0
  119. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/sag/list.py +0 -0
  120. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/task/__init__.py +0 -0
  121. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/task/cancel.py +0 -0
  122. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/task/delete.py +0 -0
  123. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/task/duplicate.py +0 -0
  124. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/task/get.py +0 -0
  125. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/task/list.py +0 -0
  126. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/task/log.py +0 -0
  127. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/task/namespaces.py +0 -0
  128. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/task/use.py +0 -0
  129. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/task/wait.py +0 -0
  130. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/upgrade.py +0 -0
  131. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/vm/__init__.py +0 -0
  132. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/vm/delete.py +0 -0
  133. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/vm/get.py +0 -0
  134. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/vm/list.py +0 -0
  135. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/vm/poweroff.py +0 -0
  136. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/vm/poweron.py +0 -0
  137. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/vm/restart.py +0 -0
  138. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/vm/shutdown.py +0 -0
  139. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/vm/use.py +0 -0
  140. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/cmds/vm/wait.py +0 -0
  141. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/config/default.yaml +0 -0
  142. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/config/int.yaml +0 -0
  143. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/config/prod.yaml +0 -0
  144. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/config/stg.yaml +0 -0
  145. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/ctxp/__init__.py +0 -0
  146. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/ctxp/built_in_cmds/__init__.py +0 -0
  147. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/ctxp/built_in_cmds/_ut.py +0 -0
  148. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/ctxp/built_in_cmds/context.py +0 -0
  149. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/ctxp/built_in_cmds/profile.py +0 -0
  150. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/ctxp/cli_options.py +0 -0
  151. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/ctxp/cli_processor.py +0 -0
  152. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/ctxp/config.py +0 -0
  153. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/ctxp/context.py +0 -0
  154. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/ctxp/data_util.py +0 -0
  155. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/ctxp/dispatcher.py +0 -0
  156. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/ctxp/extension.py +0 -0
  157. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/ctxp/fn_util.py +0 -0
  158. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/ctxp/fstore.py +0 -0
  159. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/ctxp/jsondot.py +0 -0
  160. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/ctxp/profile.py +0 -0
  161. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/ctxp/profile_store.py +0 -0
  162. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/ctxp/recent.py +0 -0
  163. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/ctxp/state.py +0 -0
  164. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/ctxp/telemetry.py +0 -0
  165. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/ctxp/template_util.py +0 -0
  166. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/ctxp/timeutil.py +0 -0
  167. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/ctxp/util.py +0 -0
  168. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/ctxp/var_template.py +0 -0
  169. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/mcp/__init__.py +0 -0
  170. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/mcp/_util.py +0 -0
  171. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/mcp/resources/__init__.py +0 -0
  172. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/mcp/resources/activity.py +0 -0
  173. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/mcp/resources/api.py +0 -0
  174. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/mcp/resources/credential.py +0 -0
  175. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/mcp/resources/deployment.py +0 -0
  176. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/mcp/resources/entitlement.py +0 -0
  177. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/mcp/resources/group.py +0 -0
  178. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/mcp/resources/network.py +0 -0
  179. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/mcp/resources/notification.py +0 -0
  180. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/mcp/resources/org.py +0 -0
  181. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/mcp/resources/pool.py +0 -0
  182. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/mcp/resources/provider.py +0 -0
  183. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/mcp/resources/sag.py +0 -0
  184. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/mcp/resources/task.py +0 -0
  185. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/mcp/resources/vm.py +0 -0
  186. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/mcp/server.py +0 -0
  187. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/service/__init__.py +0 -0
  188. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/service/activity.py +0 -0
  189. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/service/api.py +0 -0
  190. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/service/broker/__init__.py +0 -0
  191. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/service/cockpit/__init__.py +0 -0
  192. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/service/cockpit/vm.py +0 -0
  193. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/service/notification.py +0 -0
  194. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/service/task.py +0 -0
  195. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/sglib/__init__.py +0 -0
  196. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/sglib/cli_options.py +0 -0
  197. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/sglib/client_util.py +0 -0
  198. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/sglib/init.py +0 -0
  199. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/sglib/login_support.py +0 -0
  200. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/sglib/mdc.py +0 -0
  201. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/sglib/payload_util.py +0 -0
  202. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/sglib/requtil.py +0 -0
  203. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/sglib/utils.py +0 -0
  204. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/sglib/zds_client.py +0 -0
  205. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/support/profile.py +0 -0
  206. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/support/task.py +0 -0
  207. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/support/use_util.py +0 -0
  208. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/support/vm.py +0 -0
  209. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/util/exec_util.py +0 -0
  210. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/util/exit.py +0 -0
  211. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/util/param_util.py +0 -0
  212. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/util/patch_util.py +0 -0
  213. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/util/query_util.py +0 -0
  214. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/util/readonly.py +0 -0
  215. {zen_cli-0.1.2 → zen_cli-0.1.5}/src/zen_cli/util/versions.py +0 -0
  216. {zen_cli-0.1.2 → zen_cli-0.1.5}/tests/test_mcp.py +0 -0
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: zen-cli
3
- Version: 0.1.2
4
- Summary: Command-line toolbox for Zen Cloud PC. Operate orgs, pools, VMs, and tasks; call ZDS APIs; expose a stdio MCP server.
3
+ Version: 0.1.5
4
+ Summary: CLI for Zen Desktop Service. Designed for AI and Human.
5
5
  Project-URL: Homepage, https://pypi.org/project/zen-cli/
6
6
  Author: zen-cli authors
7
7
  License-Expression: MIT
@@ -36,6 +36,17 @@ Description-Content-Type: text/markdown
36
36
 
37
37
  Command-line toolbox for Zen Cloud PC, designed for AI and human.
38
38
 
39
+ ## Contents
40
+
41
+ - [Try it out](#try-it-out)
42
+ - [Prerequisites](#prerequisites)
43
+ - [Installation](#installation)
44
+ - [Mac & Linux](#mac--linux)
45
+ - [Windows](#windows)
46
+ - [Use the CLI](#use-the-cli)
47
+ - [Documentation](#documentation)
48
+ - [License](#license)
49
+
39
50
  ## Try it out
40
51
 
41
52
  ### Prerequisites
@@ -64,20 +75,23 @@ If Python was installed without “Add python to PATH”, add Python and its `Sc
64
75
  ```text
65
76
  zen login
66
77
  zen auth status
78
+ zen auth details
79
+ zen auth token
67
80
  ```
68
81
 
69
- `zen login` reuses cached or configured credentials. Interactive login is `zen login --device-code`; machine login is `zen login --client-id` / `--client-secret`. Use `zen auth status` / `zen auth token` to inspect the session (`--service` for a per-service override). `zen auth refresh` refreshes the cached token.
82
+ `zen login` reuses a valid cached token or configured credentials (API token, client id/secret). If neither is available it starts device-code login. It does not print the access token. Machine login is `zen login --client-id` / `--client-secret`. `zen auth status` is JSON (`logged_in`, `method`, `ttl`). `zen auth details` is the JWT and org. `zen auth token` is the bearer (`--service` on details/token). `zen auth refresh` refreshes the cached token.
70
83
 
71
- Run a command, for example, list orgs:
84
+ Run a command, for example, list pools:
72
85
 
73
86
  ```text
74
- zen org list
87
+ zen pool list
75
88
  ```
76
89
 
77
90
  ## Documentation
78
91
 
79
- * [Cheatsheet](docs/cheatsheet.md)
80
- * [Developer guide](docs/dev.md)
92
+ * [User guide](docs/user-guide.md) — profiles, flags, payloads, and command conventions
93
+ * [Cheatsheet](docs/cheatsheet.md) — command examples
94
+ * [Developer guide](docs/dev.md) — build, test, and package layout
81
95
 
82
96
  ## License
83
97
 
@@ -4,6 +4,17 @@
4
4
 
5
5
  Command-line toolbox for Zen Cloud PC, designed for AI and human.
6
6
 
7
+ ## Contents
8
+
9
+ - [Try it out](#try-it-out)
10
+ - [Prerequisites](#prerequisites)
11
+ - [Installation](#installation)
12
+ - [Mac & Linux](#mac--linux)
13
+ - [Windows](#windows)
14
+ - [Use the CLI](#use-the-cli)
15
+ - [Documentation](#documentation)
16
+ - [License](#license)
17
+
7
18
  ## Try it out
8
19
 
9
20
  ### Prerequisites
@@ -32,20 +43,23 @@ If Python was installed without “Add python to PATH”, add Python and its `Sc
32
43
  ```text
33
44
  zen login
34
45
  zen auth status
46
+ zen auth details
47
+ zen auth token
35
48
  ```
36
49
 
37
- `zen login` reuses cached or configured credentials. Interactive login is `zen login --device-code`; machine login is `zen login --client-id` / `--client-secret`. Use `zen auth status` / `zen auth token` to inspect the session (`--service` for a per-service override). `zen auth refresh` refreshes the cached token.
50
+ `zen login` reuses a valid cached token or configured credentials (API token, client id/secret). If neither is available it starts device-code login. It does not print the access token. Machine login is `zen login --client-id` / `--client-secret`. `zen auth status` is JSON (`logged_in`, `method`, `ttl`). `zen auth details` is the JWT and org. `zen auth token` is the bearer (`--service` on details/token). `zen auth refresh` refreshes the cached token.
38
51
 
39
- Run a command, for example, list orgs:
52
+ Run a command, for example, list pools:
40
53
 
41
54
  ```text
42
- zen org list
55
+ zen pool list
43
56
  ```
44
57
 
45
58
  ## Documentation
46
59
 
47
- * [Cheatsheet](docs/cheatsheet.md)
48
- * [Developer guide](docs/dev.md)
60
+ * [User guide](docs/user-guide.md) — profiles, flags, payloads, and command conventions
61
+ * [Cheatsheet](docs/cheatsheet.md) — command examples
62
+ * [Developer guide](docs/dev.md) — build, test, and package layout
49
63
 
50
64
  ## License
51
65
 
@@ -4,8 +4,8 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "zen-cli"
7
- version = "0.1.2"
8
- description = "Command-line toolbox for Zen Cloud PC. Operate orgs, pools, VMs, and tasks; call ZDS APIs; expose a stdio MCP server."
7
+ version = "0.1.5"
8
+ description = "CLI for Zen Desktop Service. Designed for AI and Human."
9
9
  readme = "README.md"
10
10
  license = "MIT"
11
11
  license-files = ["LICENSE"]
@@ -44,7 +44,7 @@ include = ["src/zen_cli", "tests", "README.md", "LICENSE"]
44
44
  target-version = "py312"
45
45
  line-length = 120
46
46
  src = ["src"]
47
- exclude = ["cli-ref"]
47
+ exclude = ["cli-ref", "src/zen_cli/support/test_utils2.py"]
48
48
 
49
49
  [tool.ruff.lint]
50
50
  select = ["E", "F", "I", "UP", "B", "SIM", "RUF"]
@@ -53,6 +53,7 @@ select = ["E", "F", "I", "UP", "B", "SIM", "RUF"]
53
53
  python_version = "3.12"
54
54
  strict = true
55
55
  files = ["src"]
56
+ exclude = ["test_utils2\\.py"]
56
57
 
57
58
  [[tool.mypy.overrides]]
58
59
  module = ["mcp", "mcp.*"]
@@ -67,9 +68,14 @@ module = [
67
68
  "yaml",
68
69
  "httpx2",
69
70
  "httpx2.*",
71
+ "coloredlogs",
70
72
  ]
71
73
  ignore_missing_imports = true
72
74
 
73
75
  [[tool.mypy.overrides]]
74
76
  module = ["zen_cli.cmds", "zen_cli.cmds.*", "zen_cli.ctxp", "zen_cli.ctxp.*"]
75
77
  disallow_untyped_decorators = false
78
+
79
+ [[tool.mypy.overrides]]
80
+ module = ["zen_cli.service.task"]
81
+ disallow_subclassing_any = false
@@ -1,73 +1,11 @@
1
- import json
2
- import sys
3
- from pathlib import Path
4
1
  from typing import Any
5
2
 
6
3
  import click
7
4
 
8
- from zen_cli.ctxp import CtxpException
9
5
  from zen_cli.service import api as zen_api
10
6
  from zen_cli.sglib import mdc as mdc_session
11
7
  from zen_cli.sglib.client_util import resolve_zds_base_url
12
-
13
-
14
- def _has_stdin_data() -> bool:
15
- return not sys.stdin.isatty()
16
-
17
-
18
- def _resolve_data(data_arg: str | None) -> str | None:
19
- """Resolve data from various sources following curl-style conventions."""
20
- if not data_arg:
21
- return None
22
-
23
- if data_arg == "-":
24
- content = sys.stdin.read()
25
- return content if content else None
26
-
27
- if data_arg.startswith("@"):
28
- filepath = data_arg[1:]
29
- try:
30
- content = Path(filepath).read_text()
31
- return content or None
32
- except FileNotFoundError:
33
- raise CtxpException(f"File not found: {filepath}") from None
34
-
35
- return data_arg
36
-
37
-
38
- def _handle_data_input(data_arg: str | None, json_arg: str | None) -> tuple[str | None, Any]:
39
- if data_arg and json_arg:
40
- raise click.UsageError("Cannot specify both --data and --json options. Use one of them.")
41
-
42
- raw_data = None
43
- json_data = None
44
-
45
- if data_arg:
46
- if _has_stdin_data() and data_arg != "-":
47
- raise click.UsageError(
48
- "Cannot specify --data when data is piped via stdin. Use '--data -' for explicit stdin input."
49
- )
50
- raw_data = _resolve_data(data_arg)
51
- elif json_arg:
52
- if _has_stdin_data() and json_arg != "-":
53
- raise click.UsageError(
54
- "Cannot specify --json when data is piped via stdin. Use '--json -' for explicit stdin input."
55
- )
56
- content = _resolve_data(json_arg)
57
- if content:
58
- try:
59
- json_data = json.loads(content.strip())
60
- except json.JSONDecodeError as e:
61
- raise CtxpException(f"Invalid JSON: {e}. File={json_arg}.") from e
62
- elif _has_stdin_data():
63
- stdin_content = sys.stdin.read().strip()
64
- if stdin_content:
65
- try:
66
- json_data = json.loads(stdin_content)
67
- except json.JSONDecodeError:
68
- raw_data = stdin_content
69
-
70
- return raw_data, json_data
8
+ from zen_cli.support.payload import handle_data_input
71
9
 
72
10
 
73
11
  def _build_headers(header: list[str], content_type: str | None) -> dict[str, str] | None:
@@ -170,7 +108,7 @@ def api(
170
108
  if raise_on_404 and method not in ("GET", "DELETE"):
171
109
  raise click.UsageError("The --raise-on-404 option is only applicable for GET and DELETE methods.")
172
110
 
173
- raw_data, json_data = _handle_data_input(data_arg, json_arg)
111
+ raw_data, json_data = handle_data_input(data_arg, json_arg)
174
112
 
175
113
  if method in ["GET", "DELETE"] and (raw_data is not None or json_data is not None):
176
114
  raise click.UsageError(
@@ -13,7 +13,7 @@ from zen_cli.support import auth as auth_support
13
13
  required=False,
14
14
  help="Get the auth details for a target service. Useful if per-service auth override is configured.",
15
15
  )
16
- def status(service: str | None) -> Any:
17
- """Show current authentication details."""
16
+ def details(service: str | None) -> Any:
17
+ """Show cached token, JWT claims, and org."""
18
18
  token = auth_support.oauth_token(service)
19
19
  return sglib.auth.details_from_token(token, False)
@@ -0,0 +1,17 @@
1
+ from typing import Any
2
+
3
+ import click
4
+
5
+ from zen_cli.support import auth as auth_support
6
+
7
+
8
+ @click.command()
9
+ @click.option(
10
+ "--service",
11
+ "-s",
12
+ required=False,
13
+ help="Report login status for a target service override.",
14
+ )
15
+ def status(service: str | None) -> Any:
16
+ """Show whether you are logged in, the login method, and token TTL in seconds."""
17
+ return auth_support.session_status(service)
@@ -0,0 +1,13 @@
1
+ from typing import Any
2
+
3
+ import click
4
+
5
+ from zen_cli.service import credential
6
+ from zen_cli.support.payload import payload_options, run_create
7
+
8
+
9
+ @click.command()
10
+ @payload_options
11
+ def create(data_arg: str | None, json_arg: str | None) -> Any:
12
+ """Create a credential from a JSON payload."""
13
+ return run_create("credential", credential.create, data_arg, json_arg)
@@ -0,0 +1,27 @@
1
+ from typing import Any
2
+
3
+ import click
4
+
5
+ import zen_cli.sglib.cli_options as cli
6
+ from zen_cli.ctxp import recent
7
+ from zen_cli.service import credential
8
+
9
+
10
+ @click.command()
11
+ @click.argument("id", type=str, required=False)
12
+ @cli.confirm
13
+ @cli.org_id
14
+ def delete(id: str, confirm: bool, org: str) -> Any:
15
+ """Delete credential by ID"""
16
+
17
+ org_id = cli.get_org_id(org)
18
+ id = recent.require("credential", id)
19
+ ret = credential.get(id, org_id)
20
+ if not ret:
21
+ click.echo(f"Credential {id} not found; already deleted.", err=True)
22
+ return ""
23
+
24
+ if not confirm:
25
+ click.confirm(f"Delete credential {ret.get('name', id)} ({id})?", abort=True)
26
+
27
+ return credential.delete(id, org_id)
@@ -0,0 +1,19 @@
1
+ from typing import Any
2
+
3
+ import click
4
+
5
+ import zen_cli.sglib.cli_options as cli
6
+ from zen_cli.service import deployment
7
+ from zen_cli.support.payload import payload_options, run_create
8
+
9
+
10
+ @click.command()
11
+ @cli.org_id
12
+ @payload_options
13
+ def create(org: str, data_arg: str | None, json_arg: str | None) -> Any:
14
+ """Create an express deployment from a JSON payload."""
15
+
16
+ def _create(payload: Any) -> Any:
17
+ return deployment.create(payload, org_id=cli.get_org_id(org))
18
+
19
+ return run_create("deployment", _create, data_arg, json_arg)
@@ -0,0 +1,28 @@
1
+ from typing import Any
2
+
3
+ import click
4
+
5
+ import zen_cli.sglib.cli_options as cli
6
+ from zen_cli.ctxp import recent
7
+ from zen_cli.service import deployment
8
+
9
+
10
+ @click.command()
11
+ @click.argument("id", type=str, required=False)
12
+ @cli.confirm
13
+ @cli.org_id
14
+ def delete(id: str, confirm: bool, org: str) -> Any:
15
+ """Delete express deployment by ID"""
16
+
17
+ org_id = cli.get_org_id(org)
18
+ id = recent.require("deployment", id)
19
+ ret = deployment.get(id, org_id)
20
+ if not ret:
21
+ click.echo(f"Deployment {id} not found; already deleted.", err=True)
22
+ return ""
23
+
24
+ if not confirm:
25
+ label = ret.get("name") or ret.get("providerId") or id
26
+ click.confirm(f"Delete deployment {label} ({id})?", abort=True)
27
+
28
+ return deployment.delete(id, org_id)
@@ -0,0 +1,13 @@
1
+ from typing import Any
2
+
3
+ import click
4
+
5
+ from zen_cli.service.broker import entitlement
6
+ from zen_cli.support.payload import payload_options, run_create
7
+
8
+
9
+ @click.command()
10
+ @payload_options
11
+ def create(data_arg: str | None, json_arg: str | None) -> Any:
12
+ """Create an entitlement from a JSON payload."""
13
+ return run_create("entitlement", entitlement.create, data_arg, json_arg)
@@ -0,0 +1,27 @@
1
+ from typing import Any
2
+
3
+ import click
4
+
5
+ import zen_cli.sglib.cli_options as cli
6
+ from zen_cli.ctxp import recent
7
+ from zen_cli.service.broker import entitlement
8
+
9
+
10
+ @click.command()
11
+ @click.argument("id", type=str, required=False)
12
+ @cli.confirm
13
+ @cli.org_id
14
+ def delete(id: str, confirm: bool, org: str) -> Any:
15
+ """Delete entitlement by ID"""
16
+
17
+ org_id = cli.get_org_id(org)
18
+ id = recent.require("entitlement", id)
19
+ ret = entitlement.get(id, org_id)
20
+ if not ret:
21
+ click.echo(f"Entitlement {id} not found; already deleted.", err=True)
22
+ return ""
23
+
24
+ if not confirm:
25
+ click.confirm(f"Delete entitlement {ret.get('name', id)} ({id})?", abort=True)
26
+
27
+ return entitlement.delete(id, org_id)
@@ -0,0 +1,13 @@
1
+ from typing import Any
2
+
3
+ import click
4
+
5
+ from zen_cli.service.broker import pool_group
6
+ from zen_cli.support.payload import payload_options, run_create
7
+
8
+
9
+ @click.command()
10
+ @payload_options
11
+ def create(data_arg: str | None, json_arg: str | None) -> Any:
12
+ """Create a pool group from a JSON payload."""
13
+ return run_create("group", pool_group.create, data_arg, json_arg)
@@ -0,0 +1,33 @@
1
+ from typing import Any
2
+
3
+ import click
4
+
5
+ import zen_cli.sglib.cli_options as cli
6
+ from zen_cli.ctxp import recent
7
+ from zen_cli.service.broker import pool_group
8
+
9
+
10
+ @click.command()
11
+ @click.argument("id", type=str, required=False)
12
+ @cli.confirm
13
+ @cli.org_id
14
+ @cli.wait
15
+ def delete(id: str, confirm: bool, org: str, wait: str) -> Any:
16
+ """Delete pool group by ID"""
17
+
18
+ org_id = cli.get_org_id(org)
19
+ id = recent.require("group", id)
20
+ ret = pool_group.get(id, org_id)
21
+ if not ret:
22
+ click.echo(f"Group {id} not found; already deleted.", err=True)
23
+ return ""
24
+
25
+ if not confirm:
26
+ click.confirm(f"Delete group {ret.get('name', id)} ({id})?", abort=True)
27
+
28
+ ret = pool_group.delete(id, org_id)
29
+
30
+ if wait == "0":
31
+ return ret
32
+
33
+ pool_group.wait_for_deleted(id, org_id, wait)
@@ -89,15 +89,16 @@ def login(
89
89
 
90
90
  This command works with the current profile and will update the current profile.
91
91
  With no method flag, reuses the cached token or configured credentials.
92
- Browser SSO runs only with `--browser`.
92
+ If neither is available, starts device-code login. Browser SSO runs only
93
+ with `--browser`.
93
94
 
94
95
  Inspect or refresh an existing session with `zen auth` (not this command):
95
- `zen auth status`, `zen auth token`, `zen auth refresh`.
96
- Per-service tokens: `zen auth status --service` / `zen auth token --service`.
96
+ `zen auth status`, `zen auth details`, `zen auth token`, `zen auth refresh`.
97
+ Per-service tokens: `zen auth details --service` / `zen auth token --service`.
97
98
 
98
99
  \b
99
100
  Examples:
100
- 1. Re-login with cached token or configured credentials:
101
+ 1. Re-login with cache, configured credentials, or device code:
101
102
  zen login
102
103
  2. Login with OAuth device code (any browser, no localhost callback):
103
104
  zen login --device-code
@@ -204,7 +205,12 @@ def login(
204
205
  elif device_code:
205
206
  oauth_token = _do_device_login()
206
207
  else:
207
- oauth_token = sglib.auth.login(force_refresh=refresh, verbose=verbose)
208
+ try:
209
+ oauth_token = sglib.auth.login(force_refresh=refresh, verbose=verbose)
210
+ except ctxp.CtxpException as e:
211
+ if not _is_missing_session(e):
212
+ raise
213
+ oauth_token = _do_device_login()
208
214
  except Exception as e:
209
215
  oauth_token = None
210
216
  err = error_details(e)
@@ -234,7 +240,12 @@ def login(
234
240
  # Cache key is md5(csp config); re-save so orgId backfill does not orphan the entry.
235
241
  sglib.auth.save_auth_cache(csp, oauth_token)
236
242
 
237
- return oauth_token["access_token"]
243
+ return None
244
+
245
+
246
+ def _is_missing_session(err: BaseException) -> bool:
247
+ text = str(err)
248
+ return "Not logged in" in text or "Browser session expired" in text
238
249
 
239
250
 
240
251
  def _echo(msg: str) -> None:
@@ -0,0 +1,13 @@
1
+ from typing import Any
2
+
3
+ import click
4
+
5
+ from zen_cli.service.cockpit import network
6
+ from zen_cli.support.payload import payload_options, run_create
7
+
8
+
9
+ @click.command()
10
+ @payload_options
11
+ def create(data_arg: str | None, json_arg: str | None) -> Any:
12
+ """Create a network infrastructure deployment from a JSON payload."""
13
+ return run_create("network", network.create, data_arg, json_arg)
@@ -0,0 +1,34 @@
1
+ from typing import Any
2
+
3
+ import click
4
+
5
+ import zen_cli.sglib.cli_options as cli
6
+ from zen_cli.ctxp import recent
7
+ from zen_cli.service.cockpit import network
8
+
9
+
10
+ @click.command()
11
+ @click.argument("id", type=str, required=False)
12
+ @cli.confirm
13
+ @cli.org_id
14
+ @cli.wait
15
+ def delete(id: str, confirm: bool, org: str, wait: str) -> Any:
16
+ """Delete network infrastructure deployment by ID"""
17
+
18
+ org_id = cli.get_org_id(org)
19
+ id = recent.require("network", id)
20
+ ret = network.get(id, org_id)
21
+ if not ret:
22
+ click.echo(f"Network {id} not found; already deleted.", err=True)
23
+ return ""
24
+
25
+ if not confirm:
26
+ label = ret.get("name") or ret.get("description") or id
27
+ click.confirm(f"Delete network {label} ({id})?", abort=True)
28
+
29
+ ret = network.delete(id, org_id)
30
+
31
+ if wait == "0":
32
+ return ret
33
+
34
+ network.wait_for_deleted(id, org_id, wait)
@@ -0,0 +1,13 @@
1
+ from typing import Any
2
+
3
+ import click
4
+
5
+ from zen_cli.service import org as org_svc
6
+ from zen_cli.support.payload import payload_options, run_create
7
+
8
+
9
+ @click.command()
10
+ @payload_options
11
+ def create(data_arg: str | None, json_arg: str | None) -> Any:
12
+ """Create org details from a JSON payload."""
13
+ return run_create("org", org_svc.create, data_arg, json_arg, id_field="orgId")
@@ -0,0 +1,13 @@
1
+ from typing import Any
2
+
3
+ import click
4
+
5
+ from zen_cli.service.cockpit import pool
6
+ from zen_cli.support.payload import payload_options, run_create
7
+
8
+
9
+ @click.command()
10
+ @payload_options
11
+ def create(data_arg: str | None, json_arg: str | None) -> Any:
12
+ """Create a pool from a JSON payload."""
13
+ return run_create("pool", pool.create, data_arg, json_arg)
@@ -0,0 +1,13 @@
1
+ from typing import Any
2
+
3
+ import click
4
+
5
+ from zen_cli.service.cockpit import provider
6
+ from zen_cli.support.payload import payload_options, run_create
7
+
8
+
9
+ @click.command()
10
+ @payload_options
11
+ def create(data_arg: str | None, json_arg: str | None) -> Any:
12
+ """Create a provider instance from a JSON payload."""
13
+ return run_create("provider", provider.create, data_arg, json_arg)
@@ -0,0 +1,27 @@
1
+ from typing import Any
2
+
3
+ import click
4
+
5
+ import zen_cli.sglib.cli_options as cli
6
+ from zen_cli.ctxp import recent
7
+ from zen_cli.service.cockpit import provider
8
+
9
+
10
+ @click.command()
11
+ @click.argument("id", type=str, required=False)
12
+ @cli.confirm
13
+ @cli.org_id
14
+ def delete(id: str, confirm: bool, org: str) -> Any:
15
+ """Delete provider instance by ID"""
16
+
17
+ org_id = cli.get_org_id(org)
18
+ id = recent.require("provider", id)
19
+ ret = provider.get(id, org_id)
20
+ if not ret:
21
+ click.echo(f"Provider {id} not found; already deleted.", err=True)
22
+ return ""
23
+
24
+ if not confirm:
25
+ click.confirm(f"Delete provider {ret.get('name', id)} ({id})?", abort=True)
26
+
27
+ return provider.delete(id, org_id)
@@ -0,0 +1,13 @@
1
+ from typing import Any
2
+
3
+ import click
4
+
5
+ from zen_cli.service.cockpit import sag
6
+ from zen_cli.support.payload import payload_options, run_create
7
+
8
+
9
+ @click.command()
10
+ @payload_options
11
+ def create(data_arg: str | None, json_arg: str | None) -> Any:
12
+ """Create a SAG deployment from a JSON payload."""
13
+ return run_create("sag", sag.create, data_arg, json_arg)
@@ -0,0 +1,34 @@
1
+ from typing import Any
2
+
3
+ import click
4
+
5
+ import zen_cli.sglib.cli_options as cli
6
+ from zen_cli.ctxp import recent
7
+ from zen_cli.service.cockpit import sag
8
+
9
+
10
+ @click.command()
11
+ @click.argument("id", type=str, required=False)
12
+ @cli.confirm
13
+ @cli.org_id
14
+ @cli.wait
15
+ def delete(id: str, confirm: bool, org: str, wait: str) -> Any:
16
+ """Delete SAG deployment by ID"""
17
+
18
+ org_id = cli.get_org_id(org)
19
+ id = recent.require("sag", id)
20
+ ret = sag.get(id, org_id)
21
+ if not ret:
22
+ click.echo(f"SAG {id} not found; already deleted.", err=True)
23
+ return ""
24
+
25
+ if not confirm:
26
+ label = ret.get("name") or ret.get("region") or id
27
+ click.confirm(f"Delete SAG {label} ({id})?", abort=True)
28
+
29
+ ret = sag.delete(id, org_id)
30
+
31
+ if wait == "0":
32
+ return ret
33
+
34
+ sag.wait_for_deleted(id, org_id, wait)