wasmer_cli/commands/app/secrets/
export.rs

1use super::utils;
2use crate::{
3    commands::{AsyncCliCommand, app::util::AppIdentFlag},
4    config::WasmerEnv,
5};
6use std::io::IsTerminal as _;
7use std::path::PathBuf;
8
9#[derive(clap::Parser, Debug, Clone, Copy, PartialEq, Eq, Default, clap::ValueEnum)]
10pub enum SecretExportFormat {
11    #[default]
12    #[clap(name = "env")]
13    Env,
14    #[clap(name = "json")]
15    Json,
16    #[clap(name = "yaml")]
17    Yaml,
18}
19
20/// Export app secrets to a file or stdout.
21#[derive(clap::Parser, Debug)]
22pub struct CmdAppSecretsExport {
23    #[clap(flatten)]
24    pub env: WasmerEnv,
25
26    #[clap(long)]
27    pub quiet: bool,
28
29    #[clap(long, default_value_t = !std::io::stdin().is_terminal())]
30    pub non_interactive: bool,
31
32    #[clap(flatten)]
33    pub app_id: AppIdentFlag,
34
35    #[clap(long = "app-dir", conflicts_with = "app")]
36    pub app_dir_path: Option<PathBuf>,
37
38    #[clap(short = 'f', long, default_value = "env")]
39    pub format: SecretExportFormat,
40
41    #[clap(short = 'o', long)]
42    pub output: Option<PathBuf>,
43}
44
45#[async_trait::async_trait]
46impl AsyncCliCommand for CmdAppSecretsExport {
47    type Output = ();
48
49    async fn run_async(self) -> Result<Self::Output, anyhow::Error> {
50        let client = self.env.client()?;
51        let app_id = super::utils::get_app_id(
52            &client,
53            self.app_id.app.as_ref(),
54            self.app_dir_path.as_ref(),
55            self.quiet,
56            self.non_interactive,
57        )
58        .await?;
59
60        if !self.quiet {
61            eprintln!("Exporting secrets for app {app_id}...");
62        }
63
64        let secrets: Vec<utils::Secret> = utils::reveal_secrets(&client, &app_id).await?;
65
66        let output = match self.format {
67            SecretExportFormat::Env => {
68                let mut lines = Vec::new();
69                for secret in &secrets {
70                    lines.push(format!(
71                        "{}=\"{}\"",
72                        secret.name,
73                        utils::render::sanitize_value(&secret.value)
74                    ));
75                }
76                lines.join("\n")
77            }
78            SecretExportFormat::Json => serde_json::to_string_pretty(&secrets)?,
79            SecretExportFormat::Yaml => serde_yaml::to_string(&secrets)?,
80        };
81
82        if let Some(path) = &self.output {
83            std::fs::write(path, output)?;
84            if !self.quiet {
85                eprintln!("Secrets exported to {}", path.display());
86            }
87        } else {
88            println!("{output}");
89        }
90
91        Ok(())
92    }
93}