Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] CLI-227: add implicit context_mount to Image docker methods #2582

Closed
wants to merge 34 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
a650752
init
kramstrom Nov 28, 2024
7019599
patterns
kramstrom Dec 3, 2024
57fdb88
Merge branch 'main' of github.com:modal-labs/modal-client into kramst…
kramstrom Dec 3, 2024
13ca6a1
abs path
kramstrom Dec 3, 2024
e6adb96
Merge branch 'main' into kramstrom/cli-227-remove-context_mount-from
kramstrom Dec 4, 2024
c956397
Merge branch 'main' of github.com:modal-labs/modal-client into kramst…
kramstrom Dec 16, 2024
e861d5f
Merge branch 'main' of github.com:modal-labs/modal-client into kramst…
kramstrom Dec 16, 2024
034693e
add back context_mount
kramstrom Dec 16, 2024
bf61dc2
Merge branch 'main' of github.com:modal-labs/modal-client into kramst…
kramstrom Dec 16, 2024
b8d3e14
add back
kramstrom Dec 16, 2024
75346c1
update
kramstrom Dec 16, 2024
7e6546b
Merge branch 'main' of github.com:modal-labs/modal-client into kramst…
kramstrom Dec 17, 2024
b013546
dockerignore find
kramstrom Dec 17, 2024
b2cb8ce
use dockerignore
kramstrom Dec 18, 2024
21ec1e7
dockerfile match port
kramstrom Dec 18, 2024
d7c9e76
fix test
kramstrom Dec 18, 2024
24e4b57
Merge branch 'main' into kramstrom/cli-227-remove-context_mount-from
kramstrom Dec 18, 2024
37475c3
remove
kramstrom Dec 18, 2024
8c0b412
move
kramstrom Dec 18, 2024
ed19a20
renaming
kramstrom Dec 18, 2024
e67a264
remove
kramstrom Dec 18, 2024
e5c1545
ignore
kramstrom Dec 19, 2024
a4048fb
remove docker_copy_match
kramstrom Dec 19, 2024
b6b3d51
Merge branch 'main' of github.com:modal-labs/modal-client into kramst…
kramstrom Dec 19, 2024
b7ff573
auto dockerignore
kramstrom Dec 20, 2024
6ac1400
remove autodockerignore
kramstrom Dec 20, 2024
c44a6ea
name
kramstrom Dec 20, 2024
baac945
Merge branch 'main' of github.com:modal-labs/modal-client into kramst…
kramstrom Dec 20, 2024
97685a8
autodockerignore
kramstrom Dec 20, 2024
b52fdbb
move to inside load
kramstrom Dec 20, 2024
aa8a5b0
types
kramstrom Dec 20, 2024
fa89c54
move repr inside
kramstrom Dec 20, 2024
e83725c
fix
kramstrom Dec 20, 2024
41b55d2
fix . pattern
kramstrom Dec 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 104 additions & 0 deletions modal/_utils/docker_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# Copyright Modal Labs 2024
import re
import shlex
from pathlib import Path
from typing import Optional, Sequence

from ..exception import InvalidError


def extract_copy_command_patterns(dockerfile_lines: Sequence[str]) -> list[str]:
"""
Extract all COPY command sources from a Dockerfile.
Combines multiline COPY commands into a single line.
"""
copy_source_patterns: set[str] = set()
current_command = ""
copy_pattern = re.compile(r"^\s*COPY\s+(.+)$", re.IGNORECASE)

# First pass: handle line continuations and collect full commands
for line in dockerfile_lines:
line = line.strip()
if not line or line.startswith("#"):
# ignore comments and empty lines
continue

if current_command:
# Continue previous line
current_command += " " + line.rstrip("\\").strip()
else:
# Start new command
current_command = line.rstrip("\\").strip()

if not line.endswith("\\"):
# Command is complete

match = copy_pattern.match(current_command)
if match:
args = match.group(1)
parts = shlex.split(args)

if len(parts) >= 2:
# Last part is destination, everything else is a mount source
sources = parts[:-1]

for source in sources:
special_pattern = re.compile(r"^\s*--|\$\s*")
if special_pattern.match(source):
raise InvalidError(
f"COPY command: {source} using special flags/arguments/variables are not supported"
)

if source == ".":
copy_source_patterns.add("./**")
else:
copy_source_patterns.add(source)

current_command = ""

return list(copy_source_patterns)


def find_dockerignore_file(context_directory: Path, dockerfile_path: Optional[Path] = None) -> Optional[Path]:
"""
Find dockerignore file relative to current context directory
and if dockerfile path is provided, check if specific <dockerfile_name>.dockerignore
file exists in the same directory as <dockerfile_name>

Finds the most specific dockerignore file that exists.
"""

def valid_dockerignore_file(fp):
# fp has to exist
if not fp.exists():
return False
# fp has to be subpath to current working directory
if not fp.is_relative_to(context_directory):
return False

return True

generic_name = ".dockerignore"
possible_locations = []
if dockerfile_path:
specific_name = f"{dockerfile_path.name}.dockerignore"
# 1. check if specific <dockerfile_name>.dockerignore file exists in the same directory as <dockerfile_name>
possible_locations.append(dockerfile_path.parent / specific_name)
# 2. check if generic .dockerignore file exists in the same directory as <dockerfile_name>
possible_locations.append(dockerfile_path.parent / generic_name)

# 3. check if generic .dockerignore file exists in current working directory
possible_locations.append(context_directory / generic_name)

return next((e for e in possible_locations if valid_dockerignore_file(e)), None)


class _AutoDockerIgnoreSentinel:
def __repr__(self) -> str:
return f"{__name__}.AUTO_DOCKERIGNORE"

def __call__(self, _: Path) -> bool:
raise NotImplementedError("This is only a placeholder. Do not call")


AUTO_DOCKERIGNORE = _AutoDockerIgnoreSentinel()
Loading
Loading