Sync public tree to b25bfc6
This commit is contained in:
parent
4f5df7da20
commit
009a9619e1
3 changed files with 205 additions and 15 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"kind": "disasmer-filtered-public-tree",
|
"kind": "disasmer-filtered-public-tree",
|
||||||
"source_commit": "4a860d72efe34b376c4b08762555bee3fe3105f9",
|
"source_commit": "b25bfc668c9ac086a09be0d69b2ca1e6a6ddae13",
|
||||||
"release_name": "dryrun-4a860d72efe3",
|
"release_name": "dryrun-b25bfc668c9a",
|
||||||
"filtered_out": [
|
"filtered_out": [
|
||||||
"private/**",
|
"private/**",
|
||||||
"experiments/**",
|
"experiments/**",
|
||||||
|
|
|
||||||
|
|
@ -1276,11 +1276,16 @@ fn key_revoke_report(args: KeyRevokeArgs) -> Result<Value> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn project_init_report(args: ProjectInitArgs, cwd: PathBuf) -> Result<Value> {
|
fn project_init_report(args: ProjectInitArgs, cwd: PathBuf) -> Result<Value> {
|
||||||
|
let tenant = args.scope.tenant.clone();
|
||||||
|
let project = args.new_project.clone();
|
||||||
|
let user = args.scope.user.clone();
|
||||||
|
let coordinator = args.scope.coordinator.clone();
|
||||||
|
let name = args.name.clone();
|
||||||
let config = ProjectConfig {
|
let config = ProjectConfig {
|
||||||
tenant: args.scope.tenant.clone(),
|
tenant: tenant.clone(),
|
||||||
project: args.new_project.clone(),
|
project: project.clone(),
|
||||||
user: args.scope.user.clone(),
|
user: user.clone(),
|
||||||
coordinator: args.scope.coordinator.clone(),
|
coordinator: coordinator.clone(),
|
||||||
};
|
};
|
||||||
let config_file = project_config_file(&cwd);
|
let config_file = project_config_file(&cwd);
|
||||||
if config_file.exists() && !args.yes {
|
if config_file.exists() && !args.yes {
|
||||||
|
|
@ -1289,26 +1294,63 @@ fn project_init_report(args: ProjectInitArgs, cwd: PathBuf) -> Result<Value> {
|
||||||
config_file.display()
|
config_file.display()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
let coordinator_response = if let Some(coordinator) = &args.scope.coordinator {
|
let mut coordinator_session_requests = 0;
|
||||||
|
let coordinator_response = if let Some(coordinator) = &coordinator {
|
||||||
let mut session = JsonLineSession::connect(coordinator)?;
|
let mut session = JsonLineSession::connect(coordinator)?;
|
||||||
Some(session.request(json!({
|
let response = session.request(json!({
|
||||||
"type": "create_project",
|
"type": "create_project",
|
||||||
"tenant": args.scope.tenant,
|
"tenant": tenant,
|
||||||
"actor_user": args.scope.user,
|
"actor_user": user,
|
||||||
"project": args.new_project,
|
"project": project,
|
||||||
"name": args.name,
|
"name": name,
|
||||||
}))?)
|
}))?;
|
||||||
|
coordinator_session_requests = session.requests();
|
||||||
|
Some(response)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
write_project_config(&cwd, &config)?;
|
write_project_config(&cwd, &config)?;
|
||||||
|
let created_or_linked_project = coordinator_response
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|response| response.get("project"))
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
json!({
|
||||||
|
"id": config.project.clone(),
|
||||||
|
"tenant": config.tenant.clone(),
|
||||||
|
"name": args.name.clone(),
|
||||||
|
})
|
||||||
|
});
|
||||||
Ok(json!({
|
Ok(json!({
|
||||||
"command": "project init",
|
"command": "project init",
|
||||||
"source": if args.scope.coordinator.is_some() { "public_coordinator_api" } else { "local_project_config" },
|
"source": if coordinator.is_some() { "public_coordinator_api" } else { "local_project_config" },
|
||||||
"private_website_required": false,
|
"private_website_required": false,
|
||||||
"project_config_written": true,
|
"project_config_written": true,
|
||||||
|
"project_config_write_after_coordinator_acceptance": coordinator.is_some(),
|
||||||
|
"coordinator_create_before_local_write": coordinator.is_some(),
|
||||||
|
"coordinator_session_requests": coordinator_session_requests,
|
||||||
|
"created_or_linked_project": created_or_linked_project,
|
||||||
|
"current_directory_link": {
|
||||||
|
"cwd": cwd,
|
||||||
|
"config_file": config_file,
|
||||||
|
"config_format": "disasmer_project_config_v1",
|
||||||
|
"links_current_directory": true,
|
||||||
|
"writes_current_directory_only": true,
|
||||||
|
"private_website_required": false,
|
||||||
|
},
|
||||||
|
"safe_defaults": {
|
||||||
|
"tenant": config.tenant.clone(),
|
||||||
|
"project": config.project.clone(),
|
||||||
|
"user": config.user.clone(),
|
||||||
|
"coordinator": config.coordinator.clone(),
|
||||||
|
"project_name": args.name.clone(),
|
||||||
|
"default_project_id_used": args.new_project == "project",
|
||||||
|
"default_project_name_used": args.name == "Disasmer Project",
|
||||||
|
"browser_interaction_required": false,
|
||||||
|
"private_website_required": false,
|
||||||
|
},
|
||||||
"project_config": config,
|
"project_config": config,
|
||||||
"config_file": config_file,
|
"config_file": project_config_file(&cwd),
|
||||||
"coordinator_response": coordinator_response,
|
"coordinator_response": coordinator_response,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
@ -2567,6 +2609,16 @@ fn human_report(value: &Value) -> String {
|
||||||
push_nested_string_field(&mut lines, project_config, "coordinator", "coordinator");
|
push_nested_string_field(&mut lines, project_config, "coordinator", "coordinator");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let Some(link) = value.get("current_directory_link") {
|
||||||
|
if link
|
||||||
|
.get("links_current_directory")
|
||||||
|
.and_then(Value::as_bool)
|
||||||
|
.unwrap_or(false)
|
||||||
|
{
|
||||||
|
lines.push("current directory linked: true".to_owned());
|
||||||
|
}
|
||||||
|
push_nested_string_field(&mut lines, link, "config_file", "current directory config");
|
||||||
|
}
|
||||||
if let Some(metadata) = value.get("metadata") {
|
if let Some(metadata) = value.get("metadata") {
|
||||||
push_nested_string_field(&mut lines, metadata, "identity", "bundle");
|
push_nested_string_field(&mut lines, metadata, "identity", "bundle");
|
||||||
if let Some(environments) = metadata.get("environments").and_then(Value::as_array) {
|
if let Some(environments) = metadata.get("environments").and_then(Value::as_array) {
|
||||||
|
|
@ -8128,6 +8180,27 @@ mod tests {
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(init["command"], "project init");
|
assert_eq!(init["command"], "project init");
|
||||||
|
assert_eq!(init["source"], "local_project_config");
|
||||||
|
assert_eq!(init["project_config_written"], true);
|
||||||
|
assert_eq!(
|
||||||
|
init["current_directory_link"]["config_format"],
|
||||||
|
"disasmer_project_config_v1"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
init["current_directory_link"]["links_current_directory"],
|
||||||
|
true
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
init["current_directory_link"]["writes_current_directory_only"],
|
||||||
|
true
|
||||||
|
);
|
||||||
|
assert_eq!(init["safe_defaults"]["project"], "project-a");
|
||||||
|
assert_eq!(init["safe_defaults"]["tenant"], "tenant");
|
||||||
|
assert_eq!(init["safe_defaults"]["browser_interaction_required"], false);
|
||||||
|
assert_eq!(init["coordinator_create_before_local_write"], false);
|
||||||
|
let rendered = human_report(&init);
|
||||||
|
assert!(rendered.contains("current directory linked: true"));
|
||||||
|
assert!(rendered.contains("current directory config:"));
|
||||||
|
|
||||||
let config = read_project_config(temp.path()).unwrap().unwrap();
|
let config = read_project_config(temp.path()).unwrap().unwrap();
|
||||||
assert_eq!(config.project, "project-a");
|
assert_eq!(config.project, "project-a");
|
||||||
|
|
@ -8173,6 +8246,107 @@ mod tests {
|
||||||
assert_eq!(status["attached_nodes"]["checked"], false);
|
assert_eq!(status["attached_nodes"]["checked"], false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn project_init_uses_public_create_before_writing_local_config() {
|
||||||
|
let temp_success = tempfile::tempdir().unwrap();
|
||||||
|
let temp_rejected = tempfile::tempdir().unwrap();
|
||||||
|
let listener = TcpListener::bind("127.0.0.1:0").unwrap();
|
||||||
|
let addr = listener.local_addr().unwrap().to_string();
|
||||||
|
let server = std::thread::spawn(move || {
|
||||||
|
for index in 0..2 {
|
||||||
|
let (mut stream, _) = listener.accept().unwrap();
|
||||||
|
let mut reader = BufReader::new(stream.try_clone().unwrap());
|
||||||
|
let mut line = String::new();
|
||||||
|
reader.read_line(&mut line).unwrap();
|
||||||
|
assert!(line.contains(r#""type":"create_project""#));
|
||||||
|
assert!(line.contains(r#""tenant":"tenant-live""#));
|
||||||
|
assert!(line.contains(r#""actor_user":"user-live""#));
|
||||||
|
match index {
|
||||||
|
0 => {
|
||||||
|
assert!(line.contains(r#""project":"project-created""#));
|
||||||
|
stream
|
||||||
|
.write_all(
|
||||||
|
br#"{"type":"project_created","project":{"id":"project-created","tenant":"tenant-live","name":"Created Project"},"actor":"user-live"}"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
1 => {
|
||||||
|
assert!(line.contains(r#""project":"foreign-project""#));
|
||||||
|
stream
|
||||||
|
.write_all(
|
||||||
|
br#"{"type":"error","message":"project id is outside the signed-in tenant scope"}"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
stream.write_all(b"\n").unwrap();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let scope = CliScopeArgs {
|
||||||
|
coordinator: Some(addr),
|
||||||
|
tenant: "tenant-live".to_owned(),
|
||||||
|
project: "ignored".to_owned(),
|
||||||
|
user: "user-live".to_owned(),
|
||||||
|
json: false,
|
||||||
|
};
|
||||||
|
let created = project_init_report(
|
||||||
|
ProjectInitArgs {
|
||||||
|
scope: scope.clone(),
|
||||||
|
new_project: "project-created".to_owned(),
|
||||||
|
name: "Created Project".to_owned(),
|
||||||
|
yes: true,
|
||||||
|
},
|
||||||
|
temp_success.path().to_path_buf(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(created["command"], "project init");
|
||||||
|
assert_eq!(created["source"], "public_coordinator_api");
|
||||||
|
assert_eq!(created["coordinator_create_before_local_write"], true);
|
||||||
|
assert_eq!(
|
||||||
|
created["project_config_write_after_coordinator_acceptance"],
|
||||||
|
true
|
||||||
|
);
|
||||||
|
assert_eq!(created["coordinator_session_requests"], 1);
|
||||||
|
assert_eq!(
|
||||||
|
created["created_or_linked_project"]["id"],
|
||||||
|
"project-created"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
created["current_directory_link"]["links_current_directory"],
|
||||||
|
true
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
created["safe_defaults"]["browser_interaction_required"],
|
||||||
|
false
|
||||||
|
);
|
||||||
|
assert_eq!(created["private_website_required"], false);
|
||||||
|
assert_eq!(
|
||||||
|
read_project_config(temp_success.path())
|
||||||
|
.unwrap()
|
||||||
|
.unwrap()
|
||||||
|
.project,
|
||||||
|
"project-created"
|
||||||
|
);
|
||||||
|
|
||||||
|
let rejected = project_init_report(
|
||||||
|
ProjectInitArgs {
|
||||||
|
scope,
|
||||||
|
new_project: "foreign-project".to_owned(),
|
||||||
|
name: "Foreign Project".to_owned(),
|
||||||
|
yes: true,
|
||||||
|
},
|
||||||
|
temp_rejected.path().to_path_buf(),
|
||||||
|
)
|
||||||
|
.unwrap_err();
|
||||||
|
server.join().unwrap();
|
||||||
|
|
||||||
|
assert!(rejected.to_string().contains("tenant scope"));
|
||||||
|
assert!(read_project_config(temp_rejected.path()).unwrap().is_none());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn project_list_and_select_use_public_api_without_website() {
|
fn project_list_and_select_use_public_api_without_website() {
|
||||||
let temp = tempfile::tempdir().unwrap();
|
let temp = tempfile::tempdir().unwrap();
|
||||||
|
|
|
||||||
|
|
@ -239,6 +239,7 @@ for (const [name, pattern] of [
|
||||||
["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\(\)/],
|
||||||
["project local config coverage", /fn project_init_select_and_status_use_local_project_config\(\)/],
|
["project local config coverage", /fn project_init_select_and_status_use_local_project_config\(\)/],
|
||||||
|
["project init public create coverage", /fn project_init_uses_public_create_before_writing_local_config\(\)/],
|
||||||
["project public API list/select coverage", /fn project_list_and_select_use_public_api_without_website\(\)/],
|
["project public API list/select coverage", /fn project_list_and_select_use_public_api_without_website\(\)/],
|
||||||
["project coordinator status coverage", /fn project_status_queries_public_coordinator_state\(\)/],
|
["project coordinator status coverage", /fn project_status_queries_public_coordinator_state\(\)/],
|
||||||
["run coordinator active-process coverage", /fn run_contacts_configured_coordinator_and_reports_active_process_conflicts\(\)/],
|
["run coordinator active-process coverage", /fn run_contacts_configured_coordinator_and_reports_active_process_conflicts\(\)/],
|
||||||
|
|
@ -393,6 +394,21 @@ expect(
|
||||||
"CLI exposes task placement reasons",
|
"CLI exposes task placement reasons",
|
||||||
/fn task_summaries[\s\S]*node_placement[\s\S]*reasons[\s\S]*explanation_available/
|
/fn task_summaries[\s\S]*node_placement[\s\S]*reasons[\s\S]*explanation_available/
|
||||||
);
|
);
|
||||||
|
expect(
|
||||||
|
cli,
|
||||||
|
"CLI project init report current-directory link",
|
||||||
|
/fn project_init_report[\s\S]*current_directory_link[\s\S]*links_current_directory[\s\S]*safe_defaults[\s\S]*coordinator_create_before_local_write/
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
cli,
|
||||||
|
"CLI project init writes config after public create",
|
||||||
|
/let coordinator_response = if let Some\(coordinator\)[\s\S]*"type": "create_project"[\s\S]*coordinator_session_requests = session\.requests\(\)[\s\S]*write_project_config\(&cwd, &config\)\?/
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
cli,
|
||||||
|
"CLI project init renders current-directory link",
|
||||||
|
/current_directory_link[\s\S]*current directory linked: true[\s\S]*current directory config/
|
||||||
|
);
|
||||||
expect(
|
expect(
|
||||||
cli,
|
cli,
|
||||||
"CLI project list/select report public API boundary",
|
"CLI project list/select report public API boundary",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue