From 21bfed9ed7d652dbe99644b1719be5da4e88f6fc Mon Sep 17 00:00:00 2001 From: Simon Popugaev Date: Mon, 22 Jan 2024 19:07:13 +0300 Subject: [PATCH] 1244 oss client --- Cargo.lock | 23 +-- Cargo.toml | 5 +- README.md | 4 +- src/account.rs | 143 --------------- src/auth.rs | 185 ------------------- src/clients.rs | 57 ------ src/clients/account.rs | 49 ----- src/clients/errors.rs | 151 --------------- src/clients/gateway.rs | 6 - src/clients/gateway/certificate.rs | 52 ------ src/clients/gateway/definition.rs | 50 ----- src/clients/gateway/deployment.rs | 53 ------ src/clients/gateway/domain.rs | 49 ----- src/clients/gateway/errors.rs | 115 ------------ src/clients/gateway/healthcheck.rs | 22 --- src/clients/grant.rs | 76 -------- src/clients/login.rs | 50 ----- src/clients/policy.rs | 50 ----- src/clients/project.rs | 103 ----------- src/clients/project_grant.rs | 68 ------- src/clients/template.rs | 38 +--- src/clients/token.rs | 58 ------ src/gateway.rs | 145 --------------- src/gateway/certificate.rs | 129 ------------- src/gateway/definition.rs | 127 ------------- src/gateway/deployment.rs | 101 ---------- src/gateway/domain.rs | 77 -------- src/gateway/healthcheck.rs | 22 --- src/main.rs | 198 +------------------- src/model.rs | 285 +---------------------------- src/policy.rs | 57 ------ src/project.rs | 80 -------- src/project_grant.rs | 64 ------- src/template.rs | 51 +----- src/token.rs | 75 -------- 35 files changed, 41 insertions(+), 2777 deletions(-) delete mode 100644 src/account.rs delete mode 100644 src/auth.rs delete mode 100644 src/clients/account.rs delete mode 100644 src/clients/gateway.rs delete mode 100644 src/clients/gateway/certificate.rs delete mode 100644 src/clients/gateway/definition.rs delete mode 100644 src/clients/gateway/deployment.rs delete mode 100644 src/clients/gateway/domain.rs delete mode 100644 src/clients/gateway/errors.rs delete mode 100644 src/clients/gateway/healthcheck.rs delete mode 100644 src/clients/grant.rs delete mode 100644 src/clients/login.rs delete mode 100644 src/clients/policy.rs delete mode 100644 src/clients/project.rs delete mode 100644 src/clients/project_grant.rs delete mode 100644 src/clients/token.rs delete mode 100644 src/gateway.rs delete mode 100644 src/gateway/certificate.rs delete mode 100644 src/gateway/definition.rs delete mode 100644 src/gateway/deployment.rs delete mode 100644 src/gateway/domain.rs delete mode 100644 src/gateway/healthcheck.rs delete mode 100644 src/policy.rs delete mode 100644 src/project.rs delete mode 100644 src/project_grant.rs delete mode 100644 src/token.rs diff --git a/Cargo.lock b/Cargo.lock index 4811f96..141c1cb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -579,7 +579,6 @@ dependencies = [ "futures-util", "golem-client", "golem-examples", - "golem-gateway-client", "http 1.0.0", "indoc", "itertools", @@ -601,9 +600,9 @@ dependencies = [ [[package]] name = "golem-client" -version = "0.0.52" +version = "0.0.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "864ef2692b92b3657521a7a12d6540eacd764a9acd7e204786f43403965045ed" +checksum = "16bfded1bc6ac54bcf9f10bf9c5d3c2533d6479f08d219a57072153b09020ba7" dependencies = [ "async-trait", "bytes", @@ -634,24 +633,6 @@ dependencies = [ "strum_macros", ] -[[package]] -name = "golem-gateway-client" -version = "0.0.52" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72f744be873e4c0fcfb462526f74baa627d9f66e5ad7c8f5134f1c47a2abaa5a" -dependencies = [ - "async-trait", - "bytes", - "chrono", - "futures-core", - "http 1.0.0", - "reqwest", - "serde", - "serde_json", - "tracing", - "uuid", -] - [[package]] name = "h2" version = "0.3.22" diff --git a/Cargo.toml b/Cargo.toml index 11f8141..0760ca6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ license = "Apache-2.0" homepage = "https://www.golem.cloud/" authors = ["Simon Popugaev "] readme = "README.md" -description = "Command line interface for Golem Cloud" +description = "Command line interface for OSS version of Golem" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -17,8 +17,7 @@ clap = { version = "4.4.12", features = ["derive"] } clap-verbosity-flag = "2.1.1" derive_more = "0.99.17" futures-util = "0.3.30" -golem-client = "0.0.52" -golem-gateway-client = "0.0.52" +golem-client = "0.0.54" golem-examples = "0.1.10" http = "1.0.0" indoc = "2.0.4" diff --git a/README.md b/README.md index 00ec88d..c86efcb 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # golem-cli -Command line interface for [Golem Cloud](https://golem.cloud). +Command line interface for [Golem OSS](https://golem.cloud). + +For Golem Cloud version client see [Golem Cloud CLI](https://github.com/golemcloud/golem-cloud-cli). ## Installation diff --git a/src/account.rs b/src/account.rs deleted file mode 100644 index f10c73f..0000000 --- a/src/account.rs +++ /dev/null @@ -1,143 +0,0 @@ -use async_trait::async_trait; -use clap::Subcommand; -use golem_client::model::AccountData; - -use crate::clients::account::AccountClient; -use crate::clients::grant::GrantClient; -use crate::clients::CloudAuthentication; -use crate::model::{AccountId, GolemError, GolemResult, Role}; - -#[derive(Subcommand, Debug)] -#[command()] -pub enum AccountSubcommand { - #[command()] - Get {}, - - #[command()] - Update { - // TODO: validate non-empty - #[arg(short = 'n', long)] - account_name: Option, - - #[arg(short = 'e', long)] - account_email: Option, - }, - - #[command()] - Add { - #[arg(short = 'n', long)] - account_name: String, - - #[arg(short = 'e', long)] - account_email: String, - }, - - #[command()] - Delete {}, - - #[command()] - Grant { - #[command(subcommand)] - subcommand: GrantSubcommand, - }, -} - -#[derive(Subcommand, Debug)] -#[command()] -pub enum GrantSubcommand { - #[command()] - Get {}, - - #[command()] - Add { - #[arg(value_name = "ROLE")] - role: Role, - }, - - #[command()] - Delete { - #[arg(value_name = "ROLE")] - role: Role, - }, -} - -#[async_trait] -pub trait AccountHandler { - async fn handle( - &self, - token: &CloudAuthentication, - account_id: Option, - subcommand: AccountSubcommand, - ) -> Result; -} - -pub struct AccountHandlerLive { - pub client: C, - pub grant: G, -} - -#[async_trait] -impl AccountHandler - for AccountHandlerLive -{ - async fn handle( - &self, - auth: &CloudAuthentication, - account_id: Option, - subcommand: AccountSubcommand, - ) -> Result { - let account_id = account_id.unwrap_or(auth.account_id()); - - match subcommand { - AccountSubcommand::Get {} => { - let account = self.client.get(&account_id).await?; - Ok(GolemResult::Ok(Box::new(account))) - } - AccountSubcommand::Update { - account_name, - account_email, - } => { - let existing = self.client.get(&account_id).await?; - let name = account_name.unwrap_or(existing.name); - let email = account_email.unwrap_or(existing.email); - let updated = AccountData { name, email }; - let account = self.client.put(&account_id, updated).await?; - Ok(GolemResult::Ok(Box::new(account))) - } - AccountSubcommand::Add { - account_name, - account_email, - } => { - let data = AccountData { - name: account_name, - email: account_email, - }; - - let account = self.client.post(data).await?; - - Ok(GolemResult::Ok(Box::new(account))) - } - AccountSubcommand::Delete {} => { - self.client.delete(&account_id).await?; - Ok(GolemResult::Str("Deleted".to_string())) - } - AccountSubcommand::Grant { subcommand } => match subcommand { - GrantSubcommand::Get {} => { - let roles = self.grant.get_all(account_id).await?; - - Ok(GolemResult::Ok(Box::new(roles))) - } - GrantSubcommand::Add { role } => { - self.grant.put(account_id, role).await?; - - Ok(GolemResult::Ok(Box::new("RoleGranted".to_string()))) - } - GrantSubcommand::Delete { role } => { - self.grant.put(account_id, role).await?; - - Ok(GolemResult::Ok(Box::new("RoleRemoved".to_string()))) - } - }, - } - } -} diff --git a/src/auth.rs b/src/auth.rs deleted file mode 100644 index 57b79b5..0000000 --- a/src/auth.rs +++ /dev/null @@ -1,185 +0,0 @@ -use std::fs::{create_dir_all, File, OpenOptions}; -use std::io::{BufReader, BufWriter}; -use std::path::{Path, PathBuf}; - -use async_trait::async_trait; -use chrono::{DateTime, Utc}; -use golem_client::model::OAuth2Data; -use golem_client::model::Token; -use golem_client::model::TokenSecret; -use golem_client::model::UnsafeToken; -use indoc::printdoc; -use serde::{Deserialize, Serialize}; -use tracing::info; -use uuid::Uuid; - -use crate::clients::login::LoginClient; -use crate::clients::CloudAuthentication; -use crate::model::GolemError; - -#[async_trait] -pub trait Auth { - async fn authenticate( - &self, - manual_token: Option, - config_dir: PathBuf, - ) -> Result; -} - -#[derive(Clone, PartialEq, Eq)] -pub struct AuthLive { - pub login: L, -} - -#[derive(Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -struct CloudAuthenticationConfig { - data: CloudAuthenticationConfigData, - secret: Uuid, -} - -#[derive(Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -struct CloudAuthenticationConfigData { - id: Uuid, - account_id: String, - created_at: DateTime, - expires_at: DateTime, -} - -impl AuthLive { - fn read_from_file(&self, config_dir: &Path) -> Option { - let file = File::open(self.config_path(config_dir)).ok()?; // TODO log - - let reader = BufReader::new(file); - - let parsed: serde_json::Result = serde_json::from_reader(reader); - - match parsed { - Ok(conf) => Some(CloudAuthentication(UnsafeToken { - data: Token { - id: conf.data.id, - account_id: conf.data.account_id, - created_at: conf.data.created_at, - expires_at: conf.data.expires_at, - }, - secret: TokenSecret { value: conf.secret }, - })), - Err(err) => { - info!("Parsing failed: {err}"); // TODO configure - None - } - } - } - - fn config_path(&self, config_dir: &Path) -> PathBuf { - config_dir.join("cloud_authentication.json") - } - - fn store_file(&self, token: &UnsafeToken, config_dir: &Path) { - match create_dir_all(config_dir) { - Ok(_) => {} - Err(err) => { - info!("Can't create config directory: {err}"); - } - } - let file_res = OpenOptions::new() - .read(true) - .write(true) - .create(true) - .open(self.config_path(config_dir)); - let file = match file_res { - Ok(file) => file, - Err(err) => { - info!("Can't open file: {err}"); - return; - } - }; - let writer = BufWriter::new(file); - let data = CloudAuthenticationConfig { - data: CloudAuthenticationConfigData { - id: token.data.id, - account_id: token.data.account_id.clone(), - created_at: token.data.created_at, - expires_at: token.data.expires_at, - }, - secret: token.secret.value, - }; - let res = serde_json::to_writer_pretty(writer, &data); - - if let Err(err) = res { - info!("File sawing error: {err}"); - } - } - - async fn oauth2(&self, config_dir: &Path) -> Result { - let data = self.login.start_oauth2().await?; - inform_user(&data); - let token = self.login.complete_oauth2(data.encoded_session).await?; - self.store_file(&token, config_dir); - Ok(CloudAuthentication(token)) - } - - async fn config_authentication( - &self, - config_dir: PathBuf, - ) -> Result { - if let Some(data) = self.read_from_file(&config_dir) { - Ok(data) - } else { - self.oauth2(&config_dir).await - } - } -} - -fn inform_user(data: &OAuth2Data) { - let box_url_line = String::from_utf8(vec![b'-'; data.url.len() + 2]).unwrap(); - let box_code_line = String::from_utf8(vec![b'-'; data.user_code.len() + 2]).unwrap(); - let expires: DateTime = data.expires; - let expires_in = expires.signed_duration_since(Utc::now()).num_minutes(); - let expires_at = expires.format("%T"); - let url = &data.url; - let user_code = &data.user_code; - - printdoc! {" - >> - >> Application requests to perform OAuth2 - >> authorization. - >> - >> Visit following URL in a browser: - >> - >> ┏{box_url_line}┓ - >> ┃ {url} ┃ - >> ┗{box_url_line}┛ - >> - >> And enter following code: - >> - >> ┏{box_code_line}┓ - >> ┃ {user_code} ┃ - >> ┗{box_code_line}┛ - >> - >> Code will expire in {expires_in} minutes at {expires_at}. - >> - Waiting... - "}; -} - -#[async_trait] -impl Auth for AuthLive { - async fn authenticate( - &self, - manual_token: Option, - config_dir: PathBuf, - ) -> Result { - if let Some(manual_token) = manual_token { - let secret = TokenSecret { - value: manual_token, - }; - let data = self.login.token_details(secret.clone()).await?; - - Ok(CloudAuthentication(UnsafeToken { data, secret })) - } else { - self.config_authentication(config_dir).await - } - } -} diff --git a/src/clients.rs b/src/clients.rs index a4bccf8..51c9157 100644 --- a/src/clients.rs +++ b/src/clients.rs @@ -1,60 +1,3 @@ -use crate::model::{AccountId, ProjectAction}; -use golem_client::model::TokenSecret; -use golem_client::model::UnsafeToken; - -pub mod account; pub mod errors; -pub mod gateway; -pub mod grant; -pub mod login; -pub mod policy; -pub mod project; -pub mod project_grant; pub mod template; -pub mod token; pub mod worker; - -pub fn token_header(secret: &TokenSecret) -> String { - format!("bearer {}", secret.value) -} - -#[derive(Clone, PartialEq, Debug)] -pub struct CloudAuthentication(pub UnsafeToken); - -impl CloudAuthentication { - pub fn header(&self) -> String { - let CloudAuthentication(value) = self; - - token_header(&value.secret) - } - - pub fn account_id(&self) -> AccountId { - let CloudAuthentication(value) = self; - - AccountId { - id: value.data.account_id.clone(), - } - } -} - -pub fn action_cli_to_api(action: ProjectAction) -> golem_client::model::ProjectAction { - match action { - ProjectAction::ViewTemplate => golem_client::model::ProjectAction::ViewTemplate {}, - ProjectAction::CreateTemplate => golem_client::model::ProjectAction::CreateTemplate {}, - ProjectAction::UpdateTemplate => golem_client::model::ProjectAction::UpdateTemplate {}, - ProjectAction::DeleteTemplate => golem_client::model::ProjectAction::DeleteTemplate {}, - ProjectAction::ViewWorker => golem_client::model::ProjectAction::ViewWorker {}, - ProjectAction::CreateWorker => golem_client::model::ProjectAction::CreateWorker {}, - ProjectAction::UpdateWorker => golem_client::model::ProjectAction::UpdateWorker {}, - ProjectAction::DeleteWorker => golem_client::model::ProjectAction::DeleteWorker {}, - ProjectAction::ViewProjectGrants => { - golem_client::model::ProjectAction::ViewProjectGrants {} - } - ProjectAction::CreateProjectGrants => { - golem_client::model::ProjectAction::CreateProjectGrants {} - } - ProjectAction::DeleteProjectGrants => { - golem_client::model::ProjectAction::DeleteProjectGrants {} - } - } -} diff --git a/src/clients/account.rs b/src/clients/account.rs deleted file mode 100644 index c090c73..0000000 --- a/src/clients/account.rs +++ /dev/null @@ -1,49 +0,0 @@ -use async_trait::async_trait; -use golem_client::model::Account; -use golem_client::model::AccountData; -use golem_client::model::Plan; -use tracing::info; - -use crate::model::{AccountId, GolemError}; - -#[async_trait] -pub trait AccountClient { - async fn get(&self, id: &AccountId) -> Result; - async fn get_plan(&self, id: &AccountId) -> Result; - async fn put(&self, id: &AccountId, data: AccountData) -> Result; - async fn post(&self, data: AccountData) -> Result; - async fn delete(&self, id: &AccountId) -> Result<(), GolemError>; -} - -pub struct AccountClientLive { - pub client: C, -} - -#[async_trait] -impl AccountClient for AccountClientLive { - async fn get(&self, id: &AccountId) -> Result { - info!("Getting account {id}"); - Ok(self.client.account_id_get(&id.id).await?) - } - - async fn get_plan(&self, id: &AccountId) -> Result { - info!("Getting account plan of {id}."); - Ok(self.client.account_id_plan_get(&id.id).await?) - } - - async fn put(&self, id: &AccountId, data: AccountData) -> Result { - info!("Updating account {id}."); - Ok(self.client.account_id_put(&id.id, &data).await?) - } - - async fn post(&self, data: AccountData) -> Result { - info!("Creating account."); - Ok(self.client.post(&data).await?) - } - - async fn delete(&self, id: &AccountId) -> Result<(), GolemError> { - info!("Deleting account {id}."); - let _ = self.client.account_id_delete(&id.id).await?; - Ok(()) - } -} diff --git a/src/clients/errors.rs b/src/clients/errors.rs index 6423a5c..3d24f9d 100644 --- a/src/clients/errors.rs +++ b/src/clients/errors.rs @@ -1,136 +1,10 @@ -use golem_client::api::AccountError; -use golem_client::api::GrantError; -use golem_client::api::LoginError; -use golem_client::api::ProjectError; -use golem_client::api::ProjectGrantError; -use golem_client::api::ProjectPolicyError; use golem_client::api::TemplateError; -use golem_client::api::TokenError; use golem_client::api::WorkerError; pub trait ResponseContentErrorMapper { fn map(self) -> String; } -impl ResponseContentErrorMapper for AccountError { - fn map(self) -> String { - match self { - AccountError::Error400(errors) => { - format!("BadRequest: {errors:?}") - } - AccountError::Error401(error) => { - format!("Unauthorized: {error:?}") - } - AccountError::Error404(error) => { - format!("NotFound: {error:?}") - } - AccountError::Error500(error) => { - format!("InternalError: {error:?}") - } - } - } -} - -impl ResponseContentErrorMapper for GrantError { - fn map(self) -> String { - match self { - GrantError::Error400(errors) => { - format!("BadRequest: {errors:?}") - } - GrantError::Error401(error) => { - format!("Unauthorized: {error:?}") - } - GrantError::Error404(error) => { - format!("NotFound: {error:?}") - } - GrantError::Error500(error) => { - format!("InternalError: {error:?}") - } - } - } -} - -impl ResponseContentErrorMapper for LoginError { - fn map(self) -> String { - match self { - LoginError::Error400(errors) => { - format!("BadRequest: {errors:?}") - } - LoginError::Error401(error) => { - format!("Unauthorized: {error:?}") - } - LoginError::Error500(error) => { - format!("InternalError: {error:?}") - } - } - } -} - -impl ResponseContentErrorMapper for ProjectError { - fn map(self) -> String { - match self { - ProjectError::Error400(errors) => { - format!("BadRequest: {errors:?}") - } - ProjectError::Error401(error) => { - format!("Unauthorized: {error:?}") - } - ProjectError::Error403(error) => { - format!("Forbidden: {error:?}") - } - ProjectError::Error404(error) => { - format!("NotFound: {error:?}") - } - ProjectError::Error500(error) => { - format!("InternalError: {error:?}") - } - } - } -} - -impl ResponseContentErrorMapper for ProjectGrantError { - fn map(self) -> String { - match self { - ProjectGrantError::Error400(errors) => { - format!("BadRequest: {errors:?}") - } - ProjectGrantError::Error401(error) => { - format!("Unauthorized: {error:?}") - } - ProjectGrantError::Error403(error) => { - format!("Forbidden: {error:?}") - } - ProjectGrantError::Error404(error) => { - format!("NotFound: {error:?}") - } - ProjectGrantError::Error500(error) => { - format!("InternalError: {error:?}") - } - } - } -} - -#[allow(unreachable_patterns)] -impl ResponseContentErrorMapper for ProjectPolicyError { - fn map(self) -> String { - match self { - ProjectPolicyError::Error400(errors) => { - format!("BadRequest: {errors:?}") - } - ProjectPolicyError::Error401(error) => { - format!("Unauthorized: {error:?}") - } - ProjectPolicyError::Error404(error) => { - format!("NotFound: {error:?}") - } - ProjectPolicyError::Error500(error) => { - format!("InternalError: {error:?}") - } - _ => "UnknownError".into(), - } - } -} - impl ResponseContentErrorMapper for TemplateError { fn map(self) -> String { match self { @@ -156,37 +30,12 @@ impl ResponseContentErrorMapper for TemplateError { } } -impl ResponseContentErrorMapper for TokenError { - fn map(self) -> String { - match self { - TokenError::Error400(errors) => { - format!("BadRequest: {errors:?}") - } - TokenError::Error401(error) => { - format!("Unauthorized: {error:?}") - } - TokenError::Error404(error) => { - format!("NotFound: {error:?}") - } - TokenError::Error500(error) => { - format!("InternalError: {error:?}") - } - } - } -} - impl ResponseContentErrorMapper for WorkerError { fn map(self) -> String { match self { WorkerError::Error400(errors) => { format!("BadRequest: {errors:?}") } - WorkerError::Error401(error) => { - format!("Unauthorized: {error:?}") - } - WorkerError::Error403(error) => { - format!("Forbidden: {error:?}") - } WorkerError::Error404(error) => { format!("NotFound: {error:?}") } diff --git a/src/clients/gateway.rs b/src/clients/gateway.rs deleted file mode 100644 index b2e5c05..0000000 --- a/src/clients/gateway.rs +++ /dev/null @@ -1,6 +0,0 @@ -pub mod certificate; -pub mod definition; -pub mod deployment; -pub mod domain; -pub mod errors; -pub mod healthcheck; diff --git a/src/clients/gateway/certificate.rs b/src/clients/gateway/certificate.rs deleted file mode 100644 index 8aa30b6..0000000 --- a/src/clients/gateway/certificate.rs +++ /dev/null @@ -1,52 +0,0 @@ -use async_trait::async_trait; -use golem_gateway_client::model::Certificate; -use golem_gateway_client::model::CertificateRequest; -use uuid::Uuid; - -use crate::model::{GolemError, ProjectId}; - -#[async_trait] -pub trait CertificateClient { - async fn get( - &self, - project_id: ProjectId, - certificate_id: Option<&Uuid>, - ) -> Result, GolemError>; - - async fn create(&self, certificate: CertificateRequest) -> Result; - - async fn delete( - &self, - project_id: ProjectId, - certificate_id: &Uuid, - ) -> Result; -} - -pub struct CertificateClientLive { - pub client: C, -} - -#[async_trait] -impl CertificateClient - for CertificateClientLive -{ - async fn get( - &self, - project_id: ProjectId, - certificate_id: Option<&Uuid>, - ) -> Result, GolemError> { - Ok(self.client.get(&project_id.0, certificate_id).await?) - } - - async fn create(&self, certificate: CertificateRequest) -> Result { - Ok(self.client.post(&certificate).await?) - } - - async fn delete( - &self, - project_id: ProjectId, - certificate_id: &Uuid, - ) -> Result { - Ok(self.client.delete(&project_id.0, certificate_id).await?) - } -} diff --git a/src/clients/gateway/definition.rs b/src/clients/gateway/definition.rs deleted file mode 100644 index 916f548..0000000 --- a/src/clients/gateway/definition.rs +++ /dev/null @@ -1,50 +0,0 @@ -use async_trait::async_trait; -use golem_gateway_client::model::ApiDefinition; - -use crate::model::{GolemError, ProjectId}; - -#[async_trait] -pub trait DefinitionClient { - async fn get( - &self, - project_id: ProjectId, - api_definition_id: Option<&str>, - ) -> Result, GolemError>; - - async fn update(&self, api_definition: ApiDefinition) -> Result; - - async fn delete( - &self, - project_id: ProjectId, - api_definition_id: &str, - ) -> Result; -} - -pub struct DefinitionClientLive { - pub client: C, -} - -#[async_trait] -impl DefinitionClient - for DefinitionClientLive -{ - async fn get( - &self, - project_id: ProjectId, - api_definition_id: Option<&str>, - ) -> Result, GolemError> { - Ok(self.client.get(&project_id.0, api_definition_id).await?) - } - - async fn update(&self, api_definition: ApiDefinition) -> Result { - Ok(self.client.put(&api_definition).await?) - } - - async fn delete( - &self, - project_id: ProjectId, - api_definition_id: &str, - ) -> Result { - Ok(self.client.delete(&project_id.0, api_definition_id).await?) - } -} diff --git a/src/clients/gateway/deployment.rs b/src/clients/gateway/deployment.rs deleted file mode 100644 index b1f3947..0000000 --- a/src/clients/gateway/deployment.rs +++ /dev/null @@ -1,53 +0,0 @@ -use async_trait::async_trait; -use golem_gateway_client::model::ApiDeployment; - -use crate::model::{GolemError, ProjectId}; - -#[async_trait] -pub trait DeploymentClient { - async fn get( - &self, - project_id: ProjectId, - api_definition_id: &str, - ) -> Result, GolemError>; - async fn update(&self, api_deployment: ApiDeployment) -> Result; - async fn delete( - &self, - project_id: ProjectId, - api_definition_id: &str, - site: &str, - ) -> Result; -} - -pub struct DeploymentClientLive { - pub client: C, -} - -#[async_trait] -impl DeploymentClient - for DeploymentClientLive -{ - async fn get( - &self, - project_id: ProjectId, - api_definition_id: &str, - ) -> Result, GolemError> { - Ok(self.client.get(&project_id.0, api_definition_id).await?) - } - - async fn update(&self, api_deployment: ApiDeployment) -> Result { - Ok(self.client.put(&api_deployment).await?) - } - - async fn delete( - &self, - project_id: ProjectId, - api_definition_id: &str, - site: &str, - ) -> Result { - Ok(self - .client - .delete(&project_id.0, api_definition_id, site) - .await?) - } -} diff --git a/src/clients/gateway/domain.rs b/src/clients/gateway/domain.rs deleted file mode 100644 index d29c9f4..0000000 --- a/src/clients/gateway/domain.rs +++ /dev/null @@ -1,49 +0,0 @@ -use async_trait::async_trait; -use golem_gateway_client::model::ApiDomain; -use golem_gateway_client::model::DomainRequest; - -use crate::model::{GolemError, ProjectId}; - -#[async_trait] -pub trait DomainClient { - async fn get(&self, project_id: ProjectId) -> Result, GolemError>; - - async fn update( - &self, - project_id: ProjectId, - domain_name: String, - ) -> Result; - - async fn delete(&self, project_id: ProjectId, domain_name: &str) -> Result; -} - -pub struct DomainClientLive { - pub client: C, -} - -#[async_trait] -impl DomainClient - for DomainClientLive -{ - async fn get(&self, project_id: ProjectId) -> Result, GolemError> { - Ok(self.client.get(&project_id.0).await?) - } - - async fn update( - &self, - project_id: ProjectId, - domain_name: String, - ) -> Result { - Ok(self - .client - .put(&DomainRequest { - project_id: project_id.0, - domain_name, - }) - .await?) - } - - async fn delete(&self, project_id: ProjectId, domain_name: &str) -> Result { - Ok(self.client.delete(&project_id.0, domain_name).await?) - } -} diff --git a/src/clients/gateway/errors.rs b/src/clients/gateway/errors.rs deleted file mode 100644 index 465534d..0000000 --- a/src/clients/gateway/errors.rs +++ /dev/null @@ -1,115 +0,0 @@ -use golem_gateway_client::api::ApiCertificateError; -use golem_gateway_client::api::ApiDefinitionError; -use golem_gateway_client::api::ApiDeploymentError; -use golem_gateway_client::api::ApiDomainError; -use golem_gateway_client::api::HealthcheckError; - -pub trait ResponseContentErrorMapper { - fn map(self) -> String; -} - -impl ResponseContentErrorMapper for ApiCertificateError { - fn map(self) -> String { - match self { - ApiCertificateError::Error400(errors) => { - format!("BadRequest: {errors:?}") - } - ApiCertificateError::Error401(error) => { - format!("Unauthorized: {error:?}") - } - ApiCertificateError::Error403(error) => { - format!("LimitExceeded: {error:?}") - } - ApiCertificateError::Error404(message) => { - format!("NotFound: {message:?}") - } - ApiCertificateError::Error409(string) => { - format!("AlreadyExists: {string:?}") - } - ApiCertificateError::Error500(error) => { - format!("InternalError: {error:?}") - } - } - } -} - -impl ResponseContentErrorMapper for ApiDefinitionError { - fn map(self) -> String { - match self { - ApiDefinitionError::Error400(errors) => { - format!("BadRequest: {errors:?}") - } - ApiDefinitionError::Error401(error) => { - format!("Unauthorized: {error:?}") - } - ApiDefinitionError::Error403(error) => { - format!("LimitExceeded: {error:?}") - } - ApiDefinitionError::Error404(message) => { - format!("NotFound: {message:?}") - } - ApiDefinitionError::Error409(string) => { - format!("AlreadyExists: {string:?}") - } - ApiDefinitionError::Error500(error) => { - format!("InternalError: {error:?}") - } - } - } -} - -impl ResponseContentErrorMapper for ApiDeploymentError { - fn map(self) -> String { - match self { - ApiDeploymentError::Error400(errors) => { - format!("BadRequest: {errors:?}") - } - ApiDeploymentError::Error401(error) => { - format!("Unauthorized: {error:?}") - } - ApiDeploymentError::Error403(error) => { - format!("LimitExceeded: {error:?}") - } - ApiDeploymentError::Error404(message) => { - format!("NotFound: {message:?}") - } - ApiDeploymentError::Error409(string) => { - format!("AlreadyExists: {string:?}") - } - ApiDeploymentError::Error500(error) => { - format!("InternalError: {error:?}") - } - } - } -} - -impl ResponseContentErrorMapper for ApiDomainError { - fn map(self) -> String { - match self { - ApiDomainError::Error400(errors) => { - format!("BadRequest: {errors:?}") - } - ApiDomainError::Error401(error) => { - format!("Unauthorized: {error:?}") - } - ApiDomainError::Error403(error) => { - format!("LimitExceeded: {error:?}") - } - ApiDomainError::Error404(message) => { - format!("NotFound: {message:?}") - } - ApiDomainError::Error409(string) => { - format!("AlreadyExists: {string:?}") - } - ApiDomainError::Error500(error) => { - format!("InternalError: {error:?}") - } - } - } -} - -impl ResponseContentErrorMapper for HealthcheckError { - fn map(self) -> String { - match self {} - } -} diff --git a/src/clients/gateway/healthcheck.rs b/src/clients/gateway/healthcheck.rs deleted file mode 100644 index fc10e2a..0000000 --- a/src/clients/gateway/healthcheck.rs +++ /dev/null @@ -1,22 +0,0 @@ -use async_trait::async_trait; - -use crate::model::GolemError; - -#[async_trait] -pub trait HealthcheckClient { - async fn healthcheck(&self) -> Result<(), GolemError>; -} - -pub struct HealthcheckClientLive { - pub client: C, -} - -#[async_trait] -impl HealthcheckClient - for HealthcheckClientLive -{ - async fn healthcheck(&self) -> Result<(), GolemError> { - self.client.healthcheck_get().await?; - Ok(()) - } -} diff --git a/src/clients/grant.rs b/src/clients/grant.rs deleted file mode 100644 index b360af8..0000000 --- a/src/clients/grant.rs +++ /dev/null @@ -1,76 +0,0 @@ -use async_trait::async_trait; -use tracing::info; - -use crate::model::{AccountId, GolemError, Role}; - -#[async_trait] -pub trait GrantClient { - async fn get_all(&self, account_id: AccountId) -> Result, GolemError>; - async fn get(&self, account_id: AccountId, role: Role) -> Result; - async fn put(&self, account_id: AccountId, role: Role) -> Result<(), GolemError>; - async fn delete(&self, account_id: AccountId, role: Role) -> Result<(), GolemError>; -} - -pub struct GrantClientLive { - pub client: C, -} - -#[async_trait] -impl GrantClient for GrantClientLive { - async fn get_all(&self, account_id: AccountId) -> Result, GolemError> { - info!("Getting account roles."); - - let roles = self.client.get(&account_id.id).await?; - - Ok(roles.into_iter().map(api_to_cli).collect()) - } - - async fn get(&self, account_id: AccountId, role: Role) -> Result { - info!("Getting account role."); - let role = cli_to_api(role); - - Ok(api_to_cli( - self.client.role_get(&account_id.id, &role).await?, - )) - } - - async fn put(&self, account_id: AccountId, role: Role) -> Result<(), GolemError> { - info!("Adding account role."); - let role = cli_to_api(role); - - let _ = self.client.role_put(&account_id.id, &role).await?; - - Ok(()) - } - - async fn delete(&self, account_id: AccountId, role: Role) -> Result<(), GolemError> { - info!("Deleting account role."); - let role = cli_to_api(role); - - let _ = self.client.role_delete(&account_id.id, &role).await?; - - Ok(()) - } -} - -fn api_to_cli(role: golem_client::model::Role) -> Role { - match role { - golem_client::model::Role::Admin {} => Role::Admin, - golem_client::model::Role::MarketingAdmin {} => Role::MarketingAdmin, - golem_client::model::Role::ViewProject {} => Role::ViewProject, - golem_client::model::Role::DeleteProject {} => Role::DeleteProject, - golem_client::model::Role::CreateProject {} => Role::CreateProject, - golem_client::model::Role::InstanceServer {} => Role::InstanceServer, - } -} - -fn cli_to_api(role: Role) -> golem_client::model::Role { - match role { - Role::Admin {} => golem_client::model::Role::Admin, - Role::MarketingAdmin {} => golem_client::model::Role::MarketingAdmin, - Role::ViewProject {} => golem_client::model::Role::ViewProject, - Role::DeleteProject {} => golem_client::model::Role::DeleteProject, - Role::CreateProject {} => golem_client::model::Role::CreateProject, - Role::InstanceServer {} => golem_client::model::Role::InstanceServer, - } -} diff --git a/src/clients/login.rs b/src/clients/login.rs deleted file mode 100644 index c31a77d..0000000 --- a/src/clients/login.rs +++ /dev/null @@ -1,50 +0,0 @@ -use async_trait::async_trait; -use golem_client::api::LoginClient as HttpClient; -use golem_client::model::OAuth2Data; -use golem_client::model::Token; -use golem_client::model::TokenSecret; -use golem_client::model::UnsafeToken; -use golem_client::{Context, Security}; -use tracing::info; - -use crate::model::GolemError; - -#[async_trait] -pub trait LoginClient { - async fn token_details(&self, manual_token: TokenSecret) -> Result; - - async fn start_oauth2(&self) -> Result; - - async fn complete_oauth2(&self, session: String) -> Result; -} - -pub struct LoginClientLive { - pub client: C, - pub context: Context, -} - -#[async_trait] -impl LoginClient for LoginClientLive { - async fn token_details(&self, manual_token: TokenSecret) -> Result { - info!("Getting token info"); - let mut context = self.context.clone(); - context.security_token = Security::Bearer(manual_token.value.to_string()); - - let client = golem_client::api::LoginClientLive { context }; - - Ok(client.v_2_login_token_get().await?) - } - - async fn start_oauth2(&self) -> Result { - info!("Start OAuth2 workflow"); - Ok(self.client.login_oauth_2_device_start_post().await?) - } - - async fn complete_oauth2(&self, session: String) -> Result { - info!("Complete OAuth2 workflow"); - Ok(self - .client - .login_oauth_2_device_complete_post(&session) - .await?) - } -} diff --git a/src/clients/policy.rs b/src/clients/policy.rs deleted file mode 100644 index aab4e32..0000000 --- a/src/clients/policy.rs +++ /dev/null @@ -1,50 +0,0 @@ -use async_trait::async_trait; -use golem_client::model::ProjectActions; -use golem_client::model::ProjectPolicy; -use golem_client::model::ProjectPolicyData; -use tracing::info; - -use crate::clients::action_cli_to_api; -use crate::model::{GolemError, ProjectAction, ProjectPolicyId}; - -#[async_trait] -pub trait ProjectPolicyClient { - async fn create( - &self, - name: String, - actions: Vec, - ) -> Result; - async fn get(&self, policy_id: ProjectPolicyId) -> Result; -} - -pub struct ProjectPolicyClientLive { - pub client: C, -} - -#[async_trait] -impl ProjectPolicyClient - for ProjectPolicyClientLive -{ - async fn create( - &self, - name: String, - actions: Vec, - ) -> Result { - info!("Creation project policy"); - - let actions: Vec = - actions.into_iter().map(action_cli_to_api).collect(); - let data = ProjectPolicyData { - name, - project_actions: ProjectActions { actions }, - }; - - Ok(self.client.post(&data).await?) - } - - async fn get(&self, policy_id: ProjectPolicyId) -> Result { - info!("Getting project policy"); - - Ok(self.client.project_policy_id_get(&policy_id.0).await?) - } -} diff --git a/src/clients/project.rs b/src/clients/project.rs deleted file mode 100644 index 31c7c29..0000000 --- a/src/clients/project.rs +++ /dev/null @@ -1,103 +0,0 @@ -use async_trait::async_trait; -use golem_client::model::Project; -use golem_client::model::ProjectDataRequest; -use indoc::formatdoc; -use tracing::info; - -use crate::model::{AccountId, GolemError, ProjectId, ProjectRef}; - -#[async_trait] -pub trait ProjectClient { - async fn create( - &self, - owner_account_id: AccountId, - name: String, - description: Option, - ) -> Result; - async fn find(&self, name: Option) -> Result, GolemError>; - async fn find_default(&self) -> Result; - async fn delete(&self, project_id: ProjectId) -> Result<(), GolemError>; - - async fn resolve_id(&self, project_ref: ProjectRef) -> Result, GolemError>; - - async fn resolve_id_or_default( - &self, - project_ref: ProjectRef, - ) -> Result { - match self.resolve_id(project_ref).await? { - None => Ok(ProjectId(self.find_default().await?.project_id)), - Some(project_id) => Ok(project_id), - } - } -} - -pub struct ProjectClientLive { - pub client: C, -} - -#[async_trait] -impl ProjectClient for ProjectClientLive { - async fn create( - &self, - owner_account_id: AccountId, - name: String, - description: Option, - ) -> Result { - info!("Create new project {name}."); - - let request = ProjectDataRequest { - name, - owner_account_id: owner_account_id.id, - description: description.unwrap_or("".to_string()), - }; - Ok(self.client.post(&request).await?) - } - - async fn find(&self, name: Option) -> Result, GolemError> { - info!("Listing projects."); - - Ok(self.client.get(name.as_deref()).await?) - } - - async fn find_default(&self) -> Result { - info!("Getting default project."); - - Ok(self.client.default_get().await?) - } - - async fn delete(&self, project_id: ProjectId) -> Result<(), GolemError> { - info!("Deleting project {project_id:?}"); - - let _ = self.client.project_id_delete(&project_id.0).await?; - - Ok(()) - } - - async fn resolve_id(&self, project_ref: ProjectRef) -> Result, GolemError> { - match project_ref { - ProjectRef::Id(id) => Ok(Some(id)), - ProjectRef::Name(name) => { - let projects = self.find(Some(name.clone())).await?; - - if projects.len() > 1 { - let projects: Vec = - projects.iter().map(|p| p.project_id.to_string()).collect(); - Err(GolemError(formatdoc!( - " - Multiple projects found for name {name}: - {} - Use explicit --project-id or set target project as default. - ", - projects.join(", ") - ))) - } else { - match projects.first() { - None => Err(GolemError(format!("Can't find project with name {name}"))), - Some(project) => Ok(Some(ProjectId(project.project_id))), - } - } - } - ProjectRef::Default => Ok(None), - } - } -} diff --git a/src/clients/project_grant.rs b/src/clients/project_grant.rs deleted file mode 100644 index b102c5e..0000000 --- a/src/clients/project_grant.rs +++ /dev/null @@ -1,68 +0,0 @@ -use async_trait::async_trait; -use golem_client::model::ProjectGrant; -use golem_client::model::ProjectGrantDataRequest; -use tracing::info; - -use crate::clients::action_cli_to_api; -use crate::model::{AccountId, GolemError, ProjectAction, ProjectId, ProjectPolicyId}; - -#[async_trait] -pub trait ProjectGrantClient { - async fn create( - &self, - project_id: ProjectId, - account_id: AccountId, - policy_id: ProjectPolicyId, - ) -> Result; - async fn create_actions( - &self, - project_id: ProjectId, - account_id: AccountId, - actions: Vec, - ) -> Result; -} - -pub struct ProjectGrantClientLive { - pub client: C, -} - -#[async_trait] -impl ProjectGrantClient - for ProjectGrantClientLive -{ - async fn create( - &self, - project_id: ProjectId, - account_id: AccountId, - policy_id: ProjectPolicyId, - ) -> Result { - info!("Creating project grant for policy {policy_id}."); - - let data = ProjectGrantDataRequest { - grantee_account_id: account_id.id, - project_policy_id: Some(policy_id.0), - project_actions: Vec::new(), - project_policy_name: None, - }; - - Ok(self.client.post(&project_id.0, &data).await?) - } - - async fn create_actions( - &self, - project_id: ProjectId, - account_id: AccountId, - actions: Vec, - ) -> Result { - info!("Creating project grant for actions."); - - let data = ProjectGrantDataRequest { - grantee_account_id: account_id.id, - project_policy_id: None, - project_policy_name: None, - project_actions: actions.into_iter().map(action_cli_to_api).collect(), - }; - - Ok(self.client.post(&project_id.0, &data).await?) - } -} diff --git a/src/clients/template.rs b/src/clients/template.rs index 5f9293e..6574464 100644 --- a/src/clients/template.rs +++ b/src/clients/template.rs @@ -9,7 +9,6 @@ use golem_client::model::FunctionResult; use golem_client::model::NameOptionTypePair; use golem_client::model::NameTypePair; use golem_client::model::Template; -use golem_client::model::TemplateQuery; use golem_client::model::Type; use golem_client::model::TypeEnum; use golem_client::model::TypeFlags; @@ -21,18 +20,13 @@ use tokio::fs::File; use tracing::info; use crate::model::{GolemError, PathBufOrStdin, TemplateName}; -use crate::{ProjectId, RawTemplateId}; +use crate::RawTemplateId; #[async_trait] pub trait TemplateClient { - async fn find( - &self, - project_id: Option, - name: Option, - ) -> Result, GolemError>; + async fn find(&self, name: Option) -> Result, GolemError>; async fn add( &self, - project_id: Option, name: TemplateName, file: PathBufOrStdin, ) -> Result; @@ -159,8 +153,8 @@ fn render_type(typ: &Type) -> String { fn render_result(r: &FunctionResult) -> String { match &r.name { - None => render_type(&r.typ), - Some(name) => format!("{name}: {}", render_type(&r.typ)), + None => render_type(&r.tpe), + Some(name) => format!("{name}: {}", render_type(&r.tpe)), } } @@ -172,7 +166,7 @@ fn show_exported_function( ) -> String { let params = parameters .iter() - .map(|p| format!("{}: {}", p.name, render_type(&p.typ))) + .map(|p| format!("{}: {}", p.name, render_type(&p.tpe))) .collect::>() .join(", "); let res_str = results @@ -185,44 +179,30 @@ fn show_exported_function( #[async_trait] impl TemplateClient for TemplateClientLive { - async fn find( - &self, - project_id: Option, - name: Option, - ) -> Result, GolemError> { + async fn find(&self, name: Option) -> Result, GolemError> { info!("Getting templates"); - let project_id = project_id.map(|p| p.0); let name = name.map(|n| n.0); - let templates: Vec