Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make oss cli more polymorphic & shuffle some code around #1117

Merged
merged 5 commits into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 73 additions & 2 deletions golem-cli/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,23 @@ pub mod profile;
pub mod worker;

use crate::command::api_security::ApiSecuritySchemeSubcommand;
use crate::completion;
use crate::config::ProfileName;
use crate::diagnose::{self, diagnose};
use crate::examples;
use crate::init::{init_profile, CliKind, DummyProfileAuth};
use crate::model::{ComponentUriArg, GolemError, GolemResult};
use crate::oss::model::OssContext;
use crate::stubgen::handle_stubgen;
use api_definition::ApiDefinitionSubcommand;
use api_deployment::ApiDeploymentSubcommand;
use clap::{self, Subcommand};
use clap::{self, Command, Subcommand};
use component::ComponentSubCommand;
use golem_common::uri::oss::uri::ComponentUri;
use plugin::PluginSubcommand;
use profile::ProfileSubCommand;
use profile::{ProfileSubCommand, UniversalProfileAdd};
use std::future::Future;
use std::path::PathBuf;
use worker::WorkerSubcommand;

pub trait ComponentRefSplit<ProjectRef> {
Expand Down Expand Up @@ -80,6 +84,19 @@ impl<Ctx> CliCommand<Ctx> for EmptyCommand {
}
}

/// convenience function to get both the clap::Command and the parsed struct in one pass
pub fn command_and_parsed<T: clap::Parser>() -> (clap::Command, T) {
let mut command = T::command();

let mut matches = command.clone().get_matches();
let res = <T as clap::FromArgMatches>::from_arg_matches_mut(&mut matches)
.map_err(|e| e.format(&mut command));
match res {
Ok(t) => (command, t),
Err(e) => e.exit(),
}
}

/// Commands that are supported by both the OSS and Cloud version and have the same implementation
#[derive(Debug, Subcommand)]
pub enum StaticSharedCommand {
Expand Down Expand Up @@ -198,3 +215,57 @@ pub enum SharedCommand<
generator: clap_complete::Shell,
},
}

/// Context before the user has initialized the profile.
pub struct NoProfileCommandContext {
pub config_dir: PathBuf,
pub command: Command,
pub cli_kind: CliKind,
}

impl NoProfileCommandContext {
// \! is an experimental type. Once stable, use in the return type.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you help me with this comment?

pub fn fail_uninitialized(&self) -> Result<GolemResult, GolemError> {
Err(GolemError(
"Your Golem CLI is not configured. Please run `golem-cli init`".to_owned(),
))
}
}

impl<
ProjectRef: clap::Args,
ComponentRef: clap::Args,
WorkerRef: clap::Args,
PluginScopeRef: clap::Args,
ProfileAdd: clap::Args + Into<UniversalProfileAdd>,
> CliCommand<NoProfileCommandContext>
for SharedCommand<ProjectRef, ComponentRef, WorkerRef, PluginScopeRef, ProfileAdd>
{
async fn run(self, ctx: NoProfileCommandContext) -> Result<GolemResult, GolemError> {
match self {
SharedCommand::Init {} => {
let profile_name = ProfileName::default(ctx.cli_kind);

init_profile(
ctx.cli_kind,
profile_name,
&ctx.config_dir,
&DummyProfileAuth,
)
.await?;

Ok(GolemResult::Str("Profile created".to_string()))
}
SharedCommand::Profile { subcommand } => {
subcommand
.handle(ctx.cli_kind, &ctx.config_dir, &DummyProfileAuth)
.await
}
SharedCommand::Completion { generator } => {
completion::print_completion(ctx.command, generator);
Ok(GolemResult::Str("".to_string()))
}
_ => ctx.fail_uninitialized(),
}
}
}
29 changes: 16 additions & 13 deletions golem-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,16 @@ use crate::config::{NamedProfile, Profile};
use crate::init::CliKind;
use crate::model::text::fmt::format_error;
use crate::service::version::{VersionCheckResult, VersionService};
use clap::CommandFactory;
use clap::Parser;
use clap_verbosity_flag::Verbosity;
use colored::Colorize;
use command::CliCommand;
use command::profile::OssProfileAdd;
use command::{CliCommand, NoProfileCommandContext};
use config::{get_config_dir, Config};
use golem_common::golem_version;
use indoc::eprintdoc;
use lenient_bool::LenientBool;
use log::Level;
use oss::main::GolemOssCli;
use oss::cli::{GolemOssCli, OssCommandContext};
use std::process::ExitCode;
use tracing::{info, warn};
use tracing_subscriber::FmtSubscriber;
Expand Down Expand Up @@ -111,9 +110,10 @@ pub async fn check_for_newer_server_version(
}
}

pub fn run_main<
ExtraCommands: CliCommand<oss::main::OssCommandContext> + CliCommand<oss::main::UnintializedOssCommandContext>,
>() -> ExitCode {
pub fn oss_main<ExtraCommands>() -> ExitCode
where
ExtraCommands: CliCommand<OssCommandContext> + CliCommand<NoProfileCommandContext>,
{
let config_dir = get_config_dir();

let oss_profile = match Config::get_active_profile(CliKind::Oss, &config_dir) {
Expand Down Expand Up @@ -141,13 +141,14 @@ pub fn run_main<
None => None,
};

let command = GolemOssCli::<ExtraCommands>::command();
let parsed = GolemOssCli::<ExtraCommands>::parse();
let (command, parsed) =
command::command_and_parsed::<GolemOssCli<OssProfileAdd, ExtraCommands>>();

let format = parsed
.format
.or_else(|| oss_profile.as_ref().map(|(_, p)| p.config.default_format))
.unwrap_or_default();

init_tracing(parsed.verbosity.clone());

info!(
Expand All @@ -161,13 +162,15 @@ pub fn run_main<
.build()
.expect("Failed to build tokio runtime for cli main");

let cli_kind = CliKind::Oss;

let result = if let Some((_, profile)) = oss_profile {
runtime.block_on(oss::main::run_with_profile(
format, config_dir, profile, command, parsed,
runtime.block_on(oss::cli::run_with_profile(
format, config_dir, profile, command, parsed, cli_kind,
))
} else {
runtime.block_on(oss::main::run_without_profile(
format, config_dir, command, parsed,
runtime.block_on(oss::cli::run_without_profile(
config_dir, command, parsed, cli_kind,
))
};

Expand Down
3 changes: 1 addition & 2 deletions golem-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use golem_cli::run_main;
use std::process::ExitCode;

fn main() -> ExitCode {
crate::run_main::<golem_cli::command::EmptyCommand>()
golem_cli::oss_main::<golem_cli::command::EmptyCommand>()
}
4 changes: 2 additions & 2 deletions golem-cli/src/oss.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.

pub mod cli;
pub mod clients;
pub mod factory;
pub mod main;
pub mod model;
pub mod resource;
mod resource;
Loading