Skip to content

Commit

Permalink
Convenience fallback mode for component add and update (#762)
Browse files Browse the repository at this point in the history
  • Loading branch information
vigoo authored Aug 15, 2024
1 parent 3c06c40 commit 0b8ed20
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 18 deletions.
20 changes: 19 additions & 1 deletion golem-cli/src/command/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ pub enum ComponentSubCommand<ProjectRef: clap::Args, ComponentRef: clap::Args> {
/// The WASM file to be used as a Golem component
#[arg(value_name = "component-file", value_hint = clap::ValueHint::FilePath)]
component_file: PathBufOrStdin, // TODO: validate exists

/// Do not ask for performing an update in case the component already exists
#[arg(short = 'y', long)]
non_interactive: bool,
},

/// Updates an existing component by uploading a new version of its WASM
Expand All @@ -59,6 +63,10 @@ pub enum ComponentSubCommand<ProjectRef: clap::Args, ComponentRef: clap::Args> {
/// Update mode - auto or manual
#[arg(long, default_value = "auto", requires = "try_update_workers")]
update_mode: WorkerUpdateMode,

/// Do not ask for creating a new component in case it does not exists
#[arg(short = 'y', long)]
non_interactive: bool,
},

/// Lists the existing components
Expand Down Expand Up @@ -124,17 +132,25 @@ impl<
project_ref,
component_name,
component_file,
non_interactive,
} => {
let project_id = projects.resolve_id_or_default(project_ref).await?;
service
.add(component_name, component_file, Some(project_id))
.add(
component_name,
component_file,
Some(project_id),
non_interactive,
format,
)
.await
}
ComponentSubCommand::Update {
component_name_or_uri,
component_file,
try_update_workers,
update_mode,
non_interactive,
} => {
let (component_name_or_uri, project_ref) = component_name_or_uri.split();
let project_id = projects.resolve_id_or_default_opt(project_ref).await?;
Expand All @@ -143,6 +159,8 @@ impl<
component_name_or_uri.clone(),
component_file,
project_id.clone(),
non_interactive,
format,
)
.await?;

