wasmer_cli/commands/app/secrets/
reveal.rs1use super::utils;
2use crate::{
3 commands::{AsyncCliCommand, app::util::AppIdentFlag},
4 config::WasmerEnv,
5 opts::ListFormatOpts,
6 utils::render::{ItemFormat, ListFormat},
7};
8use dialoguer::theme::ColorfulTheme;
9use is_terminal::IsTerminal;
10use std::path::PathBuf;
11
12#[derive(clap::Parser, Debug)]
14pub struct CmdAppSecretsReveal {
15 #[clap(flatten)]
17 pub env: WasmerEnv,
18
19 #[clap(long)]
21 pub quiet: bool,
22
23 #[clap(long, default_value_t = !std::io::stdin().is_terminal())]
25 pub non_interactive: bool,
26
27 #[clap(flatten)]
28 pub fmt: Option<ListFormatOpts>,
29
30 #[clap(flatten)]
32 pub app_id: AppIdentFlag,
33
34 #[clap(long = "app-dir", conflicts_with = "app")]
36 pub app_dir_path: Option<PathBuf>,
37
38 #[clap(long, conflicts_with = "name")]
40 pub all: bool,
41
42 #[clap(name = "name")]
45 pub secret_name: Option<String>,
46}
47
48impl CmdAppSecretsReveal {
49 fn get_secret_name(&self) -> anyhow::Result<String> {
50 if let Some(name) = &self.secret_name {
51 return Ok(name.clone());
52 }
53
54 if self.non_interactive {
55 anyhow::bail!("No secret name given. Provide one as a positional argument.")
56 } else {
57 let theme = ColorfulTheme::default();
58 Ok(dialoguer::Input::with_theme(&theme)
59 .with_prompt("Enter the name of the secret:")
60 .interact_text()?)
61 }
62 }
63}
64
65#[async_trait::async_trait]
66impl AsyncCliCommand for CmdAppSecretsReveal {
67 type Output = ();
68
69 async fn run_async(self) -> Result<Self::Output, anyhow::Error> {
70 let client = self.env.client()?;
71 let app_id = super::utils::get_app_id(
72 &client,
73 self.app_id.app.as_ref(),
74 self.app_dir_path.as_ref(),
75 self.quiet,
76 self.non_interactive,
77 )
78 .await?;
79
80 if !self.all {
81 let name = self.get_secret_name()?;
82
83 let value = utils::get_secret_value_by_name(&client, &app_id, &name).await?;
84
85 let secret = utils::Secret { name, value };
86
87 if let Some(fmt) = &self.fmt {
88 let fmt = match fmt.format {
89 ListFormat::Json => ItemFormat::Json,
90 ListFormat::Yaml => ItemFormat::Yaml,
91 ListFormat::Table => ItemFormat::Table,
92 ListFormat::ItemTable => {
93 anyhow::bail!("The 'item-table' format is not available for single values.")
94 }
95 };
96 println!("{}", fmt.render(&secret));
97 } else {
98 print!("{}", secret.value);
99 }
100 } else {
101 let secrets: Vec<utils::Secret> = utils::reveal_secrets(&client, &app_id).await?;
102
103 if let Some(fmt) = &self.fmt {
104 println!("{}", fmt.format.render(secrets.as_slice()));
105 } else {
106 for secret in secrets {
107 println!(
108 "{}=\"{}\"",
109 secret.name,
110 utils::render::sanitize_value(&secret.value)
111 );
112 }
113 }
114 }
115
116 Ok(())
117 }
118}