From 4601a537941cff282503dc2de5ef8f9616f9e218 Mon Sep 17 00:00:00 2001 From: Simon Popugaev Date: Fri, 9 Aug 2024 21:52:40 +0300 Subject: [PATCH] 647 docker compose profile init (#734) --- golem-cli/src/init.rs | 105 +++++++++++++++++++++++++++++++++----- golem-cli/src/oss/main.rs | 48 ++++++++++++----- 2 files changed, 128 insertions(+), 25 deletions(-) diff --git a/golem-cli/src/init.rs b/golem-cli/src/init.rs index 6d10126fba..15aa6480e7 100644 --- a/golem-cli/src/init.rs +++ b/golem-cli/src/init.rs @@ -12,15 +12,21 @@ // See the License for the specific language governing permissions and // limitations under the License. +use crate::command::api_definition::ApiDefinitionSubcommand; +use crate::command::api_deployment::ApiDeploymentSubcommand; +use crate::command::component::ComponentSubCommand; use crate::command::profile::{ProfileSubCommand, UniversalProfileAdd}; +use crate::command::worker::{OssWorkerUriArg, WorkerSubcommand}; use crate::config::{CloudProfile, Config, OssProfile, Profile, ProfileConfig, ProfileName}; use crate::examples; -use crate::model::{Format, GolemError, GolemResult}; +use crate::model::{ComponentUriArg, Format, GolemError, GolemResult}; +use crate::oss::model::OssContext; use crate::stubgen::handle_stubgen; use async_trait::async_trait; use clap::{Parser, Subcommand}; use clap_verbosity_flag::Verbosity; use colored::Colorize; +use golem_common::uri::oss::uri::ResourceUri; use indoc::formatdoc; use inquire::{Confirm, CustomType, Select}; use serde::{Deserialize, Serialize}; @@ -55,6 +61,43 @@ pub enum InitCommand { #[command(subcommand)] subcommand: golem_wasm_rpc_stubgen::Command, }, + + /// Upload and manage Golem components + #[command()] + Component { + #[command(subcommand)] + subcommand: ComponentSubCommand, + }, + + /// Manage Golem workers + #[command()] + Worker { + #[command(subcommand)] + subcommand: WorkerSubcommand, + }, + + /// Get resource by URI + /// + /// Use resource URN or URL to get resource metadata. + #[command()] + Get { + #[arg(value_name = "URI")] + uri: ResourceUri, + }, + + /// Manage Golem api definitions + #[command()] + ApiDefinition { + #[command(subcommand)] + subcommand: ApiDefinitionSubcommand, + }, + + /// Manage Golem api deployments + #[command()] + ApiDeployment { + #[command(subcommand)] + subcommand: ApiDeploymentSubcommand, + }, } #[derive(Parser, Debug)] @@ -134,6 +177,9 @@ pub async fn async_main + clap::Args>( }) => examples::process_list_examples(min_tier, language), #[cfg(feature = "stubgen")] InitCommand::Stubgen { subcommand } => handle_stubgen(subcommand).await, + _ => Err(GolemError( + "Your Golem CLI is not configured. Please run `golem-cli init`".to_owned(), + )), }; match res { @@ -173,15 +219,25 @@ fn validate_profile_override( #[derive(Debug, Clone, Copy, EnumIter)] enum ProfileType { - Golem, - GolemCloud, + OssDefaultCompose, + OssCustom, + Cloud, } impl Display for ProfileType { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { - ProfileType::Golem => write!(f, "{}. For stand-alone installations", "Golem".bold()), - ProfileType::GolemCloud => write!( + ProfileType::OssDefaultCompose => write!( + f, + "{}. For default docker compose configuration", + "Golem Default".bold() + ), + ProfileType::OssCustom => write!( + f, + "{}. For stand-alone installations with custom configuration", + "Golem".bold() + ), + ProfileType::Cloud => write!( f, "{}. To use cloud version provided by https://golem.cloud/", "Golem Cloud".bold() @@ -197,6 +253,13 @@ fn select_type() -> Result { .map_err(|err| GolemError(format!("Unexpected error: {err}"))) } +fn select_oss_type() -> Result { + let options = vec![ProfileType::OssDefaultCompose, ProfileType::OssCustom]; + Select::new("Select profile type:", options) + .prompt() + .map_err(|err| GolemError(format!("Unexpected error: {err}"))) +} + #[derive(Debug, Copy, Clone, EnumIter)] enum InitFormat { Text, @@ -309,7 +372,9 @@ async fn ask_auth_cloud() -> Result { fn ask_for_component_url() -> Result { CustomType::::new("Component service URL:") - .with_error_message("Please type a valid URL. For instance: http://localhost:9876") + .with_error_message(&format!( + "Please type a valid URL. For instance: {DEFAULT_OSS_URL}" + )) .prompt() .map_err(|err| GolemError(format!("Unexpected error: {err}"))) } @@ -346,7 +411,7 @@ fn ask_for_worker_url() -> Result, GolemError> { .map_err(|err| GolemError(format!("Unexpected error: {err}"))) } -fn make_oss_profile() -> Result { +fn make_oss_custom_profile() -> Result { let url = ask_for_component_url()?; let worker_url = ask_for_worker_url()?; @@ -372,6 +437,21 @@ fn make_oss_profile() -> Result { })) } +pub const DEFAULT_OSS_URL: &str = "http://localhost:9881"; + +fn make_oss_default_profile() -> Result { + let url = Url::parse(DEFAULT_OSS_URL).unwrap(); + + let config = make_profile_config()?; + + Ok(Profile::Golem(OssProfile { + url, + worker_url: None, + allow_insecure: false, + config, + })) +} + pub struct InitResult { pub profile_name: ProfileName, pub auth_required: bool, @@ -385,20 +465,21 @@ pub async fn init_profile( validate_profile_override(&profile_name, config_dir)?; let typ = match cli_kind { CliKind::Universal => select_type()?, - CliKind::Golem => ProfileType::Golem, - CliKind::Cloud => ProfileType::GolemCloud, + CliKind::Golem => select_oss_type()?, + CliKind::Cloud => ProfileType::Cloud, }; let profile = match typ { - ProfileType::Golem => make_oss_profile()?, - ProfileType::GolemCloud => make_cloud_profile()?, + ProfileType::OssDefaultCompose => make_oss_default_profile()?, + ProfileType::OssCustom => make_oss_custom_profile()?, + ProfileType::Cloud => make_cloud_profile()?, }; Config::set_profile(profile_name.clone(), profile, config_dir)?; set_active_profile(cli_kind, &profile_name, config_dir)?; - let auth_required = if let ProfileType::GolemCloud = typ { + let auth_required = if let ProfileType::Cloud = typ { ask_auth_cloud().await? } else { false diff --git a/golem-cli/src/oss/main.rs b/golem-cli/src/oss/main.rs index 0107d8eddb..5fb9f3031b 100644 --- a/golem-cli/src/oss/main.rs +++ b/golem-cli/src/oss/main.rs @@ -22,6 +22,7 @@ use crate::oss::command::{GolemOssCommand, OssCommand}; use crate::oss::factory::OssServiceFactory; use crate::oss::model::OssContext; use crate::stubgen::handle_stubgen; +use clap_verbosity_flag::Verbosity; use colored::Colorize; use golem_common::uri::oss::uri::{ComponentUri, ResourceUri, WorkerUri}; use golem_common::uri::oss::url::{ComponentUrl, ResourceUrl, WorkerUrl}; @@ -54,20 +55,10 @@ pub async fn async_main + clap::Args>( let ctx = &OssContext::EMPTY; - let version_check = factory.version_service(ctx)?.check().await; - - if let Err(err) = version_check { - if cmd.verbosity.log_level() == Some(log::Level::Warn) - || cmd.verbosity.log_level() == Some(log::Level::Info) - || cmd.verbosity.log_level() == Some(log::Level::Debug) - || cmd.verbosity.log_level() == Some(log::Level::Trace) - { - eprintln!("{}", err.0.yellow()) - } - } - let res = match cmd.command { OssCommand::Component { subcommand } => { + check_version(&factory, &cmd.verbosity).await?; + subcommand .handle( factory.component_service(ctx)?.as_ref(), @@ -76,6 +67,8 @@ pub async fn async_main + clap::Args>( .await } OssCommand::Worker { subcommand } => { + check_version(&factory, &cmd.verbosity).await?; + subcommand .handle( format, @@ -99,6 +92,8 @@ pub async fn async_main + clap::Args>( #[cfg(feature = "stubgen")] OssCommand::Stubgen { subcommand } => handle_stubgen(subcommand).await, OssCommand::ApiDefinition { subcommand } => { + check_version(&factory, &cmd.verbosity).await?; + subcommand .handle( factory.api_definition_service(ctx)?.as_ref(), @@ -107,6 +102,8 @@ pub async fn async_main + clap::Args>( .await } OssCommand::ApiDeployment { subcommand } => { + check_version(&factory, &cmd.verbosity).await?; + subcommand .handle( factory.api_deployment_service(ctx)?.as_ref(), @@ -124,7 +121,11 @@ pub async fn async_main + clap::Args>( .await .map(|_| GolemResult::Str("Profile created".to_string())) } - OssCommand::Get { uri } => get_resource_by_uri(uri, &factory).await, + OssCommand::Get { uri } => { + check_version(&factory, &cmd.verbosity).await?; + + get_resource_by_uri(uri, &factory).await + } }; match res { @@ -136,6 +137,27 @@ pub async fn async_main + clap::Args>( } } +async fn check_version( + factory: &OssServiceFactory, + verbosity: &Verbosity, +) -> Result<(), GolemError> { + let ctx = &OssContext::EMPTY; + + let version_check = factory.version_service(ctx)?.check().await; + + if let Err(err) = version_check { + if verbosity.log_level() == Some(log::Level::Warn) + || verbosity.log_level() == Some(log::Level::Info) + || verbosity.log_level() == Some(log::Level::Debug) + || verbosity.log_level() == Some(log::Level::Trace) + { + eprintln!("{}", err.0.yellow()) + } + } + + Ok(()) +} + async fn get_resource_by_urn( urn: ResourceUrn, factory: &OssServiceFactory,