Merge pull request #6457 from arronwy/multiple_same_images

image_rpc: Add container_count for containers without cid
This commit is contained in:
Fabiano Fidêncio 2023-03-28 10:16:48 +02:00 committed by GitHub
commit 4c810c7933
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -9,7 +9,7 @@ use std::env;
use std::fs; use std::fs;
use std::path::Path; use std::path::Path;
use std::process::Command; use std::process::Command;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, AtomicU16, Ordering};
use std::sync::Arc; use std::sync::Arc;
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
@ -45,6 +45,7 @@ pub struct ImageService {
sandbox: Arc<Mutex<Sandbox>>, sandbox: Arc<Mutex<Sandbox>>,
attestation_agent_started: AtomicBool, attestation_agent_started: AtomicBool,
image_client: Arc<Mutex<ImageClient>>, image_client: Arc<Mutex<ImageClient>>,
container_count: Arc<AtomicU16>,
} }
impl ImageService { impl ImageService {
@ -54,6 +55,7 @@ impl ImageService {
sandbox, sandbox,
attestation_agent_started: AtomicBool::new(false), attestation_agent_started: AtomicBool::new(false),
image_client: Arc::new(Mutex::new(ImageClient::default())), image_client: Arc::new(Mutex::new(ImageClient::default())),
container_count: Arc::new(AtomicU16::new(0)),
} }
} }
@ -115,13 +117,16 @@ impl ImageService {
/// ///
/// If the request specifies a non-empty id, use it; otherwise derive it from the image path. /// If the request specifies a non-empty id, use it; otherwise derive it from the image path.
/// In either case, verify that the chosen id is valid. /// In either case, verify that the chosen id is valid.
fn cid_from_request(req: &image::PullImageRequest) -> Result<String> { fn cid_from_request(&self, req: &image::PullImageRequest) -> Result<String> {
let req_cid = req.get_container_id(); let req_cid = req.get_container_id();
let cid = if !req_cid.is_empty() { let cid = if !req_cid.is_empty() {
req_cid.to_string() req_cid.to_string()
} else if let Some(last) = req.get_image().rsplit('/').next() { } else if let Some(last) = req.get_image().rsplit('/').next() {
// Support multiple containers with same image
let index = self.container_count.fetch_add(1, Ordering::Relaxed);
// ':' not valid for container id // ':' not valid for container id
last.replace(':', "_") format!("{}_{}", last.replace(':', "_"), index)
} else { } else {
return Err(anyhow!("Invalid image name. {}", req.get_image())); return Err(anyhow!("Invalid image name. {}", req.get_image()));
}; };
@ -142,7 +147,7 @@ impl ImageService {
env::set_var("NO_PROXY", no_proxy); env::set_var("NO_PROXY", no_proxy);
} }
let cid = Self::cid_from_request(req)?; let cid = self.cid_from_request(req)?;
let image = req.get_image(); let image = req.get_image();
if cid.starts_with("pause") { if cid.starts_with("pause") {
Self::unpack_pause_image(&cid)?; Self::unpack_pause_image(&cid)?;
@ -246,10 +251,13 @@ impl protocols::image_ttrpc_async::Image for ImageService {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::ImageService; use super::ImageService;
use crate::sandbox::Sandbox;
use protocols::image; use protocols::image;
use std::sync::Arc;
use tokio::sync::Mutex;
#[test] #[tokio::test]
fn test_cid_from_request() { async fn test_cid_from_request() {
struct Case { struct Case {
cid: &'static str, cid: &'static str,
image: &'static str, image: &'static str,
@ -285,12 +293,12 @@ mod tests {
Case { Case {
cid: "", cid: "",
image: "../abc", image: "../abc",
result: Some("abc"), result: Some("abc_4"),
}, },
Case { Case {
cid: "", cid: "",
image: "../9abc", image: "../9abc",
result: Some("9abc"), result: Some("9abc_5"),
}, },
Case { Case {
cid: "some-string.1_2", cid: "some-string.1_2",
@ -310,20 +318,23 @@ mod tests {
Case { Case {
cid: "", cid: "",
image: "prefix/a:b", image: "prefix/a:b",
result: Some("a_b"), result: Some("a_b_6"),
}, },
Case { Case {
cid: "", cid: "",
image: "/a/b/c/d:e", image: "/a/b/c/d:e",
result: Some("d_e"), result: Some("d_e_7"),
}, },
]; ];
let logger = slog::Logger::root(slog::Discard, o!());
let s = Sandbox::new(&logger).unwrap();
let image_service = ImageService::new(Arc::new(Mutex::new(s)));
for case in &cases { for case in &cases {
let mut req = image::PullImageRequest::new(); let mut req = image::PullImageRequest::new();
req.set_image(case.image.to_string()); req.set_image(case.image.to_string());
req.set_container_id(case.cid.to_string()); req.set_container_id(case.cid.to_string());
let ret = ImageService::cid_from_request(&req); let ret = image_service.cid_from_request(&req);
match (case.result, ret) { match (case.result, ret) {
(Some(expected), Ok(actual)) => assert_eq!(expected, actual), (Some(expected), Ok(actual)) => assert_eq!(expected, actual),
(None, Err(_)) => (), (None, Err(_)) => (),