Report self-hosted admin bootstrap path
This commit is contained in:
parent
ab84fd382d
commit
c836abc405
3 changed files with 168 additions and 4 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"kind": "disasmer-filtered-public-tree",
|
"kind": "disasmer-filtered-public-tree",
|
||||||
"source_commit": "714ecfe0fc03dec4fa3ca48b8f8760a7aeead338",
|
"source_commit": "41a0af41b5289a1cac004531798bb5269c9bd749",
|
||||||
"release_name": "dryrun-714ecfe0fc03",
|
"release_name": "dryrun-41a0af41b528",
|
||||||
"filtered_out": [
|
"filtered_out": [
|
||||||
"private/**",
|
"private/**",
|
||||||
"experiments/**",
|
"experiments/**",
|
||||||
|
|
|
||||||
|
|
@ -2258,8 +2258,9 @@ fn admin_status_report(args: AdminStatusArgs) -> Result<Value> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn admin_bootstrap_report(args: AdminBootstrapArgs, cwd: PathBuf) -> Result<Value> {
|
fn admin_bootstrap_report(args: AdminBootstrapArgs, cwd: PathBuf) -> Result<Value> {
|
||||||
|
let scope = args.scope.clone();
|
||||||
let new_project = args.scope.project.clone();
|
let new_project = args.scope.project.clone();
|
||||||
project_init_report(
|
let project_init = project_init_report(
|
||||||
ProjectInitArgs {
|
ProjectInitArgs {
|
||||||
scope: args.scope,
|
scope: args.scope,
|
||||||
new_project,
|
new_project,
|
||||||
|
|
@ -2267,7 +2268,92 @@ fn admin_bootstrap_report(args: AdminBootstrapArgs, cwd: PathBuf) -> Result<Valu
|
||||||
yes: args.yes,
|
yes: args.yes,
|
||||||
},
|
},
|
||||||
cwd,
|
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> {
|
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]
|
#[test]
|
||||||
fn top_level_help_exposes_primary_workflow_without_auth() {
|
fn top_level_help_exposes_primary_workflow_without_auth() {
|
||||||
let mut command = Cli::command();
|
let mut command = Cli::command();
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,11 @@ expect(
|
||||||
"doctor node readiness criteria",
|
"doctor node readiness criteria",
|
||||||
/`disasmer doctor` reports missing local dependencies[\s\S]*explicit node readiness summary[\s\S]*missing local dependencies[\s\S]*node next actions/
|
/`disasmer doctor` reports missing local dependencies[\s\S]*explicit node readiness summary[\s\S]*missing local dependencies[\s\S]*node next actions/
|
||||||
);
|
);
|
||||||
|
expect(
|
||||||
|
criteria,
|
||||||
|
"admin bootstrap self-hosted sequence criteria",
|
||||||
|
/admin bootstrap now reports a CLI-only self-hosted sequence[\s\S]*node enrollment\/attach[\s\S]*quota status[\s\S]*node revoke/
|
||||||
|
);
|
||||||
expect(
|
expect(
|
||||||
criteria,
|
criteria,
|
||||||
"quota resource-category criteria",
|
"quota resource-category criteria",
|
||||||
|
|
@ -213,6 +218,7 @@ for (const [name, pattern] of [
|
||||||
["CLI agent workflow actor coverage", /fn run_with_agent_public_key_sends_attributable_workflow_actor\(\)/],
|
["CLI agent workflow actor coverage", /fn run_with_agent_public_key_sends_attributable_workflow_actor\(\)/],
|
||||||
["CLI node revoke coverage", /fn node_revoke_reports_scoped_credential_revocation\(\)/],
|
["CLI node revoke coverage", /fn node_revoke_reports_scoped_credential_revocation\(\)/],
|
||||||
["CLI admin public API coverage", /fn admin_status_and_suspend_use_public_coordinator_api\(\)/],
|
["CLI admin public API coverage", /fn admin_status_and_suspend_use_public_coordinator_api\(\)/],
|
||||||
|
["CLI admin bootstrap coverage", /fn admin_bootstrap_reports_self_hosted_cli_only_path\(\)/],
|
||||||
["CLI debug attach coverage", /fn debug_attach_reports_public_authorization\(\)/],
|
["CLI debug attach coverage", /fn debug_attach_reports_public_authorization\(\)/],
|
||||||
["doctor unchecked reachability coverage", /fn doctor_reports_unchecked_coordinator_reachability_without_config\(\)/],
|
["doctor unchecked reachability coverage", /fn doctor_reports_unchecked_coordinator_reachability_without_config\(\)/],
|
||||||
["doctor ping reachability coverage", /fn doctor_pings_configured_coordinator\(\)/],
|
["doctor ping reachability coverage", /fn doctor_pings_configured_coordinator\(\)/],
|
||||||
|
|
@ -460,6 +466,11 @@ expect(
|
||||||
"CLI artifact export keeps content out of reports",
|
"CLI artifact export keeps content out of reports",
|
||||||
/fn artifact_stream_summary[\s\S]*content_material_returned_in_report[\s\S]*false/
|
/fn artifact_stream_summary[\s\S]*content_material_returned_in_report[\s\S]*false/
|
||||||
);
|
);
|
||||||
|
expect(
|
||||||
|
cli,
|
||||||
|
"CLI exposes admin bootstrap self-hosted path",
|
||||||
|
/fn admin_bootstrap_report[\s\S]*self_hosted_cli_only[\s\S]*bootstrap_sequence[\s\S]*create_node_enrollment_grant[\s\S]*attach_worker_node[\s\S]*inspect_status_logs_artifacts[\s\S]*revoke_access/
|
||||||
|
);
|
||||||
expect(
|
expect(
|
||||||
coordinator,
|
coordinator,
|
||||||
"coordinator exposes conservative artifact stream content",
|
"coordinator exposes conservative artifact stream content",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue