2017-12-01 04:09:14 +00:00
|
|
|
"""
|
2020-06-12 17:03:48 +00:00
|
|
|
Test that build time memory limits are enforced
|
2017-12-01 04:09:14 +00:00
|
|
|
"""
|
2018-12-17 12:11:45 +00:00
|
|
|
|
2017-12-01 04:09:14 +00:00
|
|
|
import os
|
|
|
|
|
2019-05-08 11:20:31 +00:00
|
|
|
from unittest.mock import MagicMock
|
|
|
|
|
|
|
|
import docker
|
|
|
|
|
2018-12-17 12:11:45 +00:00
|
|
|
import pytest
|
|
|
|
|
2019-05-08 11:20:31 +00:00
|
|
|
from repo2docker.buildpacks import BaseImage, DockerBuildPack
|
2018-12-17 12:11:45 +00:00
|
|
|
|
|
|
|
|
|
|
|
basedir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
|
|
|
|
|
|
|
2020-06-12 17:03:48 +00:00
|
|
|
def test_memory_limit_enforced(tmpdir):
|
|
|
|
fake_cache_from = ["image-1:latest"]
|
|
|
|
fake_log_value = {"stream": "fake"}
|
|
|
|
fake_client = MagicMock(spec=docker.APIClient)
|
|
|
|
fake_client.build.return_value = iter([fake_log_value])
|
|
|
|
fake_extra_build_kwargs = {"somekey": "somevalue"}
|
|
|
|
|
|
|
|
# some memory limit value, the important bit is that this value is
|
|
|
|
# later passed to the `build` method of the Docker API client
|
|
|
|
memory_limit = 128 * 1024
|
|
|
|
|
|
|
|
# Test that the buildpack passes the right arguments to the docker
|
|
|
|
# client in order to enforce the memory limit
|
|
|
|
tmpdir.chdir()
|
|
|
|
for line in BaseImage().build(
|
|
|
|
fake_client,
|
|
|
|
"image-2",
|
|
|
|
memory_limit,
|
|
|
|
{},
|
|
|
|
fake_cache_from,
|
|
|
|
fake_extra_build_kwargs,
|
|
|
|
):
|
|
|
|
pass
|
|
|
|
|
|
|
|
# check that we pass arguments asking for memory limiting
|
|
|
|
# to the Docker API client
|
|
|
|
args, kwargs = fake_client.build.call_args
|
|
|
|
assert "container_limits" in kwargs
|
|
|
|
assert kwargs["container_limits"] == {
|
|
|
|
"memory": memory_limit,
|
|
|
|
"memswap": memory_limit,
|
|
|
|
}
|
2017-12-01 04:09:14 +00:00
|
|
|
|
2017-12-01 08:41:50 +00:00
|
|
|
|
|
|
|
def test_memlimit_same_postbuild():
|
|
|
|
"""
|
2020-06-12 17:03:48 +00:00
|
|
|
Validate that the postBuild files for the dockerfile and non-dockerfile
|
|
|
|
tests are the same
|
2017-12-01 08:41:50 +00:00
|
|
|
|
2020-08-10 07:33:05 +00:00
|
|
|
Until https://github.com/jupyterhub/repo2docker/issues/160 gets fixed.
|
2017-12-01 08:41:50 +00:00
|
|
|
"""
|
|
|
|
filepaths = [
|
2019-05-31 09:10:17 +00:00
|
|
|
os.path.join(basedir, "memlimit", t, "postBuild")
|
2017-12-01 08:41:50 +00:00
|
|
|
for t in ("dockerfile", "non-dockerfile")
|
|
|
|
]
|
|
|
|
file_contents = []
|
|
|
|
for fp in filepaths:
|
|
|
|
with open(fp) as f:
|
|
|
|
file_contents.append(f.read())
|
2017-12-01 08:46:29 +00:00
|
|
|
# Make sure they're all the same
|
|
|
|
assert len(set(file_contents)) == 1
|
2019-05-08 11:20:31 +00:00
|
|
|
|
|
|
|
|
2019-05-31 09:10:17 +00:00
|
|
|
@pytest.mark.parametrize("BuildPack", [BaseImage, DockerBuildPack])
|
2019-05-08 11:20:31 +00:00
|
|
|
def test_memlimit_argument_type(BuildPack):
|
|
|
|
# check that an exception is raised when the memory limit isn't an int
|
2019-05-31 09:10:17 +00:00
|
|
|
fake_log_value = {"stream": "fake"}
|
2019-05-08 11:20:31 +00:00
|
|
|
fake_client = MagicMock(spec=docker.APIClient)
|
|
|
|
fake_client.build.return_value = iter([fake_log_value])
|
|
|
|
|
|
|
|
with pytest.raises(ValueError) as exc_info:
|
2019-05-31 09:10:17 +00:00
|
|
|
for line in BuildPack().build(fake_client, "image-2", "10Gi", {}, [], {}):
|
2019-05-08 11:20:31 +00:00
|
|
|
pass
|
|
|
|
|
|
|
|
assert "The memory limit has to be specified as an" in str(exc_info.value)
|