Skip to content

Commit

Permalink
Fixing API Gateway remaining tickets and bug fixes (#543)
Browse files Browse the repository at this point in the history
* Fix function lookup

* Fix function lookup

* Reformat code

* Remove box dyn error from api deployment

* Fix deployment

* Fix clippy and formatting

* Make sure route conflicts are resolved

* Update yaml

* Start changing golem cli

* Make changes in golem cli

* Fix formatting and clippy

* Revert the text change

* Change Golem CLI to accept multiple API definitions

* Fix clippy

* Fix deployment

* Fix more tests

* Change to slash
  • Loading branch information
afsalthaj authored Jun 6, 2024
1 parent 60a20ae commit b9da7f1
Show file tree
Hide file tree
Showing 29 changed files with 836 additions and 434 deletions.
5 changes: 2 additions & 3 deletions golem-cli/src/clients/api_deployment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::model::{ApiDefinitionId, ApiDefinitionVersion, ApiDeployment, GolemError};
use crate::model::{ApiDefinitionId, ApiDefinitionIdWithVersion, ApiDeployment, GolemError};
use async_trait::async_trait;

#[async_trait]
Expand All @@ -21,8 +21,7 @@ pub trait ApiDeploymentClient {

async fn deploy(
&self,
api_definition_id: &ApiDefinitionId,
version: &ApiDefinitionVersion,
api_definitions: Vec<ApiDefinitionIdWithVersion>,
host: &str,
subdomain: Option<String>,
project: &Self::ProjectContext,
Expand Down
36 changes: 22 additions & 14 deletions golem-cli/src/cloud/clients/api_deployment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use golem_cloud_client::model::ApiSite;
use itertools::Itertools;
use tracing::info;

use crate::model::{ApiDefinitionId, ApiDefinitionVersion, ApiDeployment, GolemError};
use crate::model::{ApiDefinitionId, ApiDefinitionIdWithVersion, ApiDeployment, GolemError};

#[derive(Clone)]
pub struct ApiDeploymentClientLive<C: golem_cloud_client::api::ApiDeploymentClient + Sync + Send> {
Expand All @@ -35,30 +35,38 @@ impl<C: golem_cloud_client::api::ApiDeploymentClient + Sync + Send> ApiDeploymen

async fn deploy(
&self,
api_definition_id: &ApiDefinitionId,
version: &ApiDefinitionVersion,
api_definitions: Vec<ApiDefinitionIdWithVersion>,
host: &str,
subdomain: Option<String>,
project: &Self::ProjectContext,
) -> Result<ApiDeployment, GolemError> {
info!(
"Deploying definition {api_definition_id}/{version}, host {host} {}",
"Deploying definitions to host {host} {}",
subdomain
.clone()
.map_or("".to_string(), |s| format!("subdomain {}", s))
);

let deployment = golem_cloud_client::model::ApiDeployment {
api_definition_id: api_definition_id.0.to_string(),
version: version.0.to_string(),
project_id: project.0,
site: ApiSite {
host: host.to_string(),
subdomain: subdomain.expect("Subdomain is mandatory"), // TODO: unify OSS and cloud
},
};
if api_definitions.len() > 1 {
Err(GolemError(
"Multiple API definitions in a deployment is not supported in Golem Cloud yet"
.to_string(),
))
} else {
let api_definition_id = api_definitions[0].id.0.clone();
let version = api_definitions[0].version.0.clone();
let deployment = golem_cloud_client::model::ApiDeployment {
api_definition_id,
version,
project_id: project.0,
site: ApiSite {
host: host.to_string(),
subdomain: subdomain.expect("Subdomain is mandatory"), // TODO: unify OSS and cloud
},
};

Ok(self.client.deploy(&deployment).await?.into())
Ok(self.client.deploy(&deployment).await?.into())
}
}

async fn list(
Expand Down
17 changes: 6 additions & 11 deletions golem-cli/src/command/api_deployment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::model::{ApiDefinitionId, ApiDefinitionVersion, GolemError, GolemResult};
use crate::model::{ApiDefinitionId, ApiDefinitionIdWithVersion, GolemError, GolemResult};
use crate::service::api_deployment::ApiDeploymentService;
use crate::service::project::ProjectResolver;
use clap::Subcommand;
Expand All @@ -27,13 +27,9 @@ pub enum ApiDeploymentSubcommand<ProjectRef: clap::Args> {
#[command(flatten)]
project_ref: ProjectRef,

/// Api definition id
#[arg(short, long)]
id: ApiDefinitionId,

/// Api definition version
#[arg(short = 'V', long)]
version: ApiDefinitionVersion,
/// Api definition id with version
#[arg(short = 'd', long = "definition")]
definitions: Vec<ApiDefinitionIdWithVersion>,

#[arg(short = 'H', long)]
host: String,
Expand Down Expand Up @@ -80,14 +76,13 @@ impl<ProjectRef: clap::Args + Send + Sync + 'static> ApiDeploymentSubcommand<Pro
match self {
ApiDeploymentSubcommand::Deploy {
project_ref,
id,
version,
definitions,
host,
subdomain,
} => {
let project_id = projects.resolve_id_or_default(project_ref).await?;
service
.deploy(id, version, host, subdomain, &project_id)
.deploy(definitions, host, subdomain, &project_id)
.await
}
ApiDeploymentSubcommand::Get { site } => service.get(site).await,
Expand Down
56 changes: 41 additions & 15 deletions golem-cli/src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use clap::builder::{StringValueParser, TypedValueParser};
use clap::error::{ContextKind, ContextValue, ErrorKind};
use clap::{Arg, ArgMatches, Command, Error, FromArgMatches};
use derive_more::{Display, FromStr};
use golem_client::model::{ApiSite, ScanCursor};
use golem_client::model::{ApiDefinitionInfo, ApiSite, ScanCursor};
use golem_examples::model::{Example, ExampleName, GuestLanguage, GuestLanguageTier};
use serde::{Deserialize, Serialize};
use strum::IntoEnumIterator;
Expand Down Expand Up @@ -293,6 +293,36 @@ impl IdempotencyKey {
}
}

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct ApiDefinitionIdWithVersion {
pub id: ApiDefinitionId,
pub version: ApiDefinitionVersion,
}

impl Display for ApiDefinitionIdWithVersion {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}/{}", self.id, self.version)
}
}

impl FromStr for ApiDefinitionIdWithVersion {
type Err = String;

fn from_str(s: &str) -> Result<Self, Self::Err> {
let parts: Vec<&str> = s.split('/').collect();
if parts.len() != 2 {
return Err(format!(
"Invalid api definition id with version: {s}. Expected format: <id>/<version>"
));
}

let id = ApiDefinitionId(parts[0].to_string());
let version = ApiDefinitionVersion(parts[1].to_string());

Ok(ApiDefinitionIdWithVersion { id, version })
}
}

#[derive(Clone, PartialEq, Eq, Debug, Display, FromStr)]
pub struct ApiDefinitionId(pub String); // TODO: Validate

Expand Down Expand Up @@ -586,9 +616,8 @@ impl From<golem_cloud_client::model::WorkersMetadataResponse> for WorkersMetadat

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ApiDeployment {
#[serde(rename = "apiDefinitionId")]
pub api_definition_id: String,
pub version: String,
#[serde(rename = "apiDefinitions")]
pub api_definitions: Vec<ApiDefinitionInfo>,
#[serde(rename = "projectId")]
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(default)]
Expand All @@ -598,17 +627,10 @@ pub struct ApiDeployment {

impl From<golem_client::model::ApiDeployment> for ApiDeployment {
fn from(value: golem_client::model::ApiDeployment) -> Self {
let golem_client::model::ApiDeployment {
api_definition_id,
version,
site,
} = value;

ApiDeployment {
api_definition_id,
version,
api_definitions: value.api_definitions,
project_id: None,
site,
site: value.site,
}
}
}
Expand All @@ -622,9 +644,13 @@ impl From<golem_cloud_client::model::ApiDeployment> for ApiDeployment {
site: golem_cloud_client::model::ApiSite { host, subdomain },
} = value;

ApiDeployment {
api_definition_id,
let api_definitions = vec![ApiDefinitionInfo {
id: api_definition_id,
version,
}];

ApiDeployment {
api_definitions,
project_id: Some(project_id),
site: ApiSite {
host,
Expand Down
53 changes: 28 additions & 25 deletions golem-cli/src/model/text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -407,17 +407,19 @@ impl TextFormat for ScanCursor {

impl TextFormat for ApiDeployment {
fn print(&self) {
printdoc!(
"
API deployment on {} with definition {}/{}
",
match &self.site.subdomain {
Some(subdomain) => format!("{}.{}", subdomain, self.site.host),
None => self.site.host.to_string(),
},
self.api_definition_id,
self.version,
);
for api_defs in &self.api_definitions {
printdoc!(
"
API deployment on {} with definition {}/{}
",
match &self.site.subdomain {
Some(subdomain) => format!("{}.{}", subdomain, self.site.host),
None => self.site.host.to_string(),
},
api_defs.id,
api_defs.version,
);
}
}
}

Expand All @@ -431,24 +433,25 @@ struct ApiDeploymentView {
pub version: String,
}

impl From<&ApiDeployment> for ApiDeploymentView {
fn from(value: &ApiDeployment) -> Self {
ApiDeploymentView {
site: match &value.site.subdomain {
Some(subdomain) => format!("{}.{}", subdomain, value.site.host),
None => value.site.host.to_string(),
},
id: value.api_definition_id.to_string(),
version: value.version.to_string(),
}
}
}

impl TextFormat for Vec<ApiDeployment> {
fn print(&self) {
print_stdout(
self.iter()
.map(ApiDeploymentView::from)
.flat_map(|deployment| {
deployment
.api_definitions
.iter()
.map(|def| ApiDeploymentView {
site: match &deployment.site.subdomain {
Some(subdomain) => {
format!("{}.{}", subdomain, deployment.site.host)
}
None => deployment.site.host.to_string(),
},
id: def.id.to_string(),
version: def.version.to_string(),
})
})
.collect::<Vec<_>>()
.with_title(),
)
Expand Down
20 changes: 13 additions & 7 deletions golem-cli/src/oss/clients/api_deployment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ use async_trait::async_trait;
use itertools::Itertools;

use crate::clients::api_deployment::ApiDeploymentClient;
use golem_client::model::ApiSite;
use golem_client::model::{ApiDefinitionInfo, ApiSite};
use tracing::info;

use crate::model::{ApiDefinitionId, ApiDefinitionVersion, ApiDeployment, GolemError};
use crate::model::{ApiDefinitionId, ApiDefinitionIdWithVersion, ApiDeployment, GolemError};
use crate::oss::model::OssContext;

#[derive(Clone)]
Expand All @@ -35,22 +35,28 @@ impl<C: golem_client::api::ApiDeploymentClient + Sync + Send> ApiDeploymentClien

async fn deploy(
&self,
api_definition_id: &ApiDefinitionId,
version: &ApiDefinitionVersion,
definitions: Vec<ApiDefinitionIdWithVersion>,
host: &str,
subdomain: Option<String>,
_project: &Self::ProjectContext,
) -> Result<ApiDeployment, GolemError> {
info!(
"Deploying definition {api_definition_id}/{version}, host {host} {}",
"Deploying definitions to host {host} {}",
subdomain
.clone()
.map_or("".to_string(), |s| format!("subdomain {}", s))
);

let api_definition_infos = definitions
.iter()
.map(|d| ApiDefinitionInfo {
id: d.id.0.clone(),
version: d.version.0.clone(),
})
.collect::<Vec<_>>();

let deployment = golem_client::model::ApiDeployment {
api_definition_id: api_definition_id.0.to_string(),
version: version.0.to_string(),
api_definitions: api_definition_infos,
site: ApiSite {
host: host.to_string(),
subdomain,
Expand Down
10 changes: 4 additions & 6 deletions golem-cli/src/service/api_deployment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
// limitations under the License.

use crate::clients::api_deployment::ApiDeploymentClient;
use crate::model::{ApiDefinitionId, ApiDefinitionVersion, GolemError, GolemResult};
use crate::model::{ApiDefinitionId, ApiDefinitionIdWithVersion, GolemError, GolemResult};
use async_trait::async_trait;

#[async_trait]
Expand All @@ -22,8 +22,7 @@ pub trait ApiDeploymentService {

async fn deploy(
&self,
id: ApiDefinitionId,
version: ApiDefinitionVersion,
definitions: Vec<ApiDefinitionIdWithVersion>,
host: String,
subdomain: Option<String>,
project: &Self::ProjectContext,
Expand All @@ -49,15 +48,14 @@ impl<ProjectContext: Send + Sync> ApiDeploymentService

async fn deploy(
&self,
id: ApiDefinitionId,
version: ApiDefinitionVersion,
definitions: Vec<ApiDefinitionIdWithVersion>,
host: String,
subdomain: Option<String>,
project: &Self::ProjectContext,
) -> Result<GolemResult, GolemError> {
let deployment = self
.client
.deploy(&id, &version, &host, subdomain, project)
.deploy(definitions, &host, subdomain, project)
.await?;

Ok(GolemResult::Ok(Box::new(deployment)))
Expand Down
Loading

0 comments on commit b9da7f1

Please sign in to comment.