cli_sub.rs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. //! Subcommand enums split out of cli.rs (the 500-line cap).
  2. //! Clap-derive types only — `crate::cli` re-exports them so callers and
  3. //! dispatch keep their import paths.
  4. use clap::{Args, Subcommand};
  5. #[derive(Subcommand)]
  6. pub enum PowerAction {
  7. /// Power off: SSH `sudo shutdown now` + wait + HA `turn_off`.
  8. Off {
  9. #[arg(long)]
  10. cluster: String,
  11. /// Target a specific node within the cluster (default: all).
  12. #[arg(long)]
  13. node: Option<String>,
  14. },
  15. /// Power on: HA `turn_on` only (no SSH; the smart plug wakes the machine).
  16. On {
  17. #[arg(long)]
  18. cluster: String,
  19. /// Target a specific node within the cluster (default: all).
  20. #[arg(long)]
  21. node: Option<String>,
  22. },
  23. /// Switch clusters: disable nodes from source, enable nodes in target.
  24. Switch {
  25. /// Current cluster (nodes + entities to shut down).
  26. #[arg(long)]
  27. from: String,
  28. /// Target cluster (nodes + entities to wake up).
  29. #[arg(long)]
  30. to: String,
  31. },
  32. }
  33. /// `sm121 config` subcommands — manage the global config file.
  34. #[derive(Subcommand)]
  35. pub enum ConfigCommands {
  36. /// Show the active config path and where the global config lives
  37. Path,
  38. /// Create the global config file (template) if it does not exist
  39. InitGlobal,
  40. }
  41. #[derive(Args)]
  42. pub struct PublishArgs {
  43. #[arg(long, required = true)]
  44. pub recipe: String,
  45. /// Cluster whose fabric env + node count fill the generated run script
  46. #[arg(long)]
  47. pub cluster: Option<String>,
  48. /// Output dir (default: ./publish/<recipe>)
  49. #[arg(long)]
  50. pub out: Option<std::path::PathBuf>,
  51. /// Also create a public GitHub gist (requires `gh` CLI, authenticated)
  52. #[arg(long)]
  53. pub gist: bool,
  54. /// After bundling, push the recipe's image to the image registry
  55. /// (`[registry]` config) under its version tag + `latest`.
  56. #[arg(long)]
  57. pub push: bool,
  58. /// Node that has the image for `--push` (default: probe all cluster
  59. /// nodes for the first match).
  60. #[arg(long)]
  61. pub node: Option<String>,
  62. /// Re-push even if the publication ledger already records this image
  63. /// digest (with `--push`).
  64. #[arg(long)]
  65. pub force: bool,
  66. /// Upload the bundle to a recipe registry (see `sm121 registry --help`)
  67. #[arg(long, value_name = "URL")]
  68. pub registry: Option<String>,
  69. /// Registry publish token (or $SM121RECIPES_TOKEN)
  70. #[arg(long)]
  71. pub token: Option<String>,
  72. }
  73. #[derive(Subcommand)]
  74. pub enum RegistryCommands {
  75. /// List recipes on the registry
  76. List {
  77. #[arg(long, value_name = "URL")]
  78. registry: Option<String>,
  79. },
  80. /// Print a registry recipe (recipe.toml)
  81. Show {
  82. name: String,
  83. #[arg(long, value_name = "URL")]
  84. registry: Option<String>,
  85. },
  86. /// Download a recipe into ./recipes/<name>/ (+ ./docker-images/<name>/ if it has an image)
  87. Install {
  88. name: String,
  89. #[arg(long, value_name = "URL")]
  90. registry: Option<String>,
  91. /// Overwrite an existing ./recipes/<name>/
  92. #[arg(long)]
  93. force: bool,
  94. },
  95. }
  96. #[derive(Subcommand)]
  97. pub enum TmuxCommands {
  98. /// Launch cluster via tmux
  99. Serve {
  100. #[arg(long, required = true)]
  101. recipe: String,
  102. #[arg(long, default_value = "auto")]
  103. cluster: String,
  104. /// Skip pre-serve hooks (cluster-level + recipe-level).
  105. #[arg(long)]
  106. skip_before_serve: bool,
  107. },
  108. /// Stop tmux sessions
  109. Stop {
  110. #[arg(long, required = true)]
  111. recipe: String,
  112. #[arg(long, default_value = "auto")]
  113. cluster: String,
  114. },
  115. /// Detailed tmux session status
  116. Status {
  117. #[arg(long, required = true)]
  118. recipe: String,
  119. #[arg(long, default_value = "auto")]
  120. cluster: String,
  121. },
  122. /// Show tmux session logs
  123. Logs {
  124. #[arg(long, required = true)]
  125. recipe: String,
  126. #[arg(long, action = clap::ArgAction::SetTrue)]
  127. follow: bool,
  128. #[arg(long, default_value = "auto")]
  129. cluster: String,
  130. },
  131. /// Attach to head node tmux session
  132. Attach {
  133. #[arg(long, required = true)]
  134. recipe: String,
  135. #[arg(long, default_value = "auto")]
  136. cluster: String,
  137. },
  138. }
  139. /// `sm121 repos` — the configured git recipe repos. `sm121 repos` (no
  140. /// subcommand) lists state; `sm121 repos sync` clones/pulls them now.
  141. #[derive(clap::Args)]
  142. pub struct ReposArgs {
  143. #[command(subcommand)]
  144. pub command: Option<ReposCommands>,
  145. }
  146. #[derive(Clone, clap::Subcommand)]
  147. pub enum ReposCommands {
  148. /// List the configured repos with their state (cloned? archived?
  149. /// last-pull ts? recipe count?)
  150. List,
  151. /// Clone/pull the configured recipe repos now (`--force` re-clones
  152. /// each cached checkout from scratch). `--watch` keeps re-syncing in
  153. /// the background (every `--interval` minutes) so the cache never goes
  154. /// stale between commands — run it detached (nohup/launchd) the way the
  155. /// HA add-on's entrypoint loop does.
  156. Sync {
  157. #[arg(long)]
  158. force: bool,
  159. /// Re-sync continuously (background mode; Ctrl-C to stop)
  160. #[arg(long)]
  161. watch: bool,
  162. /// Re-sync interval in minutes (with --watch; default 10)
  163. #[arg(long, default_value_t = 10)]
  164. interval: u32,
  165. },
  166. }
  167. #[derive(Args)]
  168. pub struct SyncImageArgs {
  169. #[arg(long, required = true)]
  170. pub recipe: String,
  171. #[arg(long, default_value = "auto")]
  172. pub cluster: String,
  173. /// Explicit source node (default: newest image present in the set).
  174. #[arg(long)]
  175. pub source: Option<String>,
  176. }