|
2 | 2 | Represents Lambda runtime containers. |
3 | 3 | """ |
4 | 4 | import logging |
5 | | -from typing import List |
| 5 | +from pathlib import Path |
| 6 | +from typing import Dict, List |
6 | 7 |
|
| 8 | +from samcli.lib.build.workflow_config import LAYER_SUBFOLDERS |
| 9 | +from samcli.lib.providers.provider import LayerVersion |
7 | 10 | from samcli.lib.utils.packagetype import IMAGE |
8 | 11 | from samcli.local.docker.lambda_debug_settings import LambdaDebugSettings |
9 | 12 |
|
@@ -99,6 +102,7 @@ def __init__( |
99 | 102 | entry, container_env_vars = LambdaContainer._get_debug_settings(runtime, debug_options) |
100 | 103 | additional_options = LambdaContainer._get_additional_options(runtime, debug_options) |
101 | 104 | additional_volumes = LambdaContainer._get_additional_volumes(runtime, debug_options) |
| 105 | + layer_volume_mounts = LambdaContainer._get_layer_folder_mounts(layers) |
102 | 106 |
|
103 | 107 | _work_dir = self._WORKING_DIR |
104 | 108 | _entrypoint = None |
@@ -133,11 +137,60 @@ def __init__( |
133 | 137 | entrypoint=_entrypoint if _entrypoint else entry, |
134 | 138 | env_vars=env_vars, |
135 | 139 | container_opts=additional_options, |
136 | | - additional_volumes=additional_volumes, |
| 140 | + additional_volumes={**additional_volumes, **layer_volume_mounts}, |
137 | 141 | container_host=container_host, |
138 | 142 | container_host_interface=container_host_interface, |
139 | 143 | ) |
140 | 144 |
|
| 145 | + @staticmethod |
| 146 | + def _get_layer_folder_mounts(layers: List[LayerVersion]) -> Dict[str, Dict[str, str]]: |
| 147 | + """ |
| 148 | + Searches the code uri of the Layer to resolve any root level symlinks before |
| 149 | + the container is created |
| 150 | +
|
| 151 | + Paramters |
| 152 | + --------- |
| 153 | + layers: List[LayerVersion] |
| 154 | + A list of layers to check for any symlinks |
| 155 | +
|
| 156 | + Returns |
| 157 | + ------- |
| 158 | + Dict[str, Dict[str, str]] |
| 159 | + A dictonary representing the resolved file or directory and the bound path |
| 160 | + on the container |
| 161 | + """ |
| 162 | + layer_mappings: Dict[str, Dict[str, str]] = {} |
| 163 | + |
| 164 | + for layer in layers: |
| 165 | + # layer.compatible_runtimes can return None |
| 166 | + for runtime in layer.compatible_runtimes or []: |
| 167 | + layer_folder = LAYER_SUBFOLDERS[runtime] if runtime in LAYER_SUBFOLDERS else None |
| 168 | + |
| 169 | + # unsupported runtime for layers |
| 170 | + if not layer_folder: |
| 171 | + LOG.debug("Skipping symlink check for layer %s, unsupported runtime (%s)", layer.layer_id, runtime) |
| 172 | + continue |
| 173 | + |
| 174 | + # not locally built layer |
| 175 | + if not layer.codeuri: |
| 176 | + LOG.debug( |
| 177 | + "Skipping symlink check for layer %s, layer does not have locally defined resources", |
| 178 | + layer.layer_id, |
| 179 | + ) |
| 180 | + continue |
| 181 | + |
| 182 | + # eg. `.aws-sam/build/MyLayer` + `nodejs` |
| 183 | + artifact_layer_path = Path(layer.codeuri, layer_folder) |
| 184 | + # eg. `/opt` + `nodejs` |
| 185 | + container_bind_path = Path(LambdaImage._LAYERS_DIR, layer_folder) |
| 186 | + |
| 187 | + mappings = LambdaContainer._create_mapped_symlink_files( |
| 188 | + str(artifact_layer_path), str(container_bind_path) |
| 189 | + ) |
| 190 | + layer_mappings.update(mappings) |
| 191 | + |
| 192 | + return layer_mappings |
| 193 | + |
141 | 194 | @staticmethod |
142 | 195 | def _get_exposed_ports(debug_options): |
143 | 196 | """ |
|
0 commit comments