@@ -142,6 +142,12 @@ pub fn router() -> Router<AppState> {
|
||||
get(timeline_api),
|
||||
)
|
||||
.route("/api/orgs/{org}/timeline", get(org_timeline_api))
|
||||
.route("/orgs/{org}/compute", get(compute_page))
|
||||
.route(
|
||||
"/orgs/{org}/compute/rollouts/{rollout_id}",
|
||||
get(rollout_detail_page),
|
||||
)
|
||||
.route("/api/compute/regions", get(regions_api))
|
||||
}
|
||||
|
||||
fn orgs_context(orgs: &[CachedOrg]) -> Vec<minijinja::Value> {
|
||||
@@ -4989,3 +4995,202 @@ async fn get_plan_output_api(
|
||||
}))
|
||||
.into_response())
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Compute
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
async fn compute_page(
|
||||
State(state): State<AppState>,
|
||||
session: Session,
|
||||
Path(org): Path<String>,
|
||||
) -> Result<Response, Response> {
|
||||
let orgs = &session.user.orgs;
|
||||
let _cached_org = require_org_membership(&state, orgs, &org)?;
|
||||
|
||||
let (instances, rollouts) = if let Some(ref scheduler) = state.compute_scheduler {
|
||||
let namespace = &org;
|
||||
let instances = scheduler
|
||||
.list_instances(namespace)
|
||||
.await
|
||||
.unwrap_or_default();
|
||||
let rollouts = scheduler
|
||||
.list_rollouts(namespace)
|
||||
.await
|
||||
.unwrap_or_default();
|
||||
(instances, rollouts)
|
||||
} else {
|
||||
(vec![], vec![])
|
||||
};
|
||||
|
||||
let instances_ctx: Vec<minijinja::Value> = instances
|
||||
.iter()
|
||||
.map(|i| {
|
||||
context! {
|
||||
id => i.id,
|
||||
resource_name => i.resource_name,
|
||||
project => i.project,
|
||||
destination => i.destination,
|
||||
environment => i.environment,
|
||||
image => i.image,
|
||||
region => i.region,
|
||||
replicas => i.replicas,
|
||||
cpu => i.cpu,
|
||||
memory => i.memory,
|
||||
status => i.status,
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let rollouts_ctx: Vec<minijinja::Value> = rollouts
|
||||
.iter()
|
||||
.take(20)
|
||||
.map(|r| {
|
||||
let resources: Vec<minijinja::Value> = r
|
||||
.resources
|
||||
.iter()
|
||||
.map(|res| {
|
||||
context! {
|
||||
name => res.name,
|
||||
kind => res.kind.to_string(),
|
||||
status => res.status.to_string(),
|
||||
message => res.message,
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
context! {
|
||||
id => r.id,
|
||||
apply_id => r.apply_id,
|
||||
namespace => r.namespace,
|
||||
status => r.status.to_string(),
|
||||
resources => resources,
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let projects = warn_default(
|
||||
"compute: list projects",
|
||||
state
|
||||
.platform_client
|
||||
.list_projects(&session.access_token, &org)
|
||||
.await,
|
||||
);
|
||||
|
||||
let html = state
|
||||
.templates
|
||||
.render(
|
||||
"pages/compute.html.jinja",
|
||||
context! {
|
||||
title => format!("Compute - {} - Forage", org),
|
||||
description => "Managed compute instances",
|
||||
user => context! { username => session.user.username },
|
||||
csrf_token => &session.csrf_token,
|
||||
orgs => orgs_context(orgs),
|
||||
current_org => &org,
|
||||
active_tab => "compute",
|
||||
projects => projects,
|
||||
instances => instances_ctx,
|
||||
rollouts => rollouts_ctx,
|
||||
org_name => &org,
|
||||
},
|
||||
)
|
||||
.map_err(|e| internal_error(&state, "compute render", &e))?;
|
||||
|
||||
Ok(Html(html).into_response())
|
||||
}
|
||||
|
||||
async fn rollout_detail_page(
|
||||
State(state): State<AppState>,
|
||||
session: Session,
|
||||
Path((org, rollout_id)): Path<(String, String)>,
|
||||
) -> Result<Response, Response> {
|
||||
let orgs = &session.user.orgs;
|
||||
let _cached_org = require_org_membership(&state, orgs, &org)?;
|
||||
|
||||
let scheduler = state.compute_scheduler.as_ref().ok_or_else(|| {
|
||||
error_page(
|
||||
&state,
|
||||
StatusCode::NOT_FOUND,
|
||||
"Not available",
|
||||
"Compute is not enabled.",
|
||||
)
|
||||
})?;
|
||||
|
||||
let rollout = scheduler.get_rollout(&rollout_id).await.map_err(|_| {
|
||||
error_page(
|
||||
&state,
|
||||
StatusCode::NOT_FOUND,
|
||||
"Not found",
|
||||
"Rollout not found.",
|
||||
)
|
||||
})?;
|
||||
|
||||
let resources_ctx: Vec<minijinja::Value> = rollout
|
||||
.resources
|
||||
.iter()
|
||||
.map(|r| {
|
||||
context! {
|
||||
name => r.name,
|
||||
kind => r.kind.to_string(),
|
||||
status => r.status.to_string(),
|
||||
message => r.message,
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let labels_ctx: Vec<minijinja::Value> = rollout.labels.iter().map(|(k, v)| context! { key => k, value => v }).collect();
|
||||
|
||||
let rollout_ctx = context! {
|
||||
id => rollout.id,
|
||||
apply_id => rollout.apply_id,
|
||||
namespace => rollout.namespace,
|
||||
status => rollout.status.to_string(),
|
||||
resources => resources_ctx,
|
||||
labels => labels_ctx,
|
||||
};
|
||||
|
||||
let projects = warn_default(
|
||||
"rollout detail: list projects",
|
||||
state
|
||||
.platform_client
|
||||
.list_projects(&session.access_token, &org)
|
||||
.await,
|
||||
);
|
||||
|
||||
let html = state
|
||||
.templates
|
||||
.render(
|
||||
"pages/rollout_detail.html.jinja",
|
||||
context! {
|
||||
title => format!("Rollout {} - Forage", rollout.apply_id),
|
||||
description => "Rollout details",
|
||||
user => context! { username => session.user.username },
|
||||
csrf_token => &session.csrf_token,
|
||||
orgs => orgs_context(orgs),
|
||||
current_org => &org,
|
||||
active_tab => "compute",
|
||||
projects => projects,
|
||||
rollout => rollout_ctx,
|
||||
org_name => &org,
|
||||
},
|
||||
)
|
||||
.map_err(|e| internal_error(&state, "rollout detail render", &e))?;
|
||||
|
||||
Ok(Html(html).into_response())
|
||||
}
|
||||
|
||||
async fn regions_api() -> impl IntoResponse {
|
||||
let regions: Vec<serde_json::Value> = forage_core::compute::REGIONS
|
||||
.iter()
|
||||
.map(|r| {
|
||||
serde_json::json!({
|
||||
"id": r.id,
|
||||
"name": r.name,
|
||||
"display_name": r.display_name,
|
||||
"available": r.available,
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
|
||||
Json(regions)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user