Report self-hosted admin bootstrap path

This commit is contained in:
Michel Paulissen 2026-07-04 12:10:15 +02:00
parent ab84fd382d
commit c836abc405
3 changed files with 168 additions and 4 deletions

View file

@ -2258,8 +2258,9 @@ fn admin_status_report(args: AdminStatusArgs) -> Result<Value> {
}
fn admin_bootstrap_report(args: AdminBootstrapArgs, cwd: PathBuf) -> Result<Value> {
let scope = args.scope.clone();
let new_project = args.scope.project.clone();
project_init_report(
let project_init = project_init_report(
ProjectInitArgs {
scope: args.scope,
new_project,
@ -2267,7 +2268,92 @@ fn admin_bootstrap_report(args: AdminBootstrapArgs, cwd: PathBuf) -> Result<Valu
yes: args.yes,
},
cwd,
)
)?;
let coordinator = scope
.coordinator
.clone()
.unwrap_or_else(|| "<local-coordinator>".to_owned());
let tenant = scope.tenant.clone();
let project = scope.project.clone();
let user = scope.user.clone();
Ok(json!({
"command": "admin bootstrap",
"mode": if scope.coordinator.is_some() { "public_coordinator_api" } else { "self_hosted_local" },
"tenant": tenant.clone(),
"project": project.clone(),
"user": user,
"coordinator": scope.coordinator,
"private_website_required": false,
"self_hosted_cli_only": true,
"project_config_written": project_init
.get("project_config_written")
.cloned()
.unwrap_or_else(|| json!(false)),
"project_init": project_init,
"admin_surfaces": {
"coordinator": "disasmer-coordinator",
"project": "disasmer project init/status/list/select",
"node": "disasmer node enroll/list/status/revoke",
"process": "disasmer run/process status/process restart/process cancel",
"logs": "disasmer logs",
"artifacts": "disasmer artifact list/download/export",
"quota": "disasmer quota status",
"policy": "disasmer admin status/suspend-tenant",
},
"bootstrap_sequence": [
{
"step": "start_self_hosted_coordinator",
"command": "disasmer-coordinator --listen 127.0.0.1:0",
"private_website_required": false,
},
{
"step": "create_or_link_project",
"command": "disasmer project init --yes",
"completed": true,
"private_website_required": false,
},
{
"step": "create_node_enrollment_grant",
"command": format!(
"disasmer node enroll --coordinator {coordinator} --tenant {} --project-id {}",
tenant, project
),
"private_website_required": false,
},
{
"step": "attach_worker_node",
"command": format!(
"disasmer node attach --coordinator {coordinator} --tenant {} --project-id {} --worker",
tenant, project
),
"private_website_required": false,
},
{
"step": "run_process",
"command": format!(
"disasmer run --coordinator {coordinator} --tenant {} --project-id {}",
tenant, project
),
"private_website_required": false,
},
{
"step": "inspect_status_logs_artifacts",
"commands": [
"disasmer process status",
"disasmer task list",
"disasmer logs",
"disasmer artifact list",
"disasmer quota status",
],
"private_website_required": false,
},
{
"step": "revoke_access",
"command": "disasmer admin revoke-node --node <node-id> --yes",
"private_website_required": false,
}
],
}))
}
fn admin_suspend_tenant_report(args: AdminSuspendTenantArgs) -> Result<Value> {
@ -7158,6 +7244,73 @@ mod tests {
}
}
#[test]
fn admin_bootstrap_reports_self_hosted_cli_only_path() {
let temp = tempfile::tempdir().unwrap();
let report = admin_bootstrap_report(
AdminBootstrapArgs {
scope: CliScopeArgs {
coordinator: None,
tenant: "team".to_owned(),
project: "self-hosted".to_owned(),
user: "admin".to_owned(),
json: false,
},
name: "Self Hosted".to_owned(),
yes: true,
},
temp.path().to_path_buf(),
)
.unwrap();
assert_eq!(report["command"], "admin bootstrap");
assert_eq!(report["mode"], "self_hosted_local");
assert_eq!(report["private_website_required"], false);
assert_eq!(report["self_hosted_cli_only"], true);
assert_eq!(report["project_config_written"], true);
assert_eq!(report["project_init"]["command"], "project init");
assert_eq!(report["project_init"]["private_website_required"], false);
assert_eq!(
report["project_init"]["project_config"]["project"],
"self-hosted"
);
assert_eq!(
report["admin_surfaces"]["node"],
"disasmer node enroll/list/status/revoke"
);
let steps = report["bootstrap_sequence"].as_array().unwrap();
for expected in [
"start_self_hosted_coordinator",
"create_or_link_project",
"create_node_enrollment_grant",
"attach_worker_node",
"run_process",
"inspect_status_logs_artifacts",
"revoke_access",
] {
assert!(
steps.iter().any(|step| step["step"] == expected),
"missing bootstrap step {expected}"
);
}
assert!(steps.iter().all(|step| {
step.get("private_website_required")
.and_then(Value::as_bool)
.unwrap_or(false)
== false
}));
assert!(steps.iter().any(|step| step
.get("command")
.and_then(Value::as_str)
.unwrap_or("")
.contains("disasmer node enroll")));
assert!(steps.iter().any(|step| step
.get("command")
.and_then(Value::as_str)
.unwrap_or("")
.contains("disasmer admin revoke-node")));
}
#[test]
fn top_level_help_exposes_primary_workflow_without_auth() {
let mut command = Cli::command();