Expand Down
87 changes: 76 additions & 11 deletions golem-cli/src/service/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
use crate::clients::component::ComponentClient;
use crate::model::component::{Component, ComponentView};
use crate::model::text::{ComponentAddView, ComponentGetView, ComponentUpdateView};
use crate::model::{ComponentName, GolemError, GolemResult, PathBufOrStdin};
use crate::model::{ComponentName, Format, GolemError, GolemResult, PathBufOrStdin};
use async_trait::async_trait;
use golem_common::model::ComponentId;
use golem_common::uri::oss::uri::ComponentUri;
Expand All @@ -34,12 +34,16 @@ pub trait ComponentService {
component_name: ComponentName,
component_file: PathBufOrStdin,
project: Option<Self::ProjectContext>,
non_interactive: bool,
format: Format,
) -> Result<GolemResult, GolemError>;
async fn update(
&self,
component_uri: ComponentUri,
component_file: PathBufOrStdin,
project: Option<Self::ProjectContext>,
non_interactive: bool,
format: Format,
) -> Result<GolemResult, GolemError>;
async fn list(
&self,
Expand All @@ -55,7 +59,7 @@ pub trait ComponentService {
async fn resolve_uri(
&self,
uri: ComponentUri,
project: Option<Self::ProjectContext>,
project: &Option<Self::ProjectContext>,
) -> Result<ComponentUrn, GolemError>;
async fn get_metadata(
&self,
Expand Down Expand Up @@ -83,13 +87,43 @@ impl<ProjectContext: Display + Send + Sync> ComponentService
component_name: ComponentName,
component_file: PathBufOrStdin,
project: Option<Self::ProjectContext>,
non_interactive: bool,
format: Format,
) -> Result<GolemResult, GolemError> {
let component = self
let result = self
.client
.add(component_name, component_file, &project)
.await?;
let view: ComponentView = component.into();
.add(component_name.clone(), component_file.clone(), &project)
.await;

let can_fallback = format == Format::Text && !non_interactive;
let component = match result {
Err(GolemError(message))
if message.starts_with("Component already exists") && can_fallback =>
{
let answer =
inquire::Confirm::new("Would you like to update the existing component?")
.with_default(false)
.with_help_message(&message)
.prompt();

match answer {
Ok(true) => {
let component_uri = ComponentUri::URL(ComponentUrl {
name: component_name.0.clone(),
});
let urn = self.resolve_uri(component_uri, &project).await?;
self.client.update(urn, component_file).await

}
Ok(false) => Err(GolemError(message)),
Err(error) => Err(GolemError(format!("Error while asking for confirmation: {}; Use the --non-interactive (-y) flag to bypass it.", error))),
}
}
Err(other) => Err(other),
Ok(component) => Ok(component),
}?;

let view: ComponentView = component.into();
Ok(GolemResult::Ok(Box::new(ComponentAddView(view))))
}

Expand All @@ -98,9 +132,40 @@ impl<ProjectContext: Display + Send + Sync> ComponentService
component_uri: ComponentUri,
component_file: PathBufOrStdin,
project: Option<Self::ProjectContext>,
non_interactive: bool,
format: Format,
) -> Result<GolemResult, GolemError> {
let urn = self.resolve_uri(component_uri, project).await?;
let component = self.client.update(urn, component_file).await?;
let result = self.resolve_uri(component_uri.clone(), &project).await;

let can_fallback = format == Format::Text
&& !non_interactive
&& matches!(component_uri, ComponentUri::URL { .. });
let component = match result {
Err(GolemError(message))
if message.starts_with("Can't find component") && can_fallback =>
{
let answer = inquire::Confirm::new("Would you like to create a new component?")
.with_default(false)
.with_help_message(&message)
.prompt();

match answer {
Ok(true) => {
let component_name = match &component_uri {
ComponentUri::URL(ComponentUrl { name }) => ComponentName(name.clone()),
_ => unreachable!(),
};
self.client.add(component_name, component_file, &project).await

}
Ok(false) => Err(GolemError(message)),
Err(error) => Err(GolemError(format!("Error while asking for confirmation: {}; Use the --non-interactive (-y) flag to bypass it.", error))),
}
}
Err(other) => Err(other),
Ok(urn) => self.client.update(urn, component_file.clone()).await,
}?;

let view: ComponentView = component.into();

Ok(GolemResult::Ok(Box::new(ComponentUpdateView(view))))
Expand All @@ -123,7 +188,7 @@ impl<ProjectContext: Display + Send + Sync> ComponentService
version: Option<u64>,
project: Option<Self::ProjectContext>,
) -> Result<GolemResult, GolemError> {
let urn = self.resolve_uri(component_uri, project).await?;
let urn = self.resolve_uri(component_uri, &project).await?;
let component = match version {
Some(v) => self.get_metadata(&urn, v).await?,
None => self.get_latest_metadata(&urn).await?,
Expand All @@ -135,14 +200,14 @@ impl<ProjectContext: Display + Send + Sync> ComponentService
async fn resolve_uri(
&self,
uri: ComponentUri,
project_context: Option<Self::ProjectContext>,
project_context: &Option<Self::ProjectContext>,
) -> Result<ComponentUrn, GolemError> {
match uri {
ComponentUri::URN(urn) => Ok(urn),
ComponentUri::URL(ComponentUrl { name }) => {
let components = self
.client
.find(Some(ComponentName(name.clone())), &project_context)
.find(Some(ComponentName(name.clone())), project_context)
.await?;
let components: Vec<Component> = components
.into_iter()
Expand Down
4 changes: 2 additions & 2 deletions golem-cli/src/service/deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ impl<ProjectContext: Display + Send + Sync> DeployService for DeployServiceLive<
) -> Result<GolemResult, GolemError> {
let component_urn = self
.component_service
.resolve_uri(component_uri, project)
.resolve_uri(component_uri, &project)
.await?;
let component = self
.component_service
Expand All @@ -89,7 +89,7 @@ impl<ProjectContext: Display + Send + Sync> DeployService for DeployServiceLive<
) -> Result<GolemResult, GolemError> {
let component_urn = self
.component_service
.resolve_uri(component_uri, project)
.resolve_uri(component_uri, &project)
.await?;
let component = self
.component_service
Expand Down
8 changes: 4 additions & 4 deletions golem-cli/src/service/worker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ impl<ProjectContext: Send + Sync + 'static> WorkerService for WorkerServiceLive<
args: Vec<String>,
project: Option<Self::ProjectContext>,
) -> Result<GolemResult, GolemError> {
let component_urn = self.components.resolve_uri(component_uri, project).await?;
let component_urn = self.components.resolve_uri(component_uri, &project).await?;
self.add_by_urn(component_urn, worker_name, env, args).await
}

Expand Down Expand Up @@ -491,7 +491,7 @@ impl<ProjectContext: Send + Sync + 'static> WorkerService for WorkerServiceLive<
let component_uri = ComponentUri::URL(ComponentUrl {
name: component_name,
});
let component_urn = self.components.resolve_uri(component_uri, project).await?;
let component_urn = self.components.resolve_uri(component_uri, &project).await?;

Ok(WorkerUrn {
id: WorkerId {
Expand Down Expand Up @@ -738,7 +738,7 @@ impl<ProjectContext: Send + Sync + 'static> WorkerService for WorkerServiceLive<
precise: Option<bool>,
project: Option<Self::ProjectContext>,
) -> Result<GolemResult, GolemError> {
let component_urn = self.components.resolve_uri(component_uri, project).await?;
let component_urn = self.components.resolve_uri(component_uri, &project).await?;

if count.is_some() {
let response: WorkersMetadataResponseView = self
Expand Down Expand Up @@ -789,7 +789,7 @@ impl<ProjectContext: Send + Sync + 'static> WorkerService for WorkerServiceLive<
mode: WorkerUpdateMode,
project: Option<Self::ProjectContext>,
) -> Result<GolemResult, GolemError> {
let component_urn = self.components.resolve_uri(component_uri, project).await?;
let component_urn = self.components.resolve_uri(component_uri, &project).await?;
self.update_many_by_urn(component_urn, filter, target_version, mode)
.await
}
Expand Down

0 comments on commit 0b8ed20

Please sign in to comment.