mirror of
https://github.com/pre-commit/pre-commit.git
synced 2026-02-19 17:14:43 +04:00
Merge pull request #3446 from matthewhughes934/fix-docker-rootless-permission-mounts
Fix permission errors for mounts in rootless docker
This commit is contained in:
commit
8a4af027a1
2 changed files with 73 additions and 0 deletions
|
|
@ -1,5 +1,6 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import functools
|
||||||
import hashlib
|
import hashlib
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
|
@ -101,7 +102,32 @@ def install_environment(
|
||||||
os.mkdir(directory)
|
os.mkdir(directory)
|
||||||
|
|
||||||
|
|
||||||
|
@functools.lru_cache(maxsize=1)
|
||||||
|
def _is_rootless() -> bool: # pragma: win32 no cover
|
||||||
|
retcode, out, _ = cmd_output_b(
|
||||||
|
'docker', 'system', 'info', '--format', '{{ json . }}',
|
||||||
|
)
|
||||||
|
if retcode != 0:
|
||||||
|
return False
|
||||||
|
|
||||||
|
info = json.loads(out)
|
||||||
|
try:
|
||||||
|
return (
|
||||||
|
# docker:
|
||||||
|
# https://docs.docker.com/reference/api/engine/version/v1.48/#tag/System/operation/SystemInfo
|
||||||
|
'name=rootless' in info.get('SecurityOptions', ()) or
|
||||||
|
# podman:
|
||||||
|
# https://docs.podman.io/en/latest/_static/api.html?version=v5.4#tag/system/operation/SystemInfoLibpod
|
||||||
|
info['host']['security']['rootless']
|
||||||
|
)
|
||||||
|
except KeyError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def get_docker_user() -> tuple[str, ...]: # pragma: win32 no cover
|
def get_docker_user() -> tuple[str, ...]: # pragma: win32 no cover
|
||||||
|
if _is_rootless():
|
||||||
|
return ()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return ('-u', f'{os.getuid()}:{os.getgid()}')
|
return ('-u', f'{os.getuid()}:{os.getgid()}')
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,42 @@ def test_docker_fallback_user():
|
||||||
assert docker.get_docker_user() == ()
|
assert docker.get_docker_user() == ()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(autouse=True)
|
||||||
|
def _avoid_cache():
|
||||||
|
with mock.patch.object(
|
||||||
|
docker,
|
||||||
|
'_is_rootless',
|
||||||
|
docker._is_rootless.__wrapped__,
|
||||||
|
):
|
||||||
|
yield
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
'info_ret',
|
||||||
|
(
|
||||||
|
(0, b'{"SecurityOptions": ["name=rootless","name=cgroupns"]}', b''),
|
||||||
|
(0, b'{"host": {"security": {"rootless": true}}}', b''),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
def test_docker_user_rootless(info_ret):
|
||||||
|
with mock.patch.object(docker, 'cmd_output_b', return_value=info_ret):
|
||||||
|
assert docker.get_docker_user() == ()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
'info_ret',
|
||||||
|
(
|
||||||
|
(0, b'{"SecurityOptions": ["name=cgroupns"]}', b''),
|
||||||
|
(0, b'{"host": {"security": {"rootless": false}}}', b''),
|
||||||
|
(0, b'{"respone_from_some_other_container_engine": true}', b''),
|
||||||
|
(1, b'', b''),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
def test_docker_user_non_rootless(info_ret):
|
||||||
|
with mock.patch.object(docker, 'cmd_output_b', return_value=info_ret):
|
||||||
|
assert docker.get_docker_user() != ()
|
||||||
|
|
||||||
|
|
||||||
def test_in_docker_no_file():
|
def test_in_docker_no_file():
|
||||||
with mock.patch.object(builtins, 'open', side_effect=FileNotFoundError):
|
with mock.patch.object(builtins, 'open', side_effect=FileNotFoundError):
|
||||||
assert docker._is_in_docker() is False
|
assert docker._is_in_docker() is False
|
||||||
|
|
@ -195,3 +231,14 @@ CMD ["echo", "This is overwritten by the entry"']
|
||||||
|
|
||||||
ret = run_language(tmp_path, docker, 'echo hello hello world')
|
ret = run_language(tmp_path, docker, 'echo hello hello world')
|
||||||
assert ret == (0, b'hello hello world\n')
|
assert ret == (0, b'hello hello world\n')
|
||||||
|
|
||||||
|
|
||||||
|
@xfailif_windows # pragma: win32 no cover
|
||||||
|
def test_docker_hook_mount_permissions(tmp_path):
|
||||||
|
dockerfile = '''\
|
||||||
|
FROM ubuntu:22.04
|
||||||
|
'''
|
||||||
|
tmp_path.joinpath('Dockerfile').write_text(dockerfile)
|
||||||
|
|
||||||
|
retcode, _ = run_language(tmp_path, docker, 'touch', ('README.md',))
|
||||||
|
assert retcode == 0
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue