diff --git a/cli/src/clients/admin_interface.rs b/cli/src/clients/admin_interface.rs index b22bb2ad88..a30684f9a3 100644 --- a/cli/src/clients/admin_interface.rs +++ b/cli/src/clients/admin_interface.rs @@ -14,7 +14,11 @@ use futures::StreamExt; use futures::stream; use http::{Uri, Version}; use indicatif::ProgressBar; -use restate_admin_rest_model::deployments::*; +use restate_admin_rest_model::deployments::{ + HttpDeploymentResponse, HttpDetailedDeploymentResponse, LambdaDeploymentResponse, + LambdaDetailedDeploymentResponse, RegisterDeploymentRequest, RegisterDeploymentResponse, + ServiceNameRevPair, +}; use restate_admin_rest_model::invocations::RestartAsNewInvocationResponse; use restate_admin_rest_model::services::*; use restate_admin_rest_model::version::VersionInformation; @@ -23,8 +27,50 @@ use restate_serde_util::SerdeableHeaderHashMap; use restate_types::identifiers::{DeploymentId, LambdaARN}; use restate_types::schema::deployment::ProtocolType; use restate_types::schema::service::ServiceMetadata; +use serde::Deserialize; use std::collections::HashMap; +// Local untagged versions of deployment response enums for backward-compatible deserialization. +// The server model uses #[serde(tag = "type")] for OpenAPI discriminator support, but the CLI +// needs #[serde(untagged)] to also work with older servers that don't emit the "type" field. + +#[derive(Clone, Debug, Deserialize)] +#[serde(untagged)] +pub enum DeploymentResponse { + Http(HttpDeploymentResponse), + Lambda(LambdaDeploymentResponse), +} + +impl DeploymentResponse { + pub fn id(&self) -> DeploymentId { + match self { + Self::Http(h) => h.id, + Self::Lambda(l) => l.id, + } + } +} + +#[derive(Clone, Debug, Deserialize)] +#[serde(untagged)] +pub enum DetailedDeploymentResponse { + Http(HttpDetailedDeploymentResponse), + Lambda(LambdaDetailedDeploymentResponse), +} + +impl DetailedDeploymentResponse { + pub fn id(&self) -> DeploymentId { + match self { + Self::Http(h) => h.id, + Self::Lambda(l) => l.id, + } + } +} + +#[derive(Debug, Deserialize)] +pub struct ListDeploymentsResponse { + pub deployments: Vec, +} + const MAX_PARALLEL_REQUESTS: usize = 500; pub trait AdminClientInterface { @@ -325,7 +371,7 @@ impl Deployment { deployment_response: DeploymentResponse, ) -> (DeploymentId, Self, Vec) { match deployment_response { - DeploymentResponse::Http { + DeploymentResponse::Http(HttpDeploymentResponse { id, uri, protocol_type, @@ -338,7 +384,7 @@ impl Deployment { metadata, sdk_version, .. - } => ( + }) => ( id, Deployment::Http { uri, @@ -353,7 +399,7 @@ impl Deployment { }, services, ), - DeploymentResponse::Lambda { + DeploymentResponse::Lambda(LambdaDeploymentResponse { id, arn, assume_role_arn, @@ -365,7 +411,7 @@ impl Deployment { metadata, sdk_version, .. - } => ( + }) => ( id, Deployment::Lambda { arn, @@ -386,7 +432,7 @@ impl Deployment { detailed_deployment_response: DetailedDeploymentResponse, ) -> (DeploymentId, Self, Vec) { match detailed_deployment_response { - DetailedDeploymentResponse::Http { + DetailedDeploymentResponse::Http(HttpDetailedDeploymentResponse { id, uri, protocol_type, @@ -399,7 +445,7 @@ impl Deployment { metadata, sdk_version, .. - } => ( + }) => ( id, Deployment::Http { uri, @@ -414,7 +460,7 @@ impl Deployment { }, services, ), - DetailedDeploymentResponse::Lambda { + DetailedDeploymentResponse::Lambda(LambdaDetailedDeploymentResponse { id, arn, assume_role_arn, @@ -426,7 +472,7 @@ impl Deployment { metadata, sdk_version, .. - } => ( + }) => ( id, Deployment::Lambda { arn, diff --git a/cli/src/clients/mod.rs b/cli/src/clients/mod.rs index 52880db6ac..7d0a747a65 100644 --- a/cli/src/clients/mod.rs +++ b/cli/src/clients/mod.rs @@ -20,5 +20,7 @@ pub use self::admin_client::AdminClient; pub use self::admin_client::Error as MetasClientError; pub use self::admin_client::{MAX_ADMIN_API_VERSION, MIN_ADMIN_API_VERSION}; pub use self::admin_interface::Deployment; +pub use self::admin_interface::DeploymentResponse; +pub use self::admin_interface::DetailedDeploymentResponse; pub use self::admin_interface::{AdminClientInterface, batch_execute}; pub use self::datafusion_http_client::DataFusionHttpClient; diff --git a/cli/src/commands/deployments/register.rs b/cli/src/commands/deployments/register.rs index 0830d8c63c..8756c5e05d 100644 --- a/cli/src/commands/deployments/register.rs +++ b/cli/src/commands/deployments/register.rs @@ -19,9 +19,9 @@ use http::{HeaderName, HeaderValue, StatusCode, Uri}; use indicatif::ProgressBar; use indoc::indoc; -use restate_admin_rest_model::deployments::{ - DetailedDeploymentResponse, RegisterDeploymentRequest, RegisterDeploymentResponse, -}; +use restate_admin_rest_model::deployments::{RegisterDeploymentRequest, RegisterDeploymentResponse}; + +use crate::clients::DetailedDeploymentResponse; use restate_admin_rest_model::version::AdminApiVersion; use restate_cli_util::ui::console::{Styled, StyledTable, confirm_or_exit}; use restate_cli_util::ui::stylesheet::Style; diff --git a/cli/src/commands/services/list.rs b/cli/src/commands/services/list.rs index 067fb2a2fb..24f69148d5 100644 --- a/cli/src/commands/services/list.rs +++ b/cli/src/commands/services/list.rs @@ -14,7 +14,7 @@ use anyhow::{Context, Result}; use cling::prelude::*; use comfy_table::Table; -use restate_admin_rest_model::deployments::DeploymentResponse; +use crate::clients::DeploymentResponse; use restate_cli_util::ui::console::StyledTable; use restate_cli_util::ui::watcher::Watch; use restate_cli_util::{c_error, c_println}; diff --git a/crates/admin-rest-model/src/deployments.rs b/crates/admin-rest-model/src/deployments.rs index 99bc2827d5..09d09d5285 100644 --- a/crates/admin-rest-model/src/deployments.rs +++ b/crates/admin-rest-model/src/deployments.rs @@ -186,304 +186,319 @@ pub struct ListDeploymentsResponse { pub deployments: Vec, } +/// Deployment response for HTTP deployments +#[serde_as] #[cfg_attr(feature = "schema", derive(utoipa::ToSchema))] #[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(untagged)] -pub enum DeploymentResponse { - /// Deployment response for HTTP deployments - #[cfg_attr(feature = "schema", schema(title = "HttpDeploymentResponse"))] - Http { - /// # Deployment ID - id: DeploymentId, +pub struct HttpDeploymentResponse { + /// # Deployment ID + pub id: DeploymentId, - /// # Deployment URI - /// - /// URI used to invoke this service deployment. - #[serde(with = "serde_with::As::")] - #[cfg_attr(feature = "schema", schema(value_type = String, format = "uri"))] - uri: Uri, + /// # Deployment URI + /// + /// URI used to invoke this service deployment. + #[serde_as(as = "serde_with::DisplayFromStr")] + #[cfg_attr(feature = "schema", schema(value_type = String, format = "uri"))] + pub uri: Uri, - /// # Protocol Type - /// - /// Protocol type used to invoke this service deployment. - protocol_type: ProtocolType, + /// # Protocol Type + /// + /// Protocol type used to invoke this service deployment. + pub protocol_type: ProtocolType, - /// # HTTP Version - /// - /// HTTP Version used to invoke this service deployment. - #[serde(with = "http_serde::version")] - #[cfg_attr(feature = "schema", schema(value_type = String))] - http_version: Version, + /// # HTTP Version + /// + /// HTTP Version used to invoke this service deployment. + #[serde(with = "http_serde::version")] + #[cfg_attr(feature = "schema", schema(value_type = String))] + pub http_version: Version, - /// # Additional headers - /// - /// Additional headers used to invoke this service deployment. - #[serde(skip_serializing_if = "SerdeableHeaderHashMap::is_empty")] - #[serde(default)] - additional_headers: SerdeableHeaderHashMap, + /// # Additional headers + /// + /// Additional headers used to invoke this service deployment. + #[serde(skip_serializing_if = "SerdeableHeaderHashMap::is_empty")] + #[serde(default)] + pub additional_headers: SerdeableHeaderHashMap, - /// # Metadata - /// - /// Deployment metadata. - #[serde(default, skip_serializing_if = "HashMap::is_empty")] - metadata: HashMap, + /// # Metadata + /// + /// Deployment metadata. + #[serde(default, skip_serializing_if = "HashMap::is_empty")] + pub metadata: HashMap, - #[serde(with = "serde_with::As::")] - #[cfg_attr(feature = "schema", schema(value_type = String))] - created_at: humantime::Timestamp, + #[serde_as(as = "serde_with::DisplayFromStr")] + #[cfg_attr(feature = "schema", schema(value_type = String))] + pub created_at: humantime::Timestamp, - /// # Minimum Service Protocol version - /// - /// During registration, the SDKs declare a range from minimum (included) to maximum (included) Service Protocol supported version. - min_protocol_version: i32, + /// # Minimum Service Protocol version + /// + /// During registration, the SDKs declare a range from minimum (included) to maximum (included) Service Protocol supported version. + pub min_protocol_version: i32, - /// # Maximum Service Protocol version - /// - /// During registration, the SDKs declare a range from minimum (included) to maximum (included) Service Protocol supported version. - max_protocol_version: i32, + /// # Maximum Service Protocol version + /// + /// During registration, the SDKs declare a range from minimum (included) to maximum (included) Service Protocol supported version. + pub max_protocol_version: i32, - /// # SDK version - /// - /// SDK library and version declared during registration. - #[serde(skip_serializing_if = "Option::is_none")] - #[serde(default)] - sdk_version: Option, + /// # SDK version + /// + /// SDK library and version declared during registration. + #[serde(skip_serializing_if = "Option::is_none")] + #[serde(default)] + pub sdk_version: Option, - /// # Services - /// - /// List of services exposed by this deployment. - services: Vec, + /// # Services + /// + /// List of services exposed by this deployment. + pub services: Vec, - /// # Info - /// - /// List of configuration/deprecation information related to this deployment. - #[serde(default, skip_serializing_if = "Vec::is_empty")] - info: Vec, - }, - /// Deployment response for Lambda deployments - #[cfg_attr(feature = "schema", schema(title = "LambdaDeploymentResponse"))] - Lambda { - /// # Deployment ID - id: DeploymentId, + /// # Info + /// + /// List of configuration/deprecation information related to this deployment. + #[serde(default, skip_serializing_if = "Vec::is_empty")] + pub info: Vec, +} - /// # Lambda ARN - /// - /// Lambda ARN used to invoke this service deployment. - arn: LambdaARN, +/// Deployment response for Lambda deployments +#[serde_as] +#[cfg_attr(feature = "schema", derive(utoipa::ToSchema))] +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct LambdaDeploymentResponse { + /// # Deployment ID + pub id: DeploymentId, - /// # Assume role ARN - /// - /// Assume role ARN used to invoke this deployment. Check https://docs.restate.dev/category/aws-lambda for more details. - #[serde(default, skip_serializing_if = "Option::is_none")] - assume_role_arn: Option, + /// # Lambda ARN + /// + /// Lambda ARN used to invoke this service deployment. + pub arn: LambdaARN, - /// # Compression - /// - /// Compression algorithm used for invoking Lambda. - #[serde(default, skip_serializing_if = "Option::is_none")] - compression: Option, + /// # Assume role ARN + /// + /// Assume role ARN used to invoke this deployment. Check https://docs.restate.dev/category/aws-lambda for more details. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub assume_role_arn: Option, - /// # Additional headers - /// - /// Additional headers used to invoke this service deployment. - #[serde(default, skip_serializing_if = "SerdeableHeaderHashMap::is_empty")] - additional_headers: SerdeableHeaderHashMap, + /// # Compression + /// + /// Compression algorithm used for invoking Lambda. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub compression: Option, - /// # Metadata - /// - /// Deployment metadata. - #[serde(default, skip_serializing_if = "HashMap::is_empty")] - metadata: HashMap, + /// # Additional headers + /// + /// Additional headers used to invoke this service deployment. + #[serde(default, skip_serializing_if = "SerdeableHeaderHashMap::is_empty")] + pub additional_headers: SerdeableHeaderHashMap, - #[serde(with = "serde_with::As::")] - #[cfg_attr(feature = "schema", schema(value_type = String))] - created_at: humantime::Timestamp, + /// # Metadata + /// + /// Deployment metadata. + #[serde(default, skip_serializing_if = "HashMap::is_empty")] + pub metadata: HashMap, - /// # Minimum Service Protocol version - /// - /// During registration, the SDKs declare a range from minimum (included) to maximum (included) Service Protocol supported version. - min_protocol_version: i32, + #[serde_as(as = "serde_with::DisplayFromStr")] + #[cfg_attr(feature = "schema", schema(value_type = String))] + pub created_at: humantime::Timestamp, - /// # Maximum Service Protocol version - /// - /// During registration, the SDKs declare a range from minimum (included) to maximum (included) Service Protocol supported version. - max_protocol_version: i32, + /// # Minimum Service Protocol version + /// + /// During registration, the SDKs declare a range from minimum (included) to maximum (included) Service Protocol supported version. + pub min_protocol_version: i32, - /// # SDK version - /// - /// SDK library and version declared during registration. - #[serde(default, skip_serializing_if = "Option::is_none")] - sdk_version: Option, + /// # Maximum Service Protocol version + /// + /// During registration, the SDKs declare a range from minimum (included) to maximum (included) Service Protocol supported version. + pub max_protocol_version: i32, - /// # Services - /// - /// List of services exposed by this deployment. - services: Vec, + /// # SDK version + /// + /// SDK library and version declared during registration. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub sdk_version: Option, - /// # Info - /// - /// List of configuration/deprecation information related to this deployment. - #[serde(default, skip_serializing_if = "Vec::is_empty")] - info: Vec, - }, + /// # Services + /// + /// List of services exposed by this deployment. + pub services: Vec, + + /// # Info + /// + /// List of configuration/deprecation information related to this deployment. + #[serde(default, skip_serializing_if = "Vec::is_empty")] + pub info: Vec, +} + +#[cfg_attr(feature = "schema", derive(utoipa::ToSchema))] +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(tag = "type", rename_all = "lowercase")] +pub enum DeploymentResponse { + Http(HttpDeploymentResponse), + Lambda(LambdaDeploymentResponse), } impl DeploymentResponse { pub fn id(&self) -> DeploymentId { match self { - Self::Http { id, .. } => *id, - Self::Lambda { id, .. } => *id, + Self::Http(h) => h.id, + Self::Lambda(l) => l.id, } } } -/// Detailed information about Restate deployments +/// Detailed deployment response for HTTP deployments +#[serde_as] #[cfg_attr(feature = "schema", derive(utoipa::ToSchema))] #[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(untagged)] -pub enum DetailedDeploymentResponse { - /// Detailed deployment response for HTTP deployments - #[cfg_attr(feature = "schema", schema(title = "HttpDetailedDeploymentResponse"))] - Http { - /// # Deployment ID - id: DeploymentId, +pub struct HttpDetailedDeploymentResponse { + /// # Deployment ID + pub id: DeploymentId, - /// # Deployment URI - /// - /// URI used to invoke this service deployment. - #[serde(with = "serde_with::As::")] - #[cfg_attr(feature = "schema", schema(value_type = String, format = "uri"))] - uri: Uri, + /// # Deployment URI + /// + /// URI used to invoke this service deployment. + #[serde_as(as = "serde_with::DisplayFromStr")] + #[cfg_attr(feature = "schema", schema(value_type = String, format = "uri"))] + pub uri: Uri, - /// # Protocol Type - /// - /// Protocol type used to invoke this service deployment. - protocol_type: ProtocolType, + /// # Protocol Type + /// + /// Protocol type used to invoke this service deployment. + pub protocol_type: ProtocolType, - /// # HTTP Version - /// - /// HTTP Version used to invoke this service deployment. - #[serde(with = "http_serde::version")] - #[cfg_attr(feature = "schema", schema(value_type = String))] - http_version: Version, + /// # HTTP Version + /// + /// HTTP Version used to invoke this service deployment. + #[serde(with = "http_serde::version")] + #[cfg_attr(feature = "schema", schema(value_type = String))] + pub http_version: Version, - /// # Additional headers - /// - /// Additional headers used to invoke this service deployment. - #[serde(default, skip_serializing_if = "SerdeableHeaderHashMap::is_empty")] - additional_headers: SerdeableHeaderHashMap, + /// # Additional headers + /// + /// Additional headers used to invoke this service deployment. + #[serde(default, skip_serializing_if = "SerdeableHeaderHashMap::is_empty")] + pub additional_headers: SerdeableHeaderHashMap, - /// # Metadata - /// - /// Deployment metadata. - #[serde(default, skip_serializing_if = "HashMap::is_empty")] - metadata: HashMap, + /// # Metadata + /// + /// Deployment metadata. + #[serde(default, skip_serializing_if = "HashMap::is_empty")] + pub metadata: HashMap, - #[serde(with = "serde_with::As::")] - #[cfg_attr(feature = "schema", schema(value_type = String))] - created_at: humantime::Timestamp, + #[serde_as(as = "serde_with::DisplayFromStr")] + #[cfg_attr(feature = "schema", schema(value_type = String))] + pub created_at: humantime::Timestamp, - /// # Minimum Service Protocol version - /// - /// During registration, the SDKs declare a range from minimum (included) to maximum (included) Service Protocol supported version. - min_protocol_version: i32, + /// # Minimum Service Protocol version + /// + /// During registration, the SDKs declare a range from minimum (included) to maximum (included) Service Protocol supported version. + pub min_protocol_version: i32, - /// # Maximum Service Protocol version - /// - /// During registration, the SDKs declare a range from minimum (included) to maximum (included) Service Protocol supported version. - max_protocol_version: i32, + /// # Maximum Service Protocol version + /// + /// During registration, the SDKs declare a range from minimum (included) to maximum (included) Service Protocol supported version. + pub max_protocol_version: i32, - /// # SDK version - /// - /// SDK library and version declared during registration. - #[serde(default, skip_serializing_if = "Option::is_none")] - sdk_version: Option, + /// # SDK version + /// + /// SDK library and version declared during registration. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub sdk_version: Option, - /// # Services - /// - /// List of services exposed by this deployment. - services: Vec, + /// # Services + /// + /// List of services exposed by this deployment. + pub services: Vec, - /// # Info - /// - /// List of configuration/deprecation information related to this deployment. - #[serde(default, skip_serializing_if = "Vec::is_empty")] - info: Vec, - }, - /// Detailed deployment response for Lambda deployments - #[cfg_attr(feature = "schema", schema(title = "LambdaDetailedDeploymentResponse"))] - Lambda { - /// # Deployment ID - id: DeploymentId, + /// # Info + /// + /// List of configuration/deprecation information related to this deployment. + #[serde(default, skip_serializing_if = "Vec::is_empty")] + pub info: Vec, +} - /// # Lambda ARN - /// - /// Lambda ARN used to invoke this service deployment. - arn: LambdaARN, +/// Detailed deployment response for Lambda deployments +#[serde_as] +#[cfg_attr(feature = "schema", derive(utoipa::ToSchema))] +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct LambdaDetailedDeploymentResponse { + /// # Deployment ID + pub id: DeploymentId, - /// # Assume role ARN - /// - /// Assume role ARN used to invoke this deployment. Check https://docs.restate.dev/category/aws-lambda for more details. - #[serde(default, skip_serializing_if = "Option::is_none")] - assume_role_arn: Option, + /// # Lambda ARN + /// + /// Lambda ARN used to invoke this service deployment. + pub arn: LambdaARN, - /// # Compression - /// - /// Compression algorithm used for invoking Lambda. - #[serde(default, skip_serializing_if = "Option::is_none")] - compression: Option, + /// # Assume role ARN + /// + /// Assume role ARN used to invoke this deployment. Check https://docs.restate.dev/category/aws-lambda for more details. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub assume_role_arn: Option, - /// # Additional headers - /// - /// Additional headers used to invoke this service deployment. - #[serde(default, skip_serializing_if = "SerdeableHeaderHashMap::is_empty")] - additional_headers: SerdeableHeaderHashMap, + /// # Compression + /// + /// Compression algorithm used for invoking Lambda. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub compression: Option, - /// # Metadata - /// - /// Deployment metadata. - #[serde(default, skip_serializing_if = "HashMap::is_empty")] - metadata: HashMap, + /// # Additional headers + /// + /// Additional headers used to invoke this service deployment. + #[serde(default, skip_serializing_if = "SerdeableHeaderHashMap::is_empty")] + pub additional_headers: SerdeableHeaderHashMap, - #[serde(with = "serde_with::As::")] - #[cfg_attr(feature = "schema", schema(value_type = String))] - created_at: humantime::Timestamp, + /// # Metadata + /// + /// Deployment metadata. + #[serde(default, skip_serializing_if = "HashMap::is_empty")] + pub metadata: HashMap, - /// # Minimum Service Protocol version - /// - /// During registration, the SDKs declare a range from minimum (included) to maximum (included) Service Protocol supported version. - min_protocol_version: i32, + #[serde_as(as = "serde_with::DisplayFromStr")] + #[cfg_attr(feature = "schema", schema(value_type = String))] + pub created_at: humantime::Timestamp, - /// # Maximum Service Protocol version - /// - /// During registration, the SDKs declare a range from minimum (included) to maximum (included) Service Protocol supported version. - max_protocol_version: i32, + /// # Minimum Service Protocol version + /// + /// During registration, the SDKs declare a range from minimum (included) to maximum (included) Service Protocol supported version. + pub min_protocol_version: i32, - /// # SDK version - /// - /// SDK library and version declared during registration. - #[serde(skip_serializing_if = "Option::is_none")] - #[serde(default)] - sdk_version: Option, + /// # Maximum Service Protocol version + /// + /// During registration, the SDKs declare a range from minimum (included) to maximum (included) Service Protocol supported version. + pub max_protocol_version: i32, - /// # Services - /// - /// List of services exposed by this deployment. - services: Vec, + /// # SDK version + /// + /// SDK library and version declared during registration. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub sdk_version: Option, - /// # Info - /// - /// List of configuration/deprecation information related to this deployment. - #[serde(default, skip_serializing_if = "Vec::is_empty")] - info: Vec, - }, + /// # Services + /// + /// List of services exposed by this deployment. + pub services: Vec, + + /// # Info + /// + /// List of configuration/deprecation information related to this deployment. + #[serde(default, skip_serializing_if = "Vec::is_empty")] + pub info: Vec, +} + +/// Detailed information about Restate deployments +#[cfg_attr(feature = "schema", derive(utoipa::ToSchema))] +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(tag = "type", rename_all = "lowercase")] +pub enum DetailedDeploymentResponse { + Http(HttpDetailedDeploymentResponse), + Lambda(LambdaDetailedDeploymentResponse), } impl DetailedDeploymentResponse { pub fn id(&self) -> DeploymentId { match self { - Self::Http { id, .. } => *id, - Self::Lambda { id, .. } => *id, + Self::Http(h) => h.id, + Self::Lambda(l) => l.id, } } } diff --git a/crates/admin-rest-model/src/invocations.rs b/crates/admin-rest-model/src/invocations.rs index d93a42e280..d7c3e3bcbc 100644 --- a/crates/admin-rest-model/src/invocations.rs +++ b/crates/admin-rest-model/src/invocations.rs @@ -13,8 +13,12 @@ use restate_types::invocation::client as invocation_client; use serde::{Deserialize, Serialize}; /// Specifies which deployment to use when resuming or restarting an invocation. +/// +/// Can be one of: +/// - `"Keep"` or `"keep"`: Keep the currently pinned deployment +/// - `"Latest"` or `"latest"`: Use the latest deployment +/// - Any other string: Use the specified deployment ID #[derive(Debug, Default, Clone, Serialize, Deserialize)] -#[cfg_attr(feature = "schema", derive(utoipa::ToSchema))] pub enum PatchDeploymentId { /// Keep the currently pinned deployment #[default] @@ -28,6 +32,30 @@ pub enum PatchDeploymentId { Id(String), } +// We just generate a simple string type here, +// because utoipa won't be able to generate a good schema by itself for this query param +#[cfg(feature = "schema")] +impl utoipa::PartialSchema for PatchDeploymentId { + fn schema() -> utoipa::openapi::RefOr { + utoipa::openapi::ObjectBuilder::new() + .schema_type(utoipa::openapi::schema::Type::String) + .description(Some( + "Specifies which deployment to use. \ + Use 'keep' to keep the currently pinned deployment, \ + 'latest' to use the latest deployment, \ + or provide a specific deployment ID.", + )) + .into() + } +} + +#[cfg(feature = "schema")] +impl utoipa::ToSchema for PatchDeploymentId { + fn name() -> std::borrow::Cow<'static, str> { + std::borrow::Cow::Borrowed("PatchDeploymentId") + } +} + impl PatchDeploymentId { /// Convert to the internal client representation. /// Returns an error string if the deployment ID cannot be parsed. diff --git a/crates/admin/src/rest_api/deployments.rs b/crates/admin/src/rest_api/deployments.rs index a3ea192b2c..d8a699f56a 100644 --- a/crates/admin/src/rest_api/deployments.rs +++ b/crates/admin/src/rest_api/deployments.rs @@ -448,7 +448,7 @@ fn to_deployment_response( http_version, protocol_type, address, - } => DeploymentResponse::Http { + } => DeploymentResponse::Http(HttpDeploymentResponse { id, uri: address, protocol_type, @@ -464,12 +464,12 @@ fn to_deployment_response( .map(|(name, revision)| ServiceNameRevPair { name, revision }) .collect(), info, - }, + }), DeploymentType::Lambda { arn, assume_role_arn, compression, - } => DeploymentResponse::Lambda { + } => DeploymentResponse::Lambda(LambdaDeploymentResponse { id, arn, assume_role_arn: assume_role_arn.map(Into::into), @@ -485,7 +485,7 @@ fn to_deployment_response( .map(|(name, revision)| ServiceNameRevPair { name, revision }) .collect(), info, - }, + }), } } @@ -508,7 +508,7 @@ fn to_detailed_deployment_response( http_version, protocol_type, address, - } => DetailedDeploymentResponse::Http { + } => DetailedDeploymentResponse::Http(HttpDetailedDeploymentResponse { id, uri: address, protocol_type, @@ -521,12 +521,12 @@ fn to_detailed_deployment_response( sdk_version, services, info, - }, + }), DeploymentType::Lambda { arn, assume_role_arn, compression, - } => DetailedDeploymentResponse::Lambda { + } => DetailedDeploymentResponse::Lambda(LambdaDetailedDeploymentResponse { id, arn, assume_role_arn: assume_role_arn.map(Into::into), @@ -539,7 +539,7 @@ fn to_detailed_deployment_response( sdk_version, services, info, - }, + }), } } diff --git a/crates/admin/src/rest_api/invocations.rs b/crates/admin/src/rest_api/invocations.rs index af9e924a44..4ce3a587a9 100644 --- a/crates/admin/src/rest_api/invocations.rs +++ b/crates/admin/src/rest_api/invocations.rs @@ -36,7 +36,7 @@ use crate::generate_meta_api_error; use crate::rest_api::create_envelope_header; use crate::state::AdminServiceState; -#[derive(Debug, Default, Deserialize, utoipa::ToSchema)] +#[derive(Debug, Default, Deserialize)] pub enum DeletionMode { #[default] #[serde(alias = "cancel")] @@ -46,7 +46,7 @@ pub enum DeletionMode { #[serde(alias = "purge")] Purge, } -#[derive(Debug, Default, Deserialize, utoipa::ToSchema)] +#[derive(Debug, Default, Deserialize)] pub struct DeleteInvocationParams { pub mode: Option, } @@ -54,26 +54,6 @@ pub struct DeleteInvocationParams { /// Delete an invocation /// /// Use kill_invocation/cancel_invocation/purge_invocation instead. -#[utoipa::path( - delete, - path = "/invocations/{invocation_id}", - operation_id = "delete_invocation", - tag = "invocation", - params( - ("invocation_id" = String, Path, description = "Invocation identifier."), - ( - "mode" = Option, Query, - description = "If cancel, it will gracefully terminate the invocation. \ - If kill, it will terminate the invocation with a hard stop. \ - If purge, it will only cleanup the response for completed invocations, - and leave unaffected an in-flight invocation." - ), - ), - responses( - (status = 202, description = "Accepted"), - MetaApiError - ) -)] #[deprecated] pub async fn delete_invocation( State(mut state): State< diff --git a/crates/admin/src/rest_api/mod.rs b/crates/admin/src/rest_api/mod.rs index f8c815930d..a267764d25 100644 --- a/crates/admin/src/rest_api/mod.rs +++ b/crates/admin/src/rest_api/mod.rs @@ -102,7 +102,6 @@ where .routes(routes!(handlers::list_service_handlers)) .routes(routes!(handlers::get_service_handler)) // Invocation endpoints - .routes(routes!(invocations::delete_invocation)) .routes(routes!(invocations::kill_invocation)) .routes(routes!(invocations::cancel_invocation)) .routes(routes!(invocations::purge_invocation)) @@ -135,6 +134,12 @@ where "/deployments/{deployment}", axum::routing::put(deployments::update_deployment), ) + // Deprecated DELETE invocation + .route( + "/invocations/{invocation_id}", + #[allow(deprecated)] + axum::routing::delete(invocations::delete_invocation), + ) // Internal batch operation routes (for UI only, not documented in OpenAPI) .route( "/internal/invocations_batch_operations/kill",