@@ -101,6 +101,7 @@ def __init__(
101101 mount_with_write : bool = False ,
102102 host_tmp_dir : Optional [str ] = None ,
103103 extra_hosts : Optional [dict ] = None ,
104+ mount_symlinks : Optional [bool ] = False ,
104105 ):
105106 """
106107 Initializes the class with given configuration. This does not automatically create or run the container.
@@ -123,6 +124,7 @@ def __init__(
123124 building on container
124125 :param string host_tmp_dir: Optional. Temporary directory on the host when mounting with write permissions.
125126 :param dict extra_hosts: Optional. Dict of hostname to IP resolutions
127+ :param bool mount_symlinks: Optional. True if symlinks should be mounted in the container
126128 """
127129
128130 self ._image = image
@@ -155,6 +157,7 @@ def __init__(
155157 self ._container_host_interface = container_host_interface
156158 self ._mount_with_write = mount_with_write
157159 self ._host_tmp_dir = host_tmp_dir
160+ self ._mount_symlinks = mount_symlinks
158161
159162 try :
160163 self .rapid_port_host = find_free_port (
@@ -183,7 +186,10 @@ def create(self, context):
183186 if self ._host_dir :
184187 mount_mode = "rw,delegated" if self ._mount_with_write else "ro,delegated"
185188 LOG .info ("Mounting %s as %s:%s, inside runtime container" , self ._host_dir , self ._working_dir , mount_mode )
186- mapped_symlinks = self ._create_mapped_symlink_files () if self ._resolve_symlinks (context ) else {}
189+ if self ._resolve_symlinks_in_context (context ) or self ._mount_symlinks :
190+ mapped_symlinks = self ._create_mapped_symlink_files ()
191+ else :
192+ mapped_symlinks = {}
187193
188194 _volumes = {
189195 self ._host_dir : {
@@ -270,16 +276,18 @@ def create(self, context):
270276
271277 def _create_mapped_symlink_files (self ) -> Dict [str , Dict [str , str ]]:
272278 """
273- Resolves any top level symlinked files and folders that are found on the
279+ Resolves top level symlinked files and folders that are found on the
274280 host directory and creates additional bind mounts to correctly map them
275281 inside of the container.
282+ By default only `node_modules` are mounted unless self.mount_symlinks is True
276283
277284 Returns
278285 -------
279286 Dict[str, Dict[str, str]]
280287 A dictonary representing the resolved file or directory and the bound path
281288 on the container
282289 """
290+
283291 mount_mode = "ro,delegated"
284292 additional_volumes : Dict [str , Dict [str , str ]] = {}
285293
@@ -291,10 +299,15 @@ def _create_mapped_symlink_files(self) -> Dict[str, Dict[str, str]]:
291299 for file in directory_iterator :
292300 if not file .is_symlink ():
293301 continue
294-
295302 host_resolved_path = os .path .realpath (file .path )
303+ if not self ._resolve_symlinks_for_file (file ) and not self ._mount_symlinks :
304+ LOG .info (
305+ "Not mounting symlink (%s -> %s) by default. "
306+ "Use --mount-symlinks to always mount symlinks in the container"
307+ % (file .path , host_resolved_path )
308+ )
309+ continue
296310 container_full_path = pathlib .Path (self ._working_dir , file .name ).as_posix ()
297-
298311 additional_volumes [host_resolved_path ] = {
299312 "bind" : container_full_path ,
300313 "mode" : mount_mode ,
@@ -659,12 +672,12 @@ def is_running(self):
659672 except docker .errors .NotFound :
660673 return False
661674
662- def _resolve_symlinks (self , context ) -> bool :
663- """_summary_
675+ def _resolve_symlinks_in_context (self , context ) -> bool :
676+ """
664677
665678 Parameters
666679 ----------
667- context : sacli .local.docker.container.ContainerContext
680+ context : samcli .local.docker.container.ContainerContext
668681 Context for the container management to run. (build, invoke)
669682
670683 Returns
@@ -673,3 +686,21 @@ def _resolve_symlinks(self, context) -> bool:
673686 True, if given these parameters it should resolve symlinks or not
674687 """
675688 return bool (context != ContainerContext .BUILD )
689+
690+ def _resolve_symlinks_for_file (self , file : os .DirEntry ) -> bool :
691+ """
692+
693+ Parameters
694+ ----------
695+ file : os.DirEntry
696+ File to check if it should be resolved
697+
698+ Returns
699+ -------
700+ bool
701+ True if the file should be resolved as a symlink to mount in the container.
702+ By default, the only symlinks resolved are `node_modules` used by build-in-source
703+ """
704+ resolved_path = os .path .realpath (file .path ) # resolved symlink
705+ resolved_name = os .path .basename (resolved_path )
706+ return bool (resolved_name == "node_modules" )
0 commit comments