Skip to content

Commit

Permalink
feat: allow configuring resource ulimits (#714)
Browse files Browse the repository at this point in the history
Thanks again for working on this project!

This exposes a way to configure resource ulimits (the
[`--ulimit`](https://docs.docker.com/reference/cli/docker/container/run/#ulimit)
flag for `docker run`).

I'm relying on CI tests because I'm currently on Windows and didn't
configure my environment to reflect
#711, since it
seems I'd need to install nasm now, as I received some errors regarding
it.
  • Loading branch information
blaenk authored Aug 3, 2024
1 parent f8d4a3d commit b10b48f
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 1 deletion.
5 changes: 5 additions & 0 deletions testcontainers/src/core/containers/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ use std::{
time::Duration,
};

use bollard_stubs::models::ResourcesUlimits;

use crate::{
core::{
logs::consumer::LogConsumer, mounts::Mount, ports::ContainerPort, ContainerState,
Expand All @@ -27,6 +29,7 @@ pub struct ContainerRequest<I: Image> {
pub(crate) hosts: BTreeMap<String, Host>,
pub(crate) mounts: Vec<Mount>,
pub(crate) ports: Option<Vec<PortMapping>>,
pub(crate) ulimits: Option<Vec<ResourcesUlimits>>,
pub(crate) privileged: bool,
pub(crate) shm_size: Option<u64>,
pub(crate) cgroupns_mode: Option<CgroupnsMode>,
Expand Down Expand Up @@ -168,6 +171,7 @@ impl<I: Image> From<I> for ContainerRequest<I> {
hosts: BTreeMap::default(),
mounts: Vec::new(),
ports: None,
ulimits: None,
privileged: false,
shm_size: None,
cgroupns_mode: None,
Expand Down Expand Up @@ -208,6 +212,7 @@ impl<I: Image + Debug> Debug for ContainerRequest<I> {
.field("hosts", &self.hosts)
.field("mounts", &self.mounts)
.field("ports", &self.ports)
.field("ulimits", &self.ulimits)
.field("privileged", &self.privileged)
.field("shm_size", &self.shm_size)
.field("cgroupns_mode", &self.cgroupns_mode)
Expand Down
27 changes: 27 additions & 0 deletions testcontainers/src/core/image/image_ext.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use std::time::Duration;

use bollard_stubs::models::ResourcesUlimits;

use crate::{
core::{logs::consumer::LogConsumer, CgroupnsMode, ContainerPort, Host, Mount, PortMapping},
ContainerRequest, Image,
Expand Down Expand Up @@ -64,6 +66,16 @@ pub trait ImageExt<I: Image> {
fn with_mapped_port(self, host_port: u16, container_port: ContainerPort)
-> ContainerRequest<I>;

/// Adds a resource ulimit to the container.
///
/// # Examples
/// ```rust,no_run
/// use testcontainers::{GenericImage, ImageExt};
///
/// let image = GenericImage::new("image", "tag").with_ulimit("nofile", 65536, Some(65536));
/// ```
fn with_ulimit(self, name: &str, soft: i64, hard: Option<i64>) -> ContainerRequest<I>;

/// Sets the container to run in privileged mode.
fn with_privileged(self, privileged: bool) -> ContainerRequest<I>;

Expand Down Expand Up @@ -168,6 +180,21 @@ impl<RI: Into<ContainerRequest<I>>, I: Image> ImageExt<I> for RI {
}
}

fn with_ulimit(self, name: &str, soft: i64, hard: Option<i64>) -> ContainerRequest<I> {
let container_req = self.into();
let mut ulimits = container_req.ulimits.unwrap_or_default();
ulimits.push(ResourcesUlimits {
name: Some(name.into()),
soft: Some(soft),
hard,
});

ContainerRequest {
ulimits: Some(ulimits),
..container_req
}
}

fn with_privileged(self, privileged: bool) -> ContainerRequest<I> {
let container_req = self.into();
ContainerRequest {
Expand Down
40 changes: 39 additions & 1 deletion testcontainers/src/runners/async_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use bollard::{
container::{Config, CreateContainerOptions},
models::{HostConfig, PortBinding},
};
use bollard_stubs::models::HostConfigCgroupnsModeEnum;
use bollard_stubs::models::{HostConfigCgroupnsModeEnum, ResourcesUlimits};

use crate::{
core::{
Expand Down Expand Up @@ -172,6 +172,23 @@ where
});
}

// resource ulimits
if let Some(ulimits) = &container_req.ulimits {
config.host_config = config.host_config.map(|mut host_config| {
host_config.ulimits = Some(
ulimits
.iter()
.map(|ulimit| ResourcesUlimits {
name: ulimit.name.clone(),
soft: ulimit.soft,
hard: ulimit.hard,
})
.collect(),
);
host_config
});
}

let cmd: Vec<_> = container_req.cmd().map(|v| v.to_string()).collect();
if !cmd.is_empty() {
config.cmd = Some(cmd);
Expand Down Expand Up @@ -546,6 +563,27 @@ mod tests {
Ok(())
}

#[tokio::test]
async fn async_run_command_should_include_ulimits() -> anyhow::Result<()> {
let image = GenericImage::new("hello-world", "latest");
let container = image.with_ulimit("nofile", 123, Some(456)).start().await?;

let client = Client::lazy_client().await?;
let container_details = client.inspect(container.id()).await?;

let ulimits = container_details
.host_config
.expect("HostConfig")
.ulimits
.expect("Privileged");

assert_eq!(ulimits.len(), 1);
assert_eq!(ulimits[0].name, Some("nofile".into()));
assert_eq!(ulimits[0].soft, Some(123));
assert_eq!(ulimits[0].hard, Some(456));
Ok(())
}

#[tokio::test]
async fn async_run_command_should_have_host_cgroupns_mode() -> anyhow::Result<()> {
let image = GenericImage::new("hello-world", "latest");
Expand Down
20 changes: 20 additions & 0 deletions testcontainers/src/runners/sync_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,26 @@ mod tests {
Ok(())
}

#[test]
fn sync_run_command_should_include_ulimits() -> anyhow::Result<()> {
let image = GenericImage::new("hello-world", "latest");
let container = image.with_ulimit("nofile", 123, Some(456)).start()?;

let container_details = inspect(container.id());

let ulimits = container_details
.host_config
.expect("HostConfig")
.ulimits
.expect("Privileged");

assert_eq!(ulimits.len(), 1);
assert_eq!(ulimits[0].name, Some("nofile".into()));
assert_eq!(ulimits[0].soft, Some(123));
assert_eq!(ulimits[0].hard, Some(456));
Ok(())
}

#[test]
fn sync_run_command_should_set_shared_memory_size() -> anyhow::Result<()> {
let image = GenericImage::new("hello-world", "latest");
Expand Down

0 comments on commit b10b48f

Please sign in to comment.