Spawns a new Docker buildx builder on Kubernetes. Each architecture gets a buildx node whose name is: `{builder_prefix}{exec_id}-{arch}` (truncated to 60 chars) Kubernetes then creates a pod named `{node_name}-{random_suffix}`. For example, with `exec_id = "03d…ef-3999-0"` and `builder_prefix = "build-"`: node = `build-03d49150-a2f5-4fb5-ba90-2c94e32dd9ef-3999-0-amd64` pod = `build-03d49150-
(
&self,
exec_id: &str,
builder_name: &str,
nb_builder: NonZeroUsize,
requested_architectures: &[Architecture],
(cpu_request_milli, cpu_limit_milli): (u
| 344 | /// The deterministic node name (without the random suffix) can be used to |
| 345 | /// identify build pods in monitoring dashboards (e.g., Grafana). |
| 346 | pub fn spawn_builder( |
| 347 | &self, |
| 348 | exec_id: &str, |
| 349 | builder_name: &str, |
| 350 | nb_builder: NonZeroUsize, |
| 351 | requested_architectures: &[Architecture], |
| 352 | (cpu_request_milli, cpu_limit_milli): (u32, u32), |
| 353 | (memory_request_gib, memory_limit_gib): (u32, u32), |
| 354 | ephemeral_storage_gib: Option<u32>, |
| 355 | should_abort: &CommandKiller, |
| 356 | http_registries: &[&str], |
| 357 | tls_invalid_registries: &[&str], |
| 358 | bootstrap_builder: bool, |
| 359 | ) -> Result<BuilderHandle, DockerError> { |
| 360 | match &self.builder_location { |
| 361 | // For local builder, we have at max 1 builder available |
| 362 | BuilderLocation::Local => Ok(BuilderHandle { |
| 363 | config_path: self.config_path.path().to_path_buf(), |
| 364 | nb_builder: NonZeroUsize::new(1).unwrap(), |
| 365 | builder_name: None, |
| 366 | }), |
| 367 | BuilderLocation::Kubernetes { |
| 368 | namespace, |
| 369 | builder_prefix, |
| 370 | supported_architectures, |
| 371 | enable_rootless, |
| 372 | } => { |
| 373 | let available_architectures = requested_architectures |
| 374 | .iter() |
| 375 | .filter(|arch| supported_architectures.contains(arch)) |
| 376 | .count(); |
| 377 | |
| 378 | if available_architectures != requested_architectures.len() { |
| 379 | return Err(DockerError::InvalidConfig { |
| 380 | raw_error_message: format!( |
| 381 | "Some requested architectures are not supported by current docker builder. Available architectures are {supported_architectures:?} while requested are {requested_architectures:?}." |
| 382 | ), |
| 383 | }); |
| 384 | } |
| 385 | |
| 386 | // We create build handle here to force the drop to run if some operation fail |
| 387 | let builder_name = format!("qovery-{builder_name}"); |
| 388 | let build_handle = BuilderHandle { |
| 389 | config_path: self.config_path.path().to_path_buf(), |
| 390 | nb_builder, |
| 391 | builder_name: Some(builder_name.clone()), |
| 392 | }; |
| 393 | |
| 394 | info!("docker spawn builder {:?} {:?}", builder_name, requested_architectures); |
| 395 | let buildkitd_cfg_arg = { |
| 396 | let cfg_path = self.config_path.path().join("buildkitd.toml"); |
| 397 | let mut cfg_file = String::new(); |
| 398 | for http in http_registries { |
| 399 | cfg_file.push_str(&format!("[registry.\"{http}\"]\n http = true\n")); |
| 400 | } |
| 401 | for tls in tls_invalid_registries { |
| 402 | cfg_file.push_str(&format!("[registry.\"{tls}\"]\n insecure = true\n")); |
| 403 | } |