manta_server/service/
ephemeral_env.rs1use csm_rs::ShastaClient;
20use manta_backend_dispatcher::error::Error;
21
22use crate::server::common::app_context::InfraContext;
23use crate::server::common::jwt_ops;
24use crate::wire_conv;
25
26const EPHEMERAL_IMAGE_NAME: &str = "__ephemeral_image";
27
28pub async fn exec(
50 infra: &InfraContext<'_>,
51 token: &str,
52 image_id: &str,
53) -> Result<String, Error> {
54 let user_public_key_name =
55 jwt_ops::get_preferred_username(token).map_err(wire_conv::to_backend)?;
56
57 tracing::info!("Looking for user '{}' public SSH key", user_public_key_name);
58
59 let shasta =
60 ShastaClient::new(infra.shasta_base_url, infra.shasta_root_cert.to_vec())
61 .map_err(|e| {
62 Error::BadRequest(format!("Could not build Shasta HTTP client: {e}"))
63 })?;
64
65 let user_public_ssh_id = if let Ok(Some(user_public_ssh_key)) = shasta
66 .ims_public_keys_v3_get_single(token, &user_public_key_name)
67 .await
68 {
69 user_public_ssh_key.id.ok_or_else(|| {
70 Error::MissingField(
71 "IMS public-key response missing server-generated 'id'".to_string(),
72 )
73 })?
74 } else {
75 return Err(Error::NotFound(format!(
76 "User '{user_public_key_name}' does not have an SSH public key in Alps. \
77 Please contact platform sys admins."
78 )));
79 };
80
81 tracing::info!("SSH key found with ID {}", user_public_ssh_id);
82 tracing::info!(
83 "Creating ephemeral environment based on image ID {}",
84 image_id
85 );
86
87 let resp_json = shasta
88 .ims_job_post_customize(
89 token,
90 EPHEMERAL_IMAGE_NAME,
91 image_id,
92 &user_public_ssh_id,
93 )
94 .await
95 .map_err(|e| {
96 Error::BadRequest(format!(
97 "Could not create ephemeral environment based on image ID {image_id}: {e}"
98 ))
99 })?;
100
101 let hostname = resp_json
102 .pointer("/ssh_containers/0/connection_info/customer_access/host")
103 .and_then(|v| v.as_str())
104 .ok_or_else(|| {
105 Error::MissingField(
106 "Failed to get SSH container hostname from ephemeral env response"
107 .to_string(),
108 )
109 })?
110 .to_string();
111
112 tracing::info!("Ephemeral environment created — SSH hostname: {}", hostname);
113
114 Ok(hostname)
115}