Skip to content

Commit bcf347e

Browse files
authored
Merge pull request #2 from Embucket/CP-5
Initial stub for UI api
2 parents ca4c60d + 7256cc3 commit bcf347e

File tree

23 files changed

+1896
-32
lines changed

23 files changed

+1896
-32
lines changed

crates/catalog/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
pub mod service;
2-
pub mod repository;
1+
pub mod error;
32
pub mod models;
4-
pub mod error;
3+
pub mod repository;
4+
pub mod service;

crates/control_plane/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,3 @@ pub mod repository; // This will expose everything inside repository.rs
88
pub mod service; // This will expose everything inside service.rs
99

1010
pub mod error;
11-

crates/nexus/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ utils = { path = "../utils" }
2424
utoipa = { workspace = true }
2525
utoipa-axum = { workspace = true }
2626
utoipa-swagger-ui = { workspace = true }
27+
swagger = { version = "6.1", features = ["serdejson", "server", "client", "tls", "tcp"] }
28+
validator = { version = "0.18.1", features = ["derive"] }
29+
thiserror = { version = "1.0.63" }
2730

2831
[dev-dependencies]
2932
tower = { workspace = true }

crates/nexus/src/http/control/handlers/storage_profiles.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,35 @@
11
use crate::http::control::schemas::storage_profiles::{
2-
AwsAccessKeyCredential, AwsRoleCredential, CloudProvider, CreateStorageProfilePayload, Credentials, StorageProfile
2+
AwsAccessKeyCredential, AwsRoleCredential, CloudProvider, CreateStorageProfilePayload,
3+
Credentials, StorageProfile,
34
};
45
use axum::{extract::Path, extract::State, Json};
56
use control_plane::models::{StorageProfile as StorageProfileModel, StorageProfileCreateRequest};
67
use std::result::Result;
7-
use uuid::Uuid;
88
use utoipa::OpenApi;
9+
use uuid::Uuid;
910

1011
use crate::error::AppError;
1112
use crate::state::AppState;
1213

13-
1414
#[derive(OpenApi)]
1515
#[openapi(
16-
paths(create_storage_profile, get_storage_profile, delete_storage_profile, list_storage_profiles,),
17-
components(schemas(CreateStorageProfilePayload, StorageProfile, Credentials, AwsAccessKeyCredential, AwsRoleCredential, CloudProvider),)
16+
paths(
17+
create_storage_profile,
18+
get_storage_profile,
19+
delete_storage_profile,
20+
list_storage_profiles,
21+
),
22+
components(schemas(
23+
CreateStorageProfilePayload,
24+
StorageProfile,
25+
Credentials,
26+
AwsAccessKeyCredential,
27+
AwsRoleCredential,
28+
CloudProvider
29+
),)
1830
)]
1931
pub struct StorageProfileApi;
2032

21-
2233
#[utoipa::path(
2334
post,
2435
operation_id = "createStorageProfile",

crates/nexus/src/http/control/handlers/warehouses.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
use crate::http::control::schemas::warehouses::{
2-
CreateWarehouseRequest, Warehouse,
3-
};
1+
use crate::http::control::schemas::warehouses::{CreateWarehouseRequest, Warehouse};
42
use axum::{extract::Path, extract::State, Json};
53
use control_plane::models::{Warehouse as WarehouseModel, WarehouseCreateRequest};
64
use std::result::Result;
@@ -10,7 +8,6 @@ use uuid::Uuid;
108
use crate::error::AppError;
119
use crate::state::AppState;
1210

13-
1411
// #[derive(OpenApi)]
1512
// #[openapi(
1613
// paths(create_storage_profile, get_storage_profile, delete_storage_profile, list_storage_profiles,),
@@ -21,7 +18,7 @@ use crate::state::AppState;
2118
#[derive(OpenApi)]
2219
#[openapi(
2320
paths(create_warehouse, get_warehouse, delete_warehouse, list_warehouses,),
24-
components(schemas(CreateWarehouseRequest, Warehouse, ),)
21+
components(schemas(CreateWarehouseRequest, Warehouse,),)
2522
)]
2623
pub struct WarehouseApi;
2724

crates/nexus/src/http/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,8 @@ pub mod control {
44
pub mod handlers;
55
pub mod schemas;
66
}
7+
pub mod ui {
8+
pub mod handlers;
9+
pub mod models;
10+
pub mod models;
11+
}

crates/nexus/src/http/router.rs

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
1-
use axum::extract::Path;
2-
use axum::{routing::delete, routing::get, routing::post, Router};
3-
use std::collections::HashMap;
1+
use axum::Router;
42
use std::fs;
5-
use utoipa::openapi::{self, OpenApiBuilder};
3+
use utoipa::openapi::{self};
64
use utoipa::{
7-
openapi::security::{ApiKey, ApiKeyValue, SecurityScheme},
85
Modify, OpenApi,
96
};
107
use utoipa_swagger_ui::SwaggerUi;
@@ -13,6 +10,11 @@ use crate::http::catalog::router::create_router as create_catalog_router;
1310
use crate::http::control::handlers::storage_profiles::StorageProfileApi;
1411
use crate::http::control::handlers::warehouses::WarehouseApi;
1512
use crate::http::control::router::create_router as create_control_router;
13+
use crate::http::ui::handlers::databases::ApiDoc as DatabaseApiDoc;
14+
use crate::http::ui::handlers::profiles::ApiDoc as ProfileApiDoc;
15+
use crate::http::ui::handlers::tables::ApiDoc as TableApiDoc;
16+
use crate::http::ui::handlers::warehouses::ApiDoc as WarehouseApiDoc;
17+
use crate::http::ui::router::create_router as create_ui_router;
1618
use crate::state::AppState;
1719

1820
#[derive(OpenApi)]
@@ -24,21 +26,28 @@ use crate::state::AppState;
2426
tags(
2527
(name = "storage-profile", description = "Storage profile API"),
2628
(name = "warehouse", description = "Warehouse API"),
29+
(name = "ui", description = "Web UI API"),
2730
)
2831
)]
29-
struct ApiDoc;
32+
pub struct ApiDoc;
3033

3134
pub fn create_app(state: AppState) -> Router {
3235
let mut spec = ApiDoc::openapi();
3336
if let Some(extra_spec) = load_openapi_spec() {
34-
spec = spec.merge_from(extra_spec);
37+
spec = spec.merge_from(extra_spec)
38+
.merge_from(WarehouseApiDoc::openapi())
39+
.merge_from(TableApiDoc::openapi())
40+
.merge_from(DatabaseApiDoc::openapi())
41+
.merge_from(ProfileApiDoc::openapi());
3542
}
3643
let catalog_router = create_catalog_router();
3744
let control_router = create_control_router();
45+
let ui_router = create_ui_router();
3846

3947
Router::new()
4048
.nest("/", control_router)
4149
.nest("/catalog", catalog_router)
50+
.nest("/ui", ui_router)
4251
.merge(SwaggerUi::new("/").url("/openapi.yaml", spec))
4352
.with_state(state)
4453
}
@@ -56,26 +65,20 @@ mod tests {
5665
#![allow(clippy::too_many_lines)]
5766

5867
use crate::http::catalog::schemas::Namespace as NamespaceSchema;
59-
use crate::http::control;
6068
use crate::http::control::schemas::storage_profiles::StorageProfile as StorageProfileSchema;
6169
use crate::http::control::schemas::warehouses::Warehouse as WarehouseSchema;
6270

6371
use super::*;
64-
use async_trait::async_trait;
65-
use axum::http::request;
6672
use axum::{
6773
body::Body,
6874
http::{self, Request, StatusCode},
6975
};
7076
use catalog::repository::{DatabaseRepositoryDb, TableRepositoryDb};
7177
use catalog::service::CatalogImpl;
72-
use control_plane::error::{Error, Result};
73-
use control_plane::models::{StorageProfile, StorageProfileCreateRequest};
74-
use control_plane::models::{Warehouse, WarehouseCreateRequest};
7578
use control_plane::repository::{StorageProfileRepositoryDb, WarehouseRepositoryDb};
76-
use control_plane::service::ControlService;
7779
use control_plane::service::ControlServiceImpl;
78-
use http_body_util::BodyExt; // for `collect`
80+
use http_body_util::BodyExt;
81+
// for `collect`
7982
use object_store::{memory::InMemory, path::Path, ObjectStore};
8083
use serde_json::json;
8184
use slatedb::config::DbOptions;
@@ -84,7 +87,6 @@ mod tests {
8487
use tempfile::TempDir;
8588
use tower::{Service, ServiceExt};
8689
use utils::Db;
87-
use uuid::Uuid;
8890

8991
lazy_static::lazy_static! {
9092
static ref TEMP_DIR: TempDir = TempDir::new().unwrap();
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
use crate::error::AppError;
2+
use crate::http::ui::models::aws;
3+
use crate::http::ui::models::database;
4+
use crate::http::ui::models::storage_profile;
5+
use crate::http::ui::models::table::Statistics;
6+
use crate::http::ui::models::warehouse;
7+
use crate::state::AppState;
8+
use axum::{extract::Path, extract::State, Json};
9+
use swagger;
10+
use utoipa::OpenApi;
11+
use uuid::Uuid;
12+
13+
#[derive(OpenApi)]
14+
#[openapi(
15+
paths(
16+
create_database,
17+
delete_database,
18+
get_database,
19+
),
20+
components(
21+
schemas(
22+
database::CreateDatabasePayload,
23+
database::Database
24+
)
25+
),
26+
tags(
27+
(name = "Databases", description = "Databases management endpoints.")
28+
)
29+
)]
30+
pub struct ApiDoc;
31+
32+
#[utoipa::path(
33+
post,
34+
path = "/ui/warehouses/{warehouseId}/databases",
35+
operation_id = "webCreateDatabase",
36+
responses(
37+
(status = 200, description = "Successful Response", body = database::Database),
38+
(status = 400, description = "Bad request"),
39+
(status = 500, description = "Internal server error")
40+
)
41+
)]
42+
pub async fn create_database(
43+
State(state): State<AppState>,
44+
Path(payload): Path<database::CreateDatabasePayload>,
45+
) -> Result<Json<database::Database>, AppError> {
46+
Ok(Json(database::Database {
47+
name: "".to_string(),
48+
properties: None,
49+
id: Default::default(),
50+
warehouse_id: Default::default(),
51+
}))
52+
}
53+
54+
#[utoipa::path(
55+
delete,
56+
path = "/ui/warehouses/{warehouseId}/databases/{databaseName}",
57+
operation_id = "webDeleteDatabase",
58+
responses(
59+
(status = 204, description = "Successful Response"),
60+
(status = 404, description = "Database not found")
61+
)
62+
)]
63+
pub async fn delete_database(
64+
State(state): State<AppState>,
65+
Path((warehouse_id, database_name)): Path<(Uuid, String)>,
66+
) -> Result<(), AppError> {
67+
Ok(())
68+
}
69+
70+
#[utoipa::path(
71+
get,
72+
path = "/ui/warehouses/{warehouseId}/databases/{databaseName}",
73+
operation_id = "webDatabaseDashboard",
74+
responses(
75+
(status = 200, description = "Successful Response", body = database::DatabaseDashboard),
76+
(status = 204, description = "Successful Response"),
77+
(status = 404, description = "Database not found")
78+
)
79+
)]
80+
pub async fn get_database(
81+
State(state): State<AppState>,
82+
Path((warehouse_id, database_name)): Path<(Uuid, String)>,
83+
) -> Result<Json<database::DatabaseDashboard>, AppError> {
84+
Ok(Json(database::DatabaseDashboard {
85+
name: "".to_string(),
86+
properties: None,
87+
id: Default::default(),
88+
warehouse_id: Default::default(),
89+
warehouse: warehouse::WarehouseEntity {
90+
name: "".to_string(),
91+
storage_profile_id: Default::default(),
92+
key_prefix: "".to_string(),
93+
id: Default::default(),
94+
external_id: Default::default(),
95+
location: "".to_string(),
96+
created_at: Default::default(),
97+
updated_at: Default::default(),
98+
storage_profile: storage_profile::StorageProfile {
99+
r#type: aws::CloudProvider::S3,
100+
region: "".to_string(),
101+
bucket: "".to_string(),
102+
credentials: Default::default(),
103+
sts_role_arn: None,
104+
endpoint: None,
105+
id: Default::default(),
106+
created_at: Default::default(),
107+
updated_at: Default::default(),
108+
},
109+
},
110+
tables: vec![],
111+
statistics: Statistics {
112+
commit_count: 0,
113+
op_append_count: 0,
114+
op_overwrite_count: 0,
115+
op_delete_count: 0,
116+
op_replace_count: 0,
117+
total_bytes: 0,
118+
bytes_added: 0,
119+
bytes_removed: 0,
120+
total_rows: 0,
121+
rows_added: 0,
122+
rows_deleted: 0,
123+
table_count: None,
124+
database_count: None,
125+
},
126+
compaction_summary: None,
127+
}))
128+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
pub mod databases;
2+
pub mod profiles;
3+
pub mod tables;
4+
pub mod warehouses;

0 commit comments

Comments
 (0)