Pull an image if it is not already present locally. Uses the `policy` parameter to decide whether to pull: - `"always"` — always pull, even if a local copy exists - `"missing"` — pull only when no local copy exists (default) - `"never"` — never pull, fail if not local - `"newer"` — pull only if the remote image is newer The pull `policy` is passed directly to Podman's API so that Podman handles
(&self, reference: &str, policy: &str)
| 573 | /// The Podman pull endpoint streams NDJSON progress. We consume the |
| 574 | /// entire stream and check for an `error` field in the final object. |
| 575 | pub async fn pull_image(&self, reference: &str, policy: &str) -> Result<(), PodmanApiError> { |
| 576 | let path = format!( |
| 577 | "/libpod/images/pull?reference={}&policy={}", |
| 578 | url_encode(reference), |
| 579 | url_encode(policy), |
| 580 | ); |
| 581 | // Image pulls can be slow — use a generous timeout. |
| 582 | let pull_timeout = Duration::from_secs(600); |
| 583 | let (status, bytes) = self |
| 584 | .request(hyper::Method::POST, &path, None, pull_timeout) |
| 585 | .await?; |
| 586 | if !status.is_success() { |
| 587 | return Err(error_from_response(status.as_u16(), &bytes)); |
| 588 | } |
| 589 | // The response is NDJSON. Check the last line for an error field. |
| 590 | let body = String::from_utf8_lossy(&bytes); |
| 591 | if let Some(last_line) = body.lines().rfind(|l| !l.is_empty()) |
| 592 | && let Ok(obj) = serde_json::from_str::<Value>(last_line) |
| 593 | && let Some(err) = obj.get("error").and_then(|v| v.as_str()) |
| 594 | && !err.is_empty() |
| 595 | { |
| 596 | return Err(PodmanApiError::Api { |
| 597 | status: 500, |
| 598 | message: format!("image pull failed: {err}"), |
| 599 | }); |
| 600 | } |
| 601 | Ok(()) |
| 602 | } |
| 603 | |
| 604 | // ── System operations ──────────────────────────────────────────────── |
| 605 |
no test coverage detected