Skip to content

Commit 30df742

Browse files
authored
Merge branch 'develop' into fix-8477
2 parents 545bb0e + 34da7c8 commit 30df742

34 files changed

Lines changed: 474 additions & 36 deletions

File tree

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,9 @@ pre-dev = [
6868
dev = [
6969
"aws-sam-cli[pre-dev]",
7070
"coverage==7.13.4",
71-
"pytest-cov==7.0.0",
71+
"pytest-cov==7.1.0",
7272
"mypy==1.19.1",
73-
"types-pywin32==311.0.0.20260316",
73+
"types-pywin32==311.0.0.20260323",
7474
"types-PyYAML==6.0.12.20250915",
7575
"types-chevron==0.14.2.20250103",
7676
"types-psutil==7.2.2.20260130",

samcli/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
SAM CLI version
33
"""
44

5-
__version__ = "1.156.0"
5+
__version__ = "1.157.1"

samcli/commands/_utils/custom_options/hook_name_option.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ def _call_prepare_hook(self, iac_hook_wrapper, opts, ctx):
9090
skip_prepare_infra = _read_parameter_value("skip_prepare_infra", opts, ctx, False)
9191
plan_file = _read_parameter_value("terraform_plan_file", opts, ctx)
9292
project_root_dir = _read_parameter_value("terraform_project_root_path", opts, ctx)
93+
mount_symlinks = _read_parameter_value("mount_symlinks", opts, ctx, False)
9394

9495
metadata_file = iac_hook_wrapper.prepare(
9596
output_dir_path,
@@ -100,6 +101,7 @@ def _call_prepare_hook(self, iac_hook_wrapper, opts, ctx):
100101
skip_prepare_infra,
101102
plan_file,
102103
project_root_dir,
104+
mount_symlinks,
103105
)
104106

105107
LOG.info("Prepare hook completed and metadata file generated at: %s", metadata_file)

samcli/commands/local/cli_common/invoke_context.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,9 @@ def function_identifier(self) -> str:
563563
@property
564564
def lambda_runtime(self) -> LambdaRuntime:
565565
if not self._lambda_runtimes:
566-
layer_downloader = LayerDownloader(self._layer_cache_basedir, self.get_cwd(), self._stacks)
566+
layer_downloader = LayerDownloader(
567+
self._layer_cache_basedir, self.get_cwd(), self._stacks, mount_symlinks=self._mount_symlinks
568+
)
567569
image_builder = LambdaImage(
568570
layer_downloader, self._skip_pull_image, self._force_image_build, invoke_images=self._invoke_images
569571
)

samcli/hook_packages/terraform/copy_terraform_built_artifacts.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ def cli_exit():
218218
sys.exit(1)
219219

220220

221-
def find_and_copy_assets(directory_path, expression, data_object):
221+
def find_and_copy_assets(directory_path, expression, data_object, mount_symlinks=False):
222222
"""
223223
Takes in an expression, directory_path and a json input from the standard input,
224224
tries to find the appropriate element within the json based on the element. It then takes action to
@@ -264,7 +264,7 @@ def find_and_copy_assets(directory_path, expression, data_object):
264264

265265
try:
266266
if zipfile.is_zipfile(abs_attribute_path):
267-
unzip(abs_attribute_path, directory_path)
267+
unzip(abs_attribute_path, directory_path, mount_symlinks=mount_symlinks)
268268
else:
269269
copytree(abs_attribute_path, directory_path)
270270
except OSError as ex:
@@ -342,12 +342,19 @@ def validate_environment_variables():
342342
required=False,
343343
help="Terraform output json body. This option is not to be used with --target.",
344344
)
345+
argparser.add_argument(
346+
"--mount-symlinks",
347+
action="store_true",
348+
default=False,
349+
help="Allow symlinks pointing outside the extraction directory when unzipping artifacts.",
350+
)
345351

346352
arguments = argparser.parse_args()
347353
directory_path = os.path.abspath(arguments.directory)
348354
expression = arguments.expression
349355
target = arguments.target
350356
json_str = arguments.json
357+
mount_symlinks = arguments.mount_symlinks
351358

352359
# validate environment variables do not contain blocked arguments
353360
validate_environment_variables()
@@ -384,4 +391,4 @@ def validate_environment_variables():
384391
cli_exit()
385392

386393
LOG.info("Find and copy built assets")
387-
find_and_copy_assets(directory_path, expression, data_object)
394+
find_and_copy_assets(directory_path, expression, data_object, mount_symlinks=mount_symlinks)

samcli/hook_packages/terraform/hooks/prepare/enrich.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ def enrich_resources_and_generate_makefile(
5252
terraform_application_dir: str,
5353
lambda_resources_to_code_map: Dict,
5454
project_root_dir: str,
55+
mount_symlinks: bool = False,
5556
) -> None:
5657
"""
5758
Use the sam metadata resources to enrich the mapped resources and to create a Makefile with a rule for
@@ -111,7 +112,12 @@ def enrich_resources_and_generate_makefile(
111112

112113
# get makefile rule for resource
113114
makefile_rule = generate_makefile_rule_for_lambda_resource(
114-
sam_metadata_resource, logical_id, terraform_application_dir, python_command_name, output_directory_path
115+
sam_metadata_resource,
116+
logical_id,
117+
terraform_application_dir,
118+
python_command_name,
119+
output_directory_path,
120+
mount_symlinks=mount_symlinks,
115121
)
116122
makefile_rules.append(makefile_rule)
117123

samcli/hook_packages/terraform/hooks/prepare/hook.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ def prepare(params: dict) -> dict:
9494
LOG.debug("The normalized OutputDirPath value is %s", output_dir_path)
9595

9696
skip_prepare_infra = params.get("SkipPrepareInfra", False)
97+
mount_symlinks = params.get("MountSymlinks", False)
9798
metadata_file_path = os.path.join(output_dir_path, TERRAFORM_METADATA_FILE)
9899

99100
plan_file = params.get("PlanFile")
@@ -112,7 +113,9 @@ def prepare(params: dict) -> dict:
112113

113114
# convert terraform to cloudformation
114115
LOG.info("Generating metadata file")
115-
cfn_dict = translate_to_cfn(tf_json, output_dir_path, terraform_application_dir, project_root_dir)
116+
cfn_dict = translate_to_cfn(
117+
tf_json, output_dir_path, terraform_application_dir, project_root_dir, mount_symlinks=mount_symlinks
118+
)
116119

117120
if cfn_dict.get("Resources"):
118121
_update_resources_paths(cfn_dict.get("Resources"), terraform_application_dir) # type: ignore

samcli/hook_packages/terraform/hooks/prepare/makefile_generator.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ def generate_makefile_rule_for_lambda_resource(
2929
terraform_application_dir: str,
3030
python_command_name: str,
3131
output_dir: str,
32+
mount_symlinks: bool = False,
3233
) -> str:
3334
"""
3435
Generates and returns a makefile rule for the lambda resource associated with the given sam metadata resource.
@@ -56,7 +57,12 @@ def generate_makefile_rule_for_lambda_resource(
5657
resource_address = sam_metadata_resource.resource.get("address", "")
5758
python_command_recipe = _format_makefile_recipe(
5859
_build_makerule_python_command(
59-
python_command_name, output_dir, resource_address, sam_metadata_resource, terraform_application_dir
60+
python_command_name,
61+
output_dir,
62+
resource_address,
63+
sam_metadata_resource,
64+
terraform_application_dir,
65+
mount_symlinks=mount_symlinks,
6066
)
6167
)
6268
return f"{target}{python_command_recipe}"
@@ -124,6 +130,7 @@ def _build_makerule_python_command(
124130
resource_address: str,
125131
sam_metadata_resource: SamMetadataResource,
126132
terraform_application_dir: str,
133+
mount_symlinks: bool = False,
127134
) -> str:
128135
"""
129136
Build the Python command recipe to be used inside of the Makefile rule
@@ -155,12 +162,15 @@ def _build_makerule_python_command(
155162
terraform_built_artifacts_script_path = convert_path_to_unix_path(
156163
str(Path(output_dir, TERRAFORM_BUILD_SCRIPT).relative_to(terraform_application_dir))
157164
)
158-
return show_command_template.format(
165+
command = show_command_template.format(
159166
python_command_name=python_command_name,
160167
terraform_built_artifacts_script_path=terraform_built_artifacts_script_path,
161168
jpath_string=jpath_string.replace('"', '\\"'),
162169
resource_address=resource_address.replace('"', '\\"'),
163170
)
171+
if mount_symlinks:
172+
command += " --mount-symlinks"
173+
return command
164174

165175

166176
def _get_makefile_build_target(logical_id: str) -> str:

samcli/hook_packages/terraform/hooks/prepare/translate.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,11 @@ def _check_unresolvable_values(root_module: dict, root_tf_module: TFModule) -> N
152152

153153

154154
def translate_to_cfn(
155-
tf_json: dict, output_directory_path: str, terraform_application_dir: str, project_root_dir: str
155+
tf_json: dict,
156+
output_directory_path: str,
157+
terraform_application_dir: str,
158+
project_root_dir: str,
159+
mount_symlinks: bool = False,
156160
) -> dict:
157161
"""
158162
Translates the json output of a terraform show into CloudFormation
@@ -339,6 +343,7 @@ def translate_to_cfn(
339343
terraform_application_dir,
340344
lambda_resources_to_code_map,
341345
project_root_dir,
346+
mount_symlinks=mount_symlinks,
342347
)
343348
else:
344349
LOG.debug("There is no sam metadata resources, no enrichment or Makefile is required")

samcli/lib/hook/hook_wrapper.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ def prepare(
5454
skip_prepare_infra: bool = False,
5555
plan_file: Optional[str] = None,
5656
project_root_dir: Optional[str] = None,
57+
mount_symlinks: bool = False,
5758
) -> str:
5859
"""
5960
Run the prepare hook to generate the IaC Metadata file.
@@ -96,6 +97,8 @@ def prepare(
9697
params["PlanFile"] = plan_file
9798
if project_root_dir:
9899
params["ProjectRootDir"] = project_root_dir
100+
if mount_symlinks:
101+
params["MountSymlinks"] = mount_symlinks
99102

100103
output = self._execute("prepare", params)
101104

0 commit comments

Comments
 (0)