From 8d4af018e2b1148a51c7632e39818adf2ee9aa0c Mon Sep 17 00:00:00 2001 From: Iulian Barbu Date: Thu, 13 Apr 2023 18:03:23 +0300 Subject: [PATCH] deployer: added OpenAPI docs --- Cargo.lock | 91 ++++++++++++ Cargo.toml | 2 + common/Cargo.toml | 1 + common/src/database.rs | 8 +- common/src/deployment.rs | 4 +- common/src/log.rs | 11 +- common/src/models/deployment.rs | 8 +- common/src/models/secret.rs | 4 +- common/src/models/service.rs | 13 +- common/src/resource.rs | 11 +- deployer/Cargo.toml | 2 + deployer/src/handlers/mod.rs | 187 +++++++++++++++++++++++-- deployer/src/lib.rs | 4 +- deployer/src/persistence/deployment.rs | 3 +- deployer/src/persistence/mod.rs | 6 +- deployer/src/persistence/state.rs | 3 +- 16 files changed, 326 insertions(+), 32 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5e2882962..c4020df77 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4550,6 +4550,41 @@ dependencies = [ "serde", ] +[[package]] +name = "rust-embed" +version = "6.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b68543d5527e158213414a92832d2aab11a84d2571a5eb021ebe22c43aab066" +dependencies = [ + "rust-embed-impl", + "rust-embed-utils", + "walkdir", +] + +[[package]] +name = "rust-embed-impl" +version = "6.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d4e0f0ced47ded9a68374ac145edd65a6c1fa13a96447b873660b2a568a0fd7" +dependencies = [ + "proc-macro2", + "quote", + "rust-embed-utils", + "shellexpand", + "syn 1.0.109", + "walkdir", +] + +[[package]] +name = "rust-embed-utils" +version = "7.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512b0ab6853f7e14e3c8754acb43d6f748bb9ced66aa5915a6553ac8213f7731" +dependencies = [ + "sha2 0.10.6", + "walkdir", +] + [[package]] name = "rustc-demangle" version = "0.1.21" @@ -5110,6 +5145,7 @@ dependencies = [ "tracing-opentelemetry", "tracing-subscriber", "ttl_cache", + "utoipa", "uuid", ] @@ -5158,6 +5194,8 @@ dependencies = [ "tracing", "tracing-opentelemetry", "tracing-subscriber", + "utoipa", + "utoipa-swagger-ui", "uuid", ] @@ -6529,6 +6567,47 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +[[package]] +name = "utoipa" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24e7ee17c9ef094b86e1e04170d90765bd76cb381921dacb4d3e175a267bdae6" +dependencies = [ + "indexmap", + "serde", + "serde_json", + "utoipa-gen", +] + +[[package]] +name = "utoipa-gen" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df6f458e5abc811d44aca28455efc4163fb7565a7af2aa32d17611f3d1d9794d" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.5", + "uuid", +] + +[[package]] +name = "utoipa-swagger-ui" +version = "3.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "062bba5a3568e126ac72049a63254f4cb1da2eb713db0c1ab2a4c76be191db8c" +dependencies = [ + "axum", + "mime_guess", + "regex", + "rust-embed", + "serde", + "serde_json", + "utoipa", + "zip", +] + [[package]] name = "uuid" version = "1.3.0" @@ -7386,6 +7465,18 @@ version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f" +[[package]] +name = "zip" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0445d0fbc924bb93539b4316c11afb121ea39296f99a3c4c9edad09e3658cdef" +dependencies = [ + "byteorder", + "crc32fast", + "crossbeam-utils", + "flate2", +] + [[package]] name = "zstd" version = "0.11.2+zstd.1.5.2" diff --git a/Cargo.toml b/Cargo.toml index 727450226..5575d6a86 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -93,4 +93,6 @@ tracing-subscriber = { version = "0.3.16", default-features = false, features = "std", ] } ttl_cache = "0.5.1" +utoipa = { version = "3.2.1", features = [ "uuid", "chrono" ] } +utoipa-swagger-ui = { version = "3.1.3", features = ["axum"] } uuid = "1.2.2" diff --git a/common/Cargo.toml b/common/Cargo.toml index 3c80d8e01..3277b1c17 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -40,6 +40,7 @@ tracing = { workspace = true, features = ["std"] } tracing-opentelemetry = { workspace = true, optional = true } tracing-subscriber = { workspace = true, optional = true } ttl_cache = { workspace = true, optional = true } +utoipa = { workspace = true } uuid = { workspace = true, features = ["v4", "serde"], optional = true } [features] diff --git a/common/src/database.rs b/common/src/database.rs index 1d3956ea0..f864b5f78 100644 --- a/common/src/database.rs +++ b/common/src/database.rs @@ -2,15 +2,17 @@ use std::fmt::Display; use serde::{Deserialize, Serialize}; use strum::Display; +use utoipa::ToSchema; -#[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq)] +#[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq, ToSchema)] #[serde(rename_all = "lowercase")] +#[schema(as = shuttle_common::database::Type)] pub enum Type { AwsRds(AwsRdsEngine), Shared(SharedEngine), } -#[derive(Clone, Debug, Deserialize, Display, Serialize, Eq, PartialEq)] +#[derive(Clone, Debug, Deserialize, Display, Serialize, Eq, PartialEq, ToSchema)] #[serde(rename_all = "lowercase")] #[strum(serialize_all = "lowercase")] pub enum AwsRdsEngine { @@ -19,7 +21,7 @@ pub enum AwsRdsEngine { MariaDB, } -#[derive(Clone, Debug, Deserialize, Display, Serialize, Eq, PartialEq)] +#[derive(Clone, Debug, Deserialize, Display, Serialize, Eq, PartialEq, ToSchema)] #[serde(rename_all = "lowercase")] #[strum(serialize_all = "lowercase")] pub enum SharedEngine { diff --git a/common/src/deployment.rs b/common/src/deployment.rs index 9b924709e..ed5736c62 100644 --- a/common/src/deployment.rs +++ b/common/src/deployment.rs @@ -1,9 +1,11 @@ use serde::{Deserialize, Serialize}; use strum::Display; +use utoipa::ToSchema; -#[derive(Clone, Debug, Deserialize, Display, Serialize)] +#[derive(Clone, Debug, Deserialize, Display, Serialize, ToSchema)] #[serde(rename_all = "lowercase")] #[strum(serialize_all = "lowercase")] +#[schema(as = shuttle_common::deployment::State)] pub enum State { Queued, Building, diff --git a/common/src/log.rs b/common/src/log.rs index 8e13e2fb3..b93fe0a0c 100644 --- a/common/src/log.rs +++ b/common/src/log.rs @@ -5,17 +5,23 @@ use chrono::{DateTime, Utc}; #[cfg(feature = "display")] use crossterm::style::{StyledContent, Stylize}; use serde::{Deserialize, Serialize}; +use utoipa::ToSchema; use uuid::Uuid; use crate::deployment::State; pub const STATE_MESSAGE: &str = "NEW STATE"; -#[derive(Clone, Debug, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize, ToSchema)] +#[schema(as = shuttle_common::log::Item)] pub struct Item { + #[schema(value_type = KnownFormat::Uuid)] pub id: Uuid, + #[schema(value_type = KnownFormat::DateTime)] pub timestamp: DateTime, + #[schema(value_type = shuttle_common::deployment::State)] pub state: State, + #[schema(value_type = shuttle_common::log::Level)] pub level: Level, pub file: Option, pub line: Option, @@ -77,8 +83,9 @@ impl std::fmt::Display for Item { } } -#[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq)] +#[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq, ToSchema)] #[serde(rename_all = "lowercase")] +#[schema(as = shuttle_common::log::Level)] pub enum Level { Trace, Debug, diff --git a/common/src/models/deployment.rs b/common/src/models/deployment.rs index 22c186c15..c2f8f49cb 100644 --- a/common/src/models/deployment.rs +++ b/common/src/models/deployment.rs @@ -7,15 +7,21 @@ use comfy_table::{ }; use crossterm::style::Stylize; use serde::{Deserialize, Serialize}; +use utoipa::ToSchema; use uuid::Uuid; use crate::deployment::State; -#[derive(Deserialize, Serialize)] +#[derive(Deserialize, Serialize, ToSchema)] +#[schema(as = shuttle_common::models::deployment::Response)] pub struct Response { + #[schema(value_type = KnownFormat::Uuid)] pub id: Uuid, + #[schema(value_type = KnownFormat::Uuid)] pub service_id: Uuid, + #[schema(value_type = shuttle_common::deployment::State)] pub state: State, + #[schema(value_type = KnownFormat::DateTime)] pub last_update: DateTime, } diff --git a/common/src/models/secret.rs b/common/src/models/secret.rs index e03664e33..b7d13700e 100644 --- a/common/src/models/secret.rs +++ b/common/src/models/secret.rs @@ -5,10 +5,12 @@ use comfy_table::{ }; use crossterm::style::Stylize; use serde::{Deserialize, Serialize}; +use utoipa::ToSchema; -#[derive(Deserialize, Serialize)] +#[derive(Deserialize, Serialize, ToSchema)] pub struct Response { pub key: String, + #[schema(value_type = KnownFormat::DateTime)] pub last_update: DateTime, } diff --git a/common/src/models/service.rs b/common/src/models/service.rs index 4eff0ad6f..53bcd2cf8 100644 --- a/common/src/models/service.rs +++ b/common/src/models/service.rs @@ -1,19 +1,24 @@ -use crate::models::deployment; - use crossterm::style::Stylize; use serde::{Deserialize, Serialize}; use std::fmt::Display; +use utoipa::ToSchema; use uuid::Uuid; -#[derive(Deserialize, Serialize)] +use crate::models::deployment; + +#[derive(Deserialize, Serialize, ToSchema)] +#[schema(as = shuttle_common::models::service::Response)] pub struct Response { + #[schema(value_type = KnownFormat::Uuid)] pub id: Uuid, pub name: String, } -#[derive(Deserialize, Serialize)] +#[derive(Deserialize, Serialize, ToSchema)] +#[schema(as = shuttle_common::models::service::Summary)] pub struct Summary { pub name: String, + #[schema(value_type = shuttle_common::models::deployment::Response)] pub deployment: Option, pub uri: String, } diff --git a/common/src/resource.rs b/common/src/resource.rs index cec5af3e8..f4287ccfc 100644 --- a/common/src/resource.rs +++ b/common/src/resource.rs @@ -2,25 +2,32 @@ use std::fmt::Display; use serde::{Deserialize, Serialize}; use serde_json::Value; +use utoipa::ToSchema; use crate::database; /// Common type to hold all the information we need for a generic resource -#[derive(Clone, Deserialize, Serialize)] +#[derive(Clone, Deserialize, Serialize, ToSchema)] +#[schema(as = shuttle_common::resource::Response)] pub struct Response { /// The type of this resource. + #[schema(value_type = shuttle_common::resource::Type)] pub r#type: Type, /// The config used when creating this resource. Use the [Self::r#type] to know how to parse this data. + #[schema(value_type = object)] pub config: Value, /// The data associated with this resource. Use the [Self::r#type] to know how to parse this data. + #[schema(value_type = object)] pub data: Value, } -#[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq)] +#[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq, ToSchema)] #[serde(rename_all = "lowercase")] +#[schema(as = shuttle_common::resource::Type)] pub enum Type { + #[schema(value_type = shuttle_common::database::Type)] Database(database::Type), Secrets, StaticFolder, diff --git a/deployer/Cargo.toml b/deployer/Cargo.toml index c7f99a769..deba2cb8b 100644 --- a/deployer/Cargo.toml +++ b/deployer/Cargo.toml @@ -52,6 +52,8 @@ tracing-subscriber = { workspace = true, features = [ "env-filter", "fmt", ] } +utoipa = { workspace = true } +utoipa-swagger-ui = { workspace = true } uuid = { workspace = true, features = ["v4"] } [dependencies.shuttle-common] diff --git a/deployer/src/handlers/mod.rs b/deployer/src/handlers/mod.rs index c5fae49d2..19d0c99f9 100644 --- a/deployer/src/handlers/mod.rs +++ b/deployer/src/handlers/mod.rs @@ -12,9 +12,7 @@ use chrono::{TimeZone, Utc}; use fqdn::FQDN; use futures::StreamExt; use hyper::Uri; -use shuttle_common::backends::auth::{ - AdminSecretLayer, AuthPublicKey, JwtAuthenticationLayer, ScopedLayer, -}; +use shuttle_common::backends::auth::{AuthPublicKey, JwtAuthenticationLayer, ScopedLayer}; use shuttle_common::backends::headers::XShuttleAccountName; use shuttle_common::backends::metrics::{Metrics, TraceLayer}; use shuttle_common::claims::{Claim, Scope}; @@ -24,6 +22,8 @@ use shuttle_common::storage_manager::StorageManager; use shuttle_common::{request_span, LogItem}; use shuttle_service::builder::clean_crate; use tracing::{debug, error, field, instrument, trace}; +use utoipa::OpenApi; +use utoipa_swagger_ui::SwaggerUi; use uuid::Uuid; use crate::deployment::{DeploymentManager, Queued}; @@ -35,23 +35,56 @@ pub use {self::error::Error, self::error::Result}; mod project; +#[derive(OpenApi)] +#[openapi( + paths( + get_services, + get_service, + create_service, + stop_service, + get_service_resources, + get_deployments, + get_deployment, + delete_deployment, + get_logs_subscribe, + get_logs, + get_secrets, + clean_project + ), + components(schemas( + shuttle_common::models::service::Summary, + shuttle_common::resource::Response, + shuttle_common::resource::Type, + shuttle_common::database::Type, + shuttle_common::database::AwsRdsEngine, + shuttle_common::database::SharedEngine, + shuttle_common::models::service::Response, + shuttle_common::models::deployment::Response, + shuttle_common::log::Item, + shuttle_common::models::secret::Response, + shuttle_common::log::Level, + shuttle_common::deployment::State + )) +)] +struct ApiDoc; + pub async fn make_router( persistence: Persistence, deployment_manager: DeploymentManager, proxy_fqdn: FQDN, - admin_secret: String, + _admin_secret: String, auth_uri: Uri, project_name: ProjectName, ) -> Router { Router::new() .route( "/projects/:project_name/services", - get(list_services.layer(ScopedLayer::new(vec![Scope::Service]))), + get(get_services.layer(ScopedLayer::new(vec![Scope::Service]))), ) .route( "/projects/:project_name/services/:service_name", get(get_service.layer(ScopedLayer::new(vec![Scope::Service]))) - .post(post_service.layer(ScopedLayer::new(vec![Scope::ServiceCreate]))) + .post(create_service.layer(ScopedLayer::new(vec![Scope::ServiceCreate]))) .delete(stop_service.layer(ScopedLayer::new(vec![Scope::ServiceCreate]))), ) .route( @@ -81,13 +114,13 @@ pub async fn make_router( ) .route( "/projects/:project_name/clean", - post(post_clean.layer(ScopedLayer::new(vec![Scope::DeploymentPush]))), + post(clean_project.layer(ScopedLayer::new(vec![Scope::DeploymentPush]))), ) .layer(Extension(persistence)) .layer(Extension(deployment_manager)) .layer(Extension(proxy_fqdn)) .layer(JwtAuthenticationLayer::new(AuthPublicKey::new(auth_uri))) - .layer(AdminSecretLayer::new(admin_secret)) + // .layer(AdminSecretLayer::new(admin_secret)) // This route should be below the auth bearer since it does not need authentication .route("/projects/:project_name/status", get(get_status)) .route_layer(from_extractor::()) @@ -110,11 +143,22 @@ pub async fn make_router( .build(), ) .route_layer(from_extractor::()) + .merge(SwaggerUi::new("/swagger-ui").url("/api-docs/openapi.json", ApiDoc::openapi())) .layer(Extension(project_name)) } #[instrument(skip_all)] -async fn list_services( +#[utoipa::path( + get, + path = "/projects/{project_name}/services", + responses( + (status = 200, description = "Lists the services owned by a project.", body = [shuttle_common::models::service::Response]) + ), + params( + ("project_name" = String, Path, description = "Name of the project that owns the services."), + ) +)] +async fn get_services( Extension(persistence): Extension, ) -> Result>> { let services = persistence @@ -128,6 +172,18 @@ async fn list_services( } #[instrument(skip_all, fields(%project_name, %service_name))] +#[instrument(skip_all)] +#[utoipa::path( + get, + path = "/projects/{project_name}/services/{service_name}", + responses( + (status = 200, description = "Gets a specific service summary.", body = shuttle_common::models::service::Summary) + ), + params( + ("project_name" = String, Path, description = "Name of the project that owns the service."), + ("service_name" = String, Path, description = "Name of the service.") + ) +)] async fn get_service( Extension(persistence): Extension, Extension(proxy_fqdn): Extension, @@ -152,6 +208,17 @@ async fn get_service( } #[instrument(skip_all, fields(%project_name, %service_name))] +#[utoipa::path( + get, + path = "/projects/{project_name}/services/{service_name}/resources", + responses( + (status = 200, description = "Gets a specific service resources.", body = shuttle_common::resource::Response) + ), + params( + ("project_name" = String, Path, description = "Name of the project that owns the service."), + ("service_name" = String, Path, description = "Name of the service.") + ) +)] async fn get_service_resources( Extension(persistence): Extension, Path((project_name, service_name)): Path<(String, String)>, @@ -171,7 +238,18 @@ async fn get_service_resources( } #[instrument(skip_all, fields(%project_name, %service_name))] -async fn post_service( +#[utoipa::path( + post, + path = "/projects/{project_name}/services/{service_name}", + responses( + (status = 200, description = "Creates a specific service owned by a specific project.", body = shuttle_common::models::deployment::Response) + ), + params( + ("project_name" = String, Path, description = "Name of the project that owns the service."), + ("service_name" = String, Path, description = "Name of the service.") + ) +)] +async fn create_service( Extension(persistence): Extension, Extension(deployment_manager): Extension, Extension(claim): Extension, @@ -217,6 +295,17 @@ async fn post_service( } #[instrument(skip_all, fields(%project_name, %service_name))] +#[utoipa::path( + delete, + path = "/projects/{project_name}/services/{service_name}", + responses( + (status = 200, description = "Stops a specific service owned by a specific project.", body = shuttle_common::models::service::Summary) + ), + params( + ("project_name" = String, Path, description = "Name of the project that owns the service."), + ("service_name" = String, Path, description = "Name of the service.") + ) +)] async fn stop_service( Extension(persistence): Extension, Extension(deployment_manager): Extension, @@ -245,6 +334,16 @@ async fn stop_service( } #[instrument(skip(persistence))] +#[utoipa::path( + get, + path = "/projects/{project_name}/deployments", + responses( + (status = 200, description = "Gets deployments information associated to a specific project.", body = shuttle_common::models::deployment::Response) + ), + params( + ("project_name" = String, Path, description = "Name of the project that owns the deployments.") + ) +)] async fn get_deployments( Extension(persistence): Extension, Path(project_name): Path, @@ -264,6 +363,18 @@ async fn get_deployments( } #[instrument(skip_all, fields(%project_name, %deployment_id))] +#[instrument(skip(persistence))] +#[utoipa::path( + get, + path = "/projects/{project_name}/deployments/{deployment_id}", + responses( + (status = 200, description = "Gets a specific deployment information.", body = shuttle_common::models::deployment::Response) + ), + params( + ("project_name" = String, Path, description = "Name of the project that owns the deployment."), + ("deployment_id" = String, Path, description = "The deployment id in uuid format.") + ) +)] async fn get_deployment( Extension(persistence): Extension, Path((project_name, deployment_id)): Path<(String, Uuid)>, @@ -276,6 +387,17 @@ async fn get_deployment( } #[instrument(skip_all, fields(%project_name, %deployment_id))] +#[utoipa::path( + delete, + path = "/projects/{project_name}/deployments/{deployment_id}", + responses( + (status = 200, description = "Deletes a specific deployment.", body = shuttle_common::models::deployment::Response) + ), + params( + ("project_name" = String, Path, description = "Name of the project that owns the deployment."), + ("deployment_id" = String, Path, description = "The deployment id in uuid format.") + ) +)] async fn delete_deployment( Extension(deployment_manager): Extension, Extension(persistence): Extension, @@ -291,6 +413,17 @@ async fn delete_deployment( } #[instrument(skip_all, fields(%project_name, %deployment_id))] +#[utoipa::path( + get, + path = "/projects/{project_name}/ws/deployments/{deployment_id}/logs", + responses( + (status = 200, description = "Gets the logs a specific deployment.", body = [shuttle_common::log::Item]) + ), + params( + ("project_name" = String, Path, description = "Name of the project that owns the deployment."), + ("deployment_id" = String, Path, description = "The deployment id in uuid format.") + ) +)] async fn get_logs( Extension(persistence): Extension, Path((project_name, deployment_id)): Path<(String, Uuid)>, @@ -309,6 +442,17 @@ async fn get_logs( } } +#[utoipa::path( + get, + path = "/projects/{project_name}/deployments/{deployment_id}/logs", + responses( + (status = 200, description = "Subscribes to a specific deployment logs.") + ), + params( + ("project_name" = String, Path, description = "Name of the project that owns the deployment."), + ("deployment_id" = String, Path, description = "The deployment id in uuid format.") + ) +)] async fn get_logs_subscribe( Extension(persistence): Extension, Path((_project_name, deployment_id)): Path<(String, Uuid)>, @@ -371,6 +515,17 @@ async fn logs_websocket_handler(mut s: WebSocket, persistence: Persistence, id: } #[instrument(skip_all, fields(%project_name, %service_name))] +#[utoipa::path( + get, + path = "/projects/{project_name}/secrets/{service_name}", + responses( + (status = 200, description = "Gets the secrets a specific service.", body = [shuttle_common::models::secret::Response]) + ), + params( + ("project_name" = String, Path, description = "Name of the project that owns the service."), + ("service_name" = String, Path, description = "Name of the service.") + ) +)] async fn get_secrets( Extension(persistence): Extension, Path((project_name, service_name)): Path<(String, String)>, @@ -389,7 +544,17 @@ async fn get_secrets( } } -async fn post_clean( +#[utoipa::path( + post, + path = "/projects/{project_name}/clean", + responses( + (status = 200, description = "Clean a specific project build artifacts.", body = [String]) + ), + params( + ("project_name" = String, Path, description = "Name of the project that owns the service."), + ) +)] +async fn clean_project( Extension(deployment_manager): Extension, Path(project_name): Path, ) -> Result>> { diff --git a/deployer/src/lib.rs b/deployer/src/lib.rs index 73912cb76..8b36de272 100644 --- a/deployer/src/lib.rs +++ b/deployer/src/lib.rs @@ -19,8 +19,8 @@ use crate::deployment::gateway_client::GatewayClient; mod args; mod deployment; mod error; -mod handlers; -mod persistence; +pub mod handlers; +pub mod persistence; mod proxy; mod runtime_manager; diff --git a/deployer/src/persistence/deployment.rs b/deployer/src/persistence/deployment.rs index b7e50f8b8..c79a0ee23 100644 --- a/deployer/src/persistence/deployment.rs +++ b/deployer/src/persistence/deployment.rs @@ -4,11 +4,12 @@ use async_trait::async_trait; use chrono::{DateTime, Utc}; use sqlx::{sqlite::SqliteRow, FromRow, Row}; use tracing::error; +use utoipa::ToSchema; use uuid::Uuid; use super::state::State; -#[derive(Clone, Debug, Eq, PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq, ToSchema)] pub struct Deployment { pub id: Uuid, pub service_id: Uuid, diff --git a/deployer/src/persistence/mod.rs b/deployer/src/persistence/mod.rs index 221b6bd30..7c90d2adf 100644 --- a/deployer/src/persistence/mod.rs +++ b/deployer/src/persistence/mod.rs @@ -1,9 +1,9 @@ -mod deployment; +pub mod deployment; mod error; -mod log; +pub mod log; mod resource; mod secret; -mod service; +pub mod service; mod state; mod user; diff --git a/deployer/src/persistence/state.rs b/deployer/src/persistence/state.rs index 77df04e9e..eb6331bf8 100644 --- a/deployer/src/persistence/state.rs +++ b/deployer/src/persistence/state.rs @@ -1,7 +1,8 @@ use strum::{Display, EnumString}; +use utoipa::ToSchema; /// States a deployment can be in -#[derive(sqlx::Type, Debug, Display, Clone, Copy, EnumString, PartialEq, Eq)] +#[derive(sqlx::Type, Debug, Display, Clone, Copy, EnumString, PartialEq, Eq, ToSchema)] pub enum State { /// Deployment is queued to be build Queued,