wasmer_cli/commands/app/volumes/credentials/
mod.rs

1pub(super) mod rotate_secrets;
2
3use crate::{
4    commands::{AsyncCliCommand, app::util::AppIdentOpts},
5    config::WasmerEnv,
6};
7
8/// Retrieve access credentials for the volumes of an app.
9///
10/// The credentials can be used to access volumes with any S3 client, for example rclone. Note:
11/// using --format=rclone - which is the default - will output an rclone configuration snippet.
12#[derive(clap::Parser, Debug)]
13pub struct CmdAppVolumesCredentials {
14    #[clap(flatten)]
15    pub env: WasmerEnv,
16
17    #[clap(flatten)]
18    pub fmt: ItemFormatOpts,
19
20    #[clap(flatten)]
21    pub ident: AppIdentOpts,
22}
23
24#[async_trait::async_trait]
25impl AsyncCliCommand for CmdAppVolumesCredentials {
26    type Output = ();
27
28    async fn run_async(self) -> Result<Self::Output, anyhow::Error> {
29        let client = self.env.client()?;
30        let (_ident, app) = self.ident.load_app(&client).await?;
31
32        let creds =
33            wasmer_backend_api::query::get_app_s3_credentials(&client, app.id.clone().into_inner())
34                .await?;
35
36        match self.fmt.format {
37            CredsItemFormat::Rclone => {
38                let rclone_config = format!(
39                    r#"
40[edge-{app_name}]
41# rclone configuration for volumes of {app_name}
42type = s3
43provider = Other
44acl = private
45access_key_id = {access_key}
46secret_access_key = {secret_key}
47endpoint = {endpoint}
48
49"#,
50                    app_name = app.name,
51                    access_key = creds.access_key,
52                    secret_key = creds.secret_key,
53                    endpoint = creds.endpoint,
54                );
55                println!("{rclone_config}");
56            }
57            CredsItemFormat::Json => {
58                let value = serde_json::json!({
59                    "app_name": app.name,
60                    "access_key": creds.access_key,
61                    "secret_key": creds.secret_key,
62                    "endpoint": creds.endpoint,
63                });
64
65                println!("{}", serde_json::to_string_pretty(&value).unwrap());
66            }
67            CredsItemFormat::Yaml => {
68                let config = format!(
69                    r#"
70app_name: {app_name}
71access_key: {access_key}
72secret_key: {secret_key}
73endpoint: {endpoint}
74"#,
75                    app_name = app.name,
76                    access_key = creds.access_key,
77                    secret_key = creds.secret_key,
78                    endpoint = creds.endpoint,
79                );
80                println!("{config}");
81            }
82
83            CredsItemFormat::Table => {
84                let mut table = comfy_table::Table::new();
85                table.add_row(vec!["App name", "Access key", "Secret key", "Endpoint"]);
86                table.add_row(vec![
87                    app.name,
88                    creds.access_key,
89                    creds.secret_key,
90                    creds.endpoint,
91                ]);
92
93                println!("{table}");
94            }
95        }
96
97        Ok(())
98    }
99}
100
101/*
102 * The following is a copy of [`crate::opts::ItemFormatOpts`] with an
103 * additional formatting - rclone - that only makes sense in this context.
104 */
105
106/// The possibile formats to output the credentials in.
107#[derive(Clone, Copy, Debug, PartialEq, Eq, clap::ValueEnum)]
108pub enum CredsItemFormat {
109    Json,
110    Yaml,
111    Table,
112    Rclone,
113}
114
115/// Formatting options for credentials.
116#[derive(clap::Parser, Debug)]
117pub struct ItemFormatOpts {
118    /// Output format
119    #[clap(short = 'f', long, default_value = "rclone")]
120    pub format: CredsItemFormat,
121}