From 792c6daedaac528ed966bafc933817ad06fce02e Mon Sep 17 00:00:00 2001 From: Connor Kirkpatrick Date: Tue, 1 Aug 2023 00:30:35 +0100 Subject: [PATCH 01/13] chore: Update CFN Lint version to support python 3.11 (#5651) * Update CFN Lint version to support python 3.11 * Run make update-reproducible-reqs --------- Co-authored-by: Mohamed Elasmar <71043312+moelasmar@users.noreply.github.com> --- requirements/base.txt | 2 +- requirements/reproducible-linux.txt | 6 +++--- requirements/reproducible-mac.txt | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/requirements/base.txt b/requirements/base.txt index 11e1c7f068..80725f827c 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -31,7 +31,7 @@ regex!=2021.10.8 tzlocal==3.0 #Adding cfn-lint dependency for SAM validate -cfn-lint~=0.78.1 +cfn-lint~=0.79.5 # Type checking boto3 objects boto3-stubs[apigateway,cloudformation,ecr,iam,lambda,s3,schemas,secretsmanager,signer,stepfunctions,sts,xray]==1.28.2 diff --git a/requirements/reproducible-linux.txt b/requirements/reproducible-linux.txt index 60823b5628..916aa45e7b 100644 --- a/requirements/reproducible-linux.txt +++ b/requirements/reproducible-linux.txt @@ -119,9 +119,9 @@ cffi==1.15.1 \ --hash=sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01 \ --hash=sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0 # via cryptography -cfn-lint==0.78.1 \ - --hash=sha256:2dacb19d5f70c0d49f466302507707cfa4914f65b8fc9310ae3771a273cec044 \ - --hash=sha256:46118362b2e13b79ba3ae6b3c28b7df5fcd437c06f5bcc3384d13a2defdb7d06 +cfn-lint==0.79.5 \ + --hash=sha256:3054a2e407f77b3115c41de49fe2c11d728d53ab7be4ae478c1b5ff0e21331b7 \ + --hash=sha256:7a00dba8f70b8a92c38bfc8f45e2ab20cedad5c49054a46f1ce931e48fc1cd0c # via aws-sam-cli (setup.py) chardet==5.1.0 \ --hash=sha256:0d62712b956bc154f85fb0a266e2a3c5913c2967e00348701b32411d6def31e5 \ diff --git a/requirements/reproducible-mac.txt b/requirements/reproducible-mac.txt index 15c74810ca..be1c8f439e 100644 --- a/requirements/reproducible-mac.txt +++ b/requirements/reproducible-mac.txt @@ -137,9 +137,9 @@ cffi==1.15.1 \ --hash=sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01 \ --hash=sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0 # via cryptography -cfn-lint==0.78.1 \ - --hash=sha256:2dacb19d5f70c0d49f466302507707cfa4914f65b8fc9310ae3771a273cec044 \ - --hash=sha256:46118362b2e13b79ba3ae6b3c28b7df5fcd437c06f5bcc3384d13a2defdb7d06 +cfn-lint==0.79.5 \ + --hash=sha256:3054a2e407f77b3115c41de49fe2c11d728d53ab7be4ae478c1b5ff0e21331b7 \ + --hash=sha256:7a00dba8f70b8a92c38bfc8f45e2ab20cedad5c49054a46f1ce931e48fc1cd0c # via aws-sam-cli (setup.py) chardet==5.1.0 \ --hash=sha256:0d62712b956bc154f85fb0a266e2a3c5913c2967e00348701b32411d6def31e5 \ From e0de9987f5321f1fb1926aff32f1fa768d9eeb48 Mon Sep 17 00:00:00 2001 From: Lucas <12496191+lucashuy@users.noreply.github.com> Date: Mon, 31 Jul 2023 16:37:07 -0700 Subject: [PATCH 02/13] fix: Require file label to run before maintainers (#5656) * Require file label to run before maintainers * Run maintainer label job even if previous job fails --- .github/workflows/pr-labeler.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/pr-labeler.yml b/.github/workflows/pr-labeler.yml index 16f48ae22f..fa38d437e2 100644 --- a/.github/workflows/pr-labeler.yml +++ b/.github/workflows/pr-labeler.yml @@ -13,6 +13,8 @@ jobs: with: repo-token: "${{ secrets.GITHUB_TOKEN }}" apply-internal-external-label: + needs: apply-file-based-labels + if: ${{ always() }} permissions: pull-requests: write runs-on: ubuntu-latest From d264edd40cc14a8f2f5f80f12c4ce58d17b8eabf Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 1 Aug 2023 02:26:09 +0000 Subject: [PATCH 03/13] chore: update aws_lambda_builders to 1.36.0 (#5655) Co-authored-by: GitHub Action Co-authored-by: Mohamed Elasmar <71043312+moelasmar@users.noreply.github.com> --- requirements/base.txt | 2 +- requirements/reproducible-linux.txt | 6 +++--- requirements/reproducible-mac.txt | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/requirements/base.txt b/requirements/base.txt index 80725f827c..299e4dbe48 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -14,7 +14,7 @@ aws-sam-translator==1.71.0 docker~=6.1.0 dateparser~=1.1 requests~=2.31.0 -aws_lambda_builders==1.35.0 +aws_lambda_builders==1.36.0 tomlkit==0.11.8 watchdog==2.1.2 rich~=13.4.2 diff --git a/requirements/reproducible-linux.txt b/requirements/reproducible-linux.txt index 916aa45e7b..354b363df0 100644 --- a/requirements/reproducible-linux.txt +++ b/requirements/reproducible-linux.txt @@ -15,9 +15,9 @@ attrs==23.1.0 \ # jschema-to-python # jsonschema # sarif-om -aws-lambda-builders==1.35.0 \ - --hash=sha256:419d766e60ac2a7303a23889b354d108a4244ce8d467dcf9dc71a62461895780 \ - --hash=sha256:cf462961ec8c9d493f82b955d6b76630dc0ed356b166caddd5436719ce599586 +aws-lambda-builders==1.36.0 \ + --hash=sha256:00ce31612a62dc8fa1a2dcd087648d125b6274ff8b18799d3ebe5bb4824f3e96 \ + --hash=sha256:b673b13d72ab9a85523e70a0980a8df86868bcf285d1ae1c032bb747bfc5b5d1 # via aws-sam-cli (setup.py) aws-sam-translator==1.71.0 \ --hash=sha256:17fb87c8137d8d49e7a978396b2b3b279211819dee44618415aab1e99c2cb659 \ diff --git a/requirements/reproducible-mac.txt b/requirements/reproducible-mac.txt index be1c8f439e..08062fd84e 100644 --- a/requirements/reproducible-mac.txt +++ b/requirements/reproducible-mac.txt @@ -15,9 +15,9 @@ attrs==23.1.0 \ # jschema-to-python # jsonschema # sarif-om -aws-lambda-builders==1.35.0 \ - --hash=sha256:419d766e60ac2a7303a23889b354d108a4244ce8d467dcf9dc71a62461895780 \ - --hash=sha256:cf462961ec8c9d493f82b955d6b76630dc0ed356b166caddd5436719ce599586 +aws-lambda-builders==1.36.0 \ + --hash=sha256:00ce31612a62dc8fa1a2dcd087648d125b6274ff8b18799d3ebe5bb4824f3e96 \ + --hash=sha256:b673b13d72ab9a85523e70a0980a8df86868bcf285d1ae1c032bb747bfc5b5d1 # via aws-sam-cli (setup.py) aws-sam-translator==1.71.0 \ --hash=sha256:17fb87c8137d8d49e7a978396b2b3b279211819dee44618415aab1e99c2cb659 \ From 253852cbd844075321b9d69108db2c9ee6913b5a Mon Sep 17 00:00:00 2001 From: Jacob Fuss <32497805+jfuss@users.noreply.github.com> Date: Tue, 1 Aug 2023 14:00:31 -0500 Subject: [PATCH 04/13] fix(invoke): Write in UTF-8 string instead of bytes (#5642) * Revert "fix: Revert UTF-8 fixes #5485 and #5427 (#5512)" This reverts commit 36f8bf970df7a8072eef58ca76405c40e1cc1c90. * Enforce utf8 on stdout/stderr/logfile --------- Co-authored-by: Jacob Fuss --- .../local/cli_common/invoke_context.py | 8 ++-- .../commands/remote/remote_invoke_context.py | 4 +- samcli/lib/docker/log_streamer.py | 28 +++++------ samcli/lib/package/ecr_uploader.py | 4 +- samcli/lib/package/s3_uploader.py | 2 +- samcli/lib/utils/osutils.py | 19 ++++++-- samcli/lib/utils/stream_writer.py | 25 ++++++++-- samcli/lib/utils/subprocess_utils.py | 4 +- samcli/local/apigw/local_apigw_service.py | 4 +- samcli/local/docker/container.py | 47 +++++++++++++++---- samcli/local/docker/lambda_image.py | 11 +++-- samcli/local/docker/manager.py | 6 +-- .../local_lambda_invoke_service.py | 2 +- samcli/local/services/base_local_service.py | 4 +- .../local/invoke/test_integrations_cli.py | 21 +++++++++ .../local/cli_common/test_invoke_context.py | 2 +- tests/unit/lib/utils/test_osutils.py | 8 ---- tests/unit/lib/utils/test_stream_writer.py | 11 +++-- tests/unit/lib/utils/test_subprocess_utils.py | 13 ++--- tests/unit/local/docker/test_container.py | 29 ++++++------ tests/unit/local/docker/test_lambda_image.py | 9 ++-- tests/unit/local/docker/test_manager.py | 24 +++++++--- .../local/services/test_base_local_service.py | 18 +++---- 23 files changed, 191 insertions(+), 112 deletions(-) diff --git a/samcli/commands/local/cli_common/invoke_context.py b/samcli/commands/local/cli_common/invoke_context.py index 837b122558..30dc8b4c03 100644 --- a/samcli/commands/local/cli_common/invoke_context.py +++ b/samcli/commands/local/cli_common/invoke_context.py @@ -7,7 +7,7 @@ import os from enum import Enum from pathlib import Path -from typing import IO, Any, Dict, List, Optional, Tuple, Type, cast +from typing import Any, Dict, List, Optional, TextIO, Tuple, Type, cast from samcli.commands._utils.template import TemplateFailedParsingException, TemplateNotFoundException from samcli.commands.exceptions import ContainersInitializationException @@ -196,7 +196,7 @@ def __init__( self._stacks: List[Stack] = None # type: ignore self._env_vars_value: Optional[Dict] = None self._container_env_vars_value: Optional[Dict] = None - self._log_file_handle: Optional[IO] = None + self._log_file_handle: Optional[TextIO] = None self._debug_context: Optional[DebugContext] = None self._layers_downloader: Optional[LayerDownloader] = None self._container_manager: Optional[ContainerManager] = None @@ -490,7 +490,7 @@ def _get_env_vars_value(filename: Optional[str]) -> Optional[Dict]: ) from ex @staticmethod - def _setup_log_file(log_file: Optional[str]) -> Optional[IO]: + def _setup_log_file(log_file: Optional[str]) -> Optional[TextIO]: """ Open a log file if necessary and return the file handle. This will create a file if it does not exist @@ -500,7 +500,7 @@ def _setup_log_file(log_file: Optional[str]) -> Optional[IO]: if not log_file: return None - return open(log_file, "wb") + return open(log_file, "w", encoding="utf8") @staticmethod def _get_debug_context( diff --git a/samcli/commands/remote/remote_invoke_context.py b/samcli/commands/remote/remote_invoke_context.py index b710df8410..d1294983bc 100644 --- a/samcli/commands/remote/remote_invoke_context.py +++ b/samcli/commands/remote/remote_invoke_context.py @@ -242,7 +242,7 @@ class DefaultRemoteInvokeResponseConsumer(RemoteInvokeConsumer[RemoteInvokeRespo _stream_writer: StreamWriter def consume(self, remote_invoke_response: RemoteInvokeResponse) -> None: - self._stream_writer.write(cast(str, remote_invoke_response.response).encode()) + self._stream_writer.write_bytes(cast(str, remote_invoke_response.response).encode()) @dataclass @@ -254,4 +254,4 @@ class DefaultRemoteInvokeLogConsumer(RemoteInvokeConsumer[RemoteInvokeLogOutput] _stream_writer: StreamWriter def consume(self, remote_invoke_response: RemoteInvokeLogOutput) -> None: - self._stream_writer.write(remote_invoke_response.log_output.encode()) + self._stream_writer.write_bytes(remote_invoke_response.log_output.encode()) diff --git a/samcli/lib/docker/log_streamer.py b/samcli/lib/docker/log_streamer.py index b013459bae..3bb437781a 100644 --- a/samcli/lib/docker/log_streamer.py +++ b/samcli/lib/docker/log_streamer.py @@ -47,23 +47,21 @@ def stream_progress(self, logs: docker.APIClient.logs): else: curr_log_line_id = ids[_id] change_cursor_count = len(ids) - curr_log_line_id - self._stream.write( + self._stream.write_str( self._cursor_up_formatter.cursor_format(change_cursor_count) - + self._cursor_left_formatter.cursor_format(), - encode=True, + + self._cursor_left_formatter.cursor_format() ) self._stream_write(_id, status, stream, progress, error) if _id: - self._stream.write( + self._stream.write_str( self._cursor_down_formatter.cursor_format(change_cursor_count) - + self._cursor_left_formatter.cursor_format(), - encode=True, + + self._cursor_left_formatter.cursor_format() ) - self._stream.write(os.linesep, encode=True) + self._stream.write_str(os.linesep) - def _stream_write(self, _id: str, status: str, stream: bytes, progress: str, error: str): + def _stream_write(self, _id: str, status: str, stream: str, progress: str, error: str): """ Write stream information to stderr, if the stream information contains a log id, use the carriage return character to rewrite that particular line. @@ -80,14 +78,14 @@ def _stream_write(self, _id: str, status: str, stream: bytes, progress: str, err # NOTE(sriram-mv): Required for the purposes of when the cursor overflows existing terminal buffer. if not stream: - self._stream.write(os.linesep, encode=True) - self._stream.write( - self._cursor_up_formatter.cursor_format() + self._cursor_left_formatter.cursor_format(), encode=True + self._stream.write_str(os.linesep) + self._stream.write_str( + self._cursor_up_formatter.cursor_format() + self._cursor_left_formatter.cursor_format() ) - self._stream.write(self._cursor_clear_formatter.cursor_format(), encode=True) + self._stream.write_str(self._cursor_clear_formatter.cursor_format()) if not _id: - self._stream.write(stream, encode=True) - self._stream.write(status, encode=True) + self._stream.write_str(stream) + self._stream.write_str(status) else: - self._stream.write(f"\r{_id}: {status} {progress}", encode=True) + self._stream.write_str(f"\r{_id}: {status} {progress}") diff --git a/samcli/lib/package/ecr_uploader.py b/samcli/lib/package/ecr_uploader.py index f2d4371407..0393596b39 100644 --- a/samcli/lib/package/ecr_uploader.py +++ b/samcli/lib/package/ecr_uploader.py @@ -2,8 +2,8 @@ Client for uploading packaged artifacts to ecr """ import base64 -import io import logging +from io import StringIO from typing import Dict import botocore @@ -94,7 +94,7 @@ def upload(self, image, resource_name): else: # we need to wait till the image got pushed to ecr, without this workaround sam sync for template # contains image always fail, because the provided ecr uri is not exist. - _log_streamer = LogStreamer(stream=StreamWriter(stream=io.BytesIO(), auto_flush=True)) + _log_streamer = LogStreamer(stream=StreamWriter(stream=StringIO(), auto_flush=True)) _log_streamer.stream_progress(push_logs) except (BuildError, APIError, LogStreamError) as ex: diff --git a/samcli/lib/package/s3_uploader.py b/samcli/lib/package/s3_uploader.py index fe141ada51..95981e92ed 100644 --- a/samcli/lib/package/s3_uploader.py +++ b/samcli/lib/package/s3_uploader.py @@ -265,4 +265,4 @@ def on_progress(self, bytes_transferred, **kwargs): ) sys.stderr.flush() if int(percentage) == 100: # noqa: PLR2004 - sys.stderr.write("\n") + sys.stderr.write(os.linesep) diff --git a/samcli/lib/utils/osutils.py b/samcli/lib/utils/osutils.py index d53dc9ffb5..a9a12bf88c 100644 --- a/samcli/lib/utils/osutils.py +++ b/samcli/lib/utils/osutils.py @@ -1,6 +1,7 @@ """ Common OS utilities """ +import io import logging import os import shutil @@ -78,7 +79,7 @@ def rmtree_if_exists(path: Union[str, Path]): shutil.rmtree(path_obj) -def stdout(): +def stdout() -> io.TextIOWrapper: """ Returns the stdout as a byte stream in a Py2/PY3 compatible manner @@ -87,10 +88,15 @@ def stdout(): io.BytesIO Byte stream of Stdout """ - return sys.stdout.buffer + # ensure stdout is utf8 + sys.stdout.reconfigure(encoding="utf-8") # type:ignore[attr-defined] + # Note(jfuss): sys.stdout is a type typing.TextIO but are initialized to + # io.TextIOWrapper. To make mypy and typing play well, tell mypy to ignore. + return sys.stdout # type:ignore[return-value] -def stderr(): + +def stderr() -> io.TextIOWrapper: """ Returns the stderr as a byte stream in a Py2/PY3 compatible manner @@ -99,7 +105,12 @@ def stderr(): io.BytesIO Byte stream of stderr """ - return sys.stderr.buffer + # ensure stderr is utf8 + sys.stderr.reconfigure(encoding="utf-8") # type:ignore[attr-defined] + + # Note(jfuss): sys.stderr is a type typing.TextIO but are initialized to + # io.TextIOWrapper. To make mypy and typing play well, tell mypy to ignore. + return sys.stderr # type:ignore[return-value] def remove(path): diff --git a/samcli/lib/utils/stream_writer.py b/samcli/lib/utils/stream_writer.py index 1fc62fa690..99f72c1036 100644 --- a/samcli/lib/utils/stream_writer.py +++ b/samcli/lib/utils/stream_writer.py @@ -1,10 +1,11 @@ """ This class acts like a wrapper around output streams to provide any flexibility with output we need """ +from typing import TextIO, Union class StreamWriter: - def __init__(self, stream, auto_flush=False): + def __init__(self, stream: TextIO, auto_flush: bool = False): """ Instatiates new StreamWriter to the specified stream @@ -19,19 +20,33 @@ def __init__(self, stream, auto_flush=False): self._auto_flush = auto_flush @property - def stream(self): + def stream(self) -> TextIO: return self._stream - def write(self, output, encode=False): + def write_bytes(self, output: Union[bytes, bytearray]): """ Writes specified text to the underlying stream Parameters ---------- output bytes-like object - Bytes to write + Bytes to write into buffer """ - self._stream.write(output.encode() if encode else output) + self._stream.buffer.write(output) + + if self._auto_flush: + self._stream.flush() + + def write_str(self, output: str): + """ + Writes specified text to the underlying stream + + Parameters + ---------- + output string object + String to write + """ + self._stream.write(output) if self._auto_flush: self._stream.flush() diff --git a/samcli/lib/utils/subprocess_utils.py b/samcli/lib/utils/subprocess_utils.py index e08ec12e49..1937a44eeb 100644 --- a/samcli/lib/utils/subprocess_utils.py +++ b/samcli/lib/utils/subprocess_utils.py @@ -34,7 +34,7 @@ def default_loading_pattern(stream_writer: Optional[StreamWriter] = None, loadin How frequently to generate the pattern """ stream_writer = stream_writer or StreamWriter(sys.stderr) - stream_writer.write(".") + stream_writer.write_str(".") stream_writer.flush() sleep(loading_pattern_rate) @@ -96,7 +96,7 @@ def _print_loading_pattern(): return_code = process.wait() keep_printing = False - stream_writer.write(os.linesep) + stream_writer.write_str(os.linesep) stream_writer.flush() process_stderr = _check_and_convert_stream_to_string(process.stderr) diff --git a/samcli/local/apigw/local_apigw_service.py b/samcli/local/apigw/local_apigw_service.py index f979b2e9a3..b80b1fc2c2 100644 --- a/samcli/local/apigw/local_apigw_service.py +++ b/samcli/local/apigw/local_apigw_service.py @@ -4,7 +4,7 @@ import json import logging from datetime import datetime -from io import BytesIO +from io import StringIO from time import time from typing import Any, Dict, List, Optional @@ -605,7 +605,7 @@ def _invoke_lambda_function(self, lambda_function_name: str, event: dict) -> str str A string containing the output from the Lambda function """ - with BytesIO() as stdout: + with StringIO() as stdout: event_str = json.dumps(event, sort_keys=True) stdout_writer = StreamWriter(stdout, auto_flush=True) diff --git a/samcli/local/docker/container.py b/samcli/local/docker/container.py index fc2a190b53..d4c7c93fef 100644 --- a/samcli/local/docker/container.py +++ b/samcli/local/docker/container.py @@ -1,6 +1,8 @@ """ Representation of a generic Docker container """ +import io +import json import logging import os import pathlib @@ -9,7 +11,7 @@ import tempfile import threading import time -from typing import Optional +from typing import Iterator, Optional, Tuple, Union import docker import requests @@ -17,6 +19,7 @@ from samcli.lib.constants import DOCKER_MIN_API_VERSION from samcli.lib.utils.retry import retry +from samcli.lib.utils.stream_writer import StreamWriter from samcli.lib.utils.tar import extract_tarfile from samcli.local.docker.effective_user import ROOT_USER_ID, EffectiveUser from samcli.local.docker.exceptions import ContainerNotStartableException, PortAlreadyInUse @@ -318,7 +321,7 @@ def start(self, input_data=None): raise ex @retry(exc=requests.exceptions.RequestException, exc_raise=ContainerResponseException) - def wait_for_http_response(self, name, event, stdout): + def wait_for_http_response(self, name, event, stdout) -> str: # TODO(sriram-mv): `aws-lambda-rie` is in a mode where the function_name is always "function" # NOTE(sriram-mv): There is a connection timeout set on the http call to `aws-lambda-rie`, however there is not # a read time out for the response received from the server. @@ -328,7 +331,7 @@ def wait_for_http_response(self, name, event, stdout): data=event.encode("utf-8"), timeout=(self.RAPID_CONNECTION_TIMEOUT, None), ) - stdout.write(resp.content) + return json.dumps(json.loads(resp.content), ensure_ascii=False) def wait_for_result(self, full_path, event, stdout, stderr, start_timer=None): # NOTE(sriram-mv): Let logging happen in its own thread, so that a http request can be sent. @@ -348,11 +351,21 @@ def wait_for_result(self, full_path, event, stdout, stderr, start_timer=None): # start the timer for function timeout right before executing the function, as waiting for the socket # can take some time timer = start_timer() if start_timer else None - self.wait_for_http_response(full_path, event, stdout) + response = self.wait_for_http_response(full_path, event, stdout) if timer: timer.cancel() - def wait_for_logs(self, stdout=None, stderr=None): + # NOTE(jfuss): Adding a sleep after we get a response from the contianer but before we + # we write the response to ensure the last thing written to stdout is the container response + time.sleep(1) + stdout.write_str(response) + stdout.flush() + + def wait_for_logs( + self, + stdout: Optional[Union[StreamWriter, io.BytesIO, io.TextIOWrapper]] = None, + stderr: Optional[Union[StreamWriter, io.BytesIO, io.TextIOWrapper]] = None, + ): # Return instantly if we don't have to fetch any logs if not stdout and not stderr: return @@ -364,7 +377,6 @@ def wait_for_logs(self, stdout=None, stderr=None): # Fetch both stdout and stderr streams from Docker as a single iterator. logs_itr = real_container.attach(stream=True, logs=True, demux=True) - self._write_container_output(logs_itr, stdout=stdout, stderr=stderr) def _wait_for_socket_connection(self) -> None: @@ -415,7 +427,11 @@ def copy(self, from_container_path, to_host_path) -> None: extract_tarfile(file_obj=fp, unpack_dir=to_host_path) @staticmethod - def _write_container_output(output_itr, stdout=None, stderr=None): + def _write_container_output( + output_itr: Iterator[Tuple[bytes, bytes]], + stdout: Optional[Union[StreamWriter, io.BytesIO, io.TextIOWrapper]] = None, + stderr: Optional[Union[StreamWriter, io.BytesIO, io.TextIOWrapper]] = None, + ): """ Based on the data returned from the Container output, via the iterator, write it to the appropriate streams @@ -434,13 +450,26 @@ def _write_container_output(output_itr, stdout=None, stderr=None): # Iterator returns a tuple of (stdout, stderr) for stdout_data, stderr_data in output_itr: if stdout_data and stdout: - stdout.write(stdout_data) + Container._handle_data_writing(stdout, stdout_data) if stderr_data and stderr: - stderr.write(stderr_data) + Container._handle_data_writing(stderr, stderr_data) + except Exception as ex: LOG.debug("Failed to get the logs from the container", exc_info=ex) + @staticmethod + def _handle_data_writing(output_stream: Union[StreamWriter, io.BytesIO, io.TextIOWrapper], output_data: bytes): + if isinstance(output_stream, StreamWriter): + output_stream.write_bytes(output_data) + output_stream.flush() + + if isinstance(output_stream, io.BytesIO): + output_stream.write(output_data) + + if isinstance(output_stream, io.TextIOWrapper): + output_stream.buffer.write(output_data) + @property def network_id(self): """ diff --git a/samcli/local/docker/lambda_image.py b/samcli/local/docker/lambda_image.py index 923b740edc..72ad813de9 100644 --- a/samcli/local/docker/lambda_image.py +++ b/samcli/local/docker/lambda_image.py @@ -3,6 +3,7 @@ """ import hashlib import logging +import os import platform import re import sys @@ -227,7 +228,7 @@ def build(self, runtime, packagetype, image, layers, architecture, stream=None, or not runtime ): stream_writer = stream or StreamWriter(sys.stderr) - stream_writer.write("Building image...") + stream_writer.write_str("Building image...") stream_writer.flush() self._build_image( image if image else base_image, rapid_image, downloaded_layers, architecture, stream=stream_writer @@ -338,15 +339,15 @@ def set_item_permission(tar_info): platform=get_docker_platform(architecture), ) for log in resp_stream: - stream_writer.write(".") + stream_writer.write_str(".") stream_writer.flush() if "error" in log: - stream_writer.write("\n") + stream_writer.write_str(os.linesep) LOG.exception("Failed to build Docker Image") raise ImageBuildException("Error building docker image: {}".format(log["error"])) - stream_writer.write("\n") + stream_writer.write_str(os.linesep) except (docker.errors.BuildError, docker.errors.APIError) as ex: - stream_writer.write("\n") + stream_writer.write_str(os.linesep) LOG.exception("Failed to build Docker Image") raise ImageBuildException("Building Image failed.") from ex finally: diff --git a/samcli/local/docker/manager.py b/samcli/local/docker/manager.py index a035003bb0..6975828cd1 100644 --- a/samcli/local/docker/manager.py +++ b/samcli/local/docker/manager.py @@ -168,16 +168,16 @@ def pull_image(self, image_name, tag=None, stream=None): raise DockerImagePullFailedException(str(ex)) from ex # io streams, especially StringIO, work only with unicode strings - stream_writer.write("\nFetching {}:{} Docker container image...".format(image_name, tag)) + stream_writer.write_str("\nFetching {}:{} Docker container image...".format(image_name, tag)) # Each line contains information on progress of the pull. Each line is a JSON string for _ in result_itr: # For every line, print a dot to show progress - stream_writer.write(".") + stream_writer.write_str(".") stream_writer.flush() # We are done. Go to the next line - stream_writer.write("\n") + stream_writer.write_str("\n") def has_image(self, image_name): """ diff --git a/samcli/local/lambda_service/local_lambda_invoke_service.py b/samcli/local/lambda_service/local_lambda_invoke_service.py index c6d7506fb2..546066449c 100644 --- a/samcli/local/lambda_service/local_lambda_invoke_service.py +++ b/samcli/local/lambda_service/local_lambda_invoke_service.py @@ -162,7 +162,7 @@ def _invoke_request_handler(self, function_name): request_data = request_data.decode("utf-8") - stdout_stream = io.BytesIO() + stdout_stream = io.StringIO() stdout_stream_writer = StreamWriter(stdout_stream, auto_flush=True) try: diff --git a/samcli/local/services/base_local_service.py b/samcli/local/services/base_local_service.py index fcb7cd95ae..671d48888c 100644 --- a/samcli/local/services/base_local_service.py +++ b/samcli/local/services/base_local_service.py @@ -82,7 +82,7 @@ def service_response(body, headers, status_code): class LambdaOutputParser: @staticmethod - def get_lambda_output(stdout_stream: io.BytesIO) -> Tuple[str, bool]: + def get_lambda_output(stdout_stream: io.StringIO) -> Tuple[str, bool]: """ This method will extract read the given stream and return the response from Lambda function separated out from any log statements it might have outputted. Logs end up in the stdout stream if the Lambda function @@ -100,7 +100,7 @@ def get_lambda_output(stdout_stream: io.BytesIO) -> Tuple[str, bool]: bool If the response is an error/exception from the container """ - lambda_response = stdout_stream.getvalue().decode("utf-8") + lambda_response = stdout_stream.getvalue() # When the Lambda Function returns an Error/Exception, the output is added to the stdout of the container. From # our perspective, the container returned some value, which is not always true. Since the output is the only diff --git a/tests/integration/local/invoke/test_integrations_cli.py b/tests/integration/local/invoke/test_integrations_cli.py index 3604fc4010..70711459d6 100644 --- a/tests/integration/local/invoke/test_integrations_cli.py +++ b/tests/integration/local/invoke/test_integrations_cli.py @@ -291,6 +291,27 @@ def test_invoke_returns_expected_result_when_no_event_given(self): self.assertEqual(process.returncode, 0) self.assertEqual("{}", process_stdout.decode("utf-8")) + @pytest.mark.flaky(reruns=3) + def test_invoke_returns_utf8(self): + command_list = InvokeIntegBase.get_command_list( + "EchoEventFunction", template_path=self.template_path, event_path=self.event_utf8_path + ) + + process = Popen(command_list, stdout=PIPE) + try: + stdout, _ = process.communicate(timeout=TIMEOUT) + except TimeoutExpired: + process.kill() + raise + + process_stdout = stdout.strip() + + with open(self.event_utf8_path) as f: + expected_output = json.dumps(json.load(f), ensure_ascii=False) + + self.assertEqual(process.returncode, 0) + self.assertEqual(expected_output, process_stdout.decode("utf-8")) + @pytest.mark.flaky(reruns=3) def test_invoke_with_env_using_parameters(self): command_list = InvokeIntegBase.get_command_list( diff --git a/tests/unit/commands/local/cli_common/test_invoke_context.py b/tests/unit/commands/local/cli_common/test_invoke_context.py index 3cab08c82a..b89d5b6115 100644 --- a/tests/unit/commands/local/cli_common/test_invoke_context.py +++ b/tests/unit/commands/local/cli_common/test_invoke_context.py @@ -1106,7 +1106,7 @@ def test_must_open_file_for_writing(self): with patch("samcli.commands.local.cli_common.invoke_context.open", m): InvokeContext._setup_log_file(filename) - m.assert_called_with(filename, "wb") + m.assert_called_with(filename, "w", encoding="utf8") class TestInvokeContext_get_debug_context(TestCase): diff --git a/tests/unit/lib/utils/test_osutils.py b/tests/unit/lib/utils/test_osutils.py index bf4794f2c4..6f7a6cf4df 100644 --- a/tests/unit/lib/utils/test_osutils.py +++ b/tests/unit/lib/utils/test_osutils.py @@ -34,9 +34,7 @@ def test_raises_on_cleanup_failure(self, rmdir_mock): @patch("os.rmdir") def test_handles_ignore_error_case(self, rmdir_mock): rmdir_mock.side_effect = OSError("fail") - dir_name = None with osutils.mkdir_temp(ignore_errors=True) as tempdir: - dir_name = tempdir self.assertTrue(os.path.exists(tempdir)) @@ -44,9 +42,6 @@ class Test_stderr(TestCase): def test_must_return_sys_stderr(self): expected_stderr = sys.stderr - if sys.version_info.major > 2: - expected_stderr = sys.stderr.buffer - self.assertEqual(expected_stderr, osutils.stderr()) @@ -54,9 +49,6 @@ class Test_stdout(TestCase): def test_must_return_sys_stdout(self): expected_stdout = sys.stdout - if sys.version_info.major > 2: - expected_stdout = sys.stdout.buffer - self.assertEqual(expected_stdout, osutils.stdout()) diff --git a/tests/unit/lib/utils/test_stream_writer.py b/tests/unit/lib/utils/test_stream_writer.py index cb48955850..a6875b59da 100644 --- a/tests/unit/lib/utils/test_stream_writer.py +++ b/tests/unit/lib/utils/test_stream_writer.py @@ -1,6 +1,7 @@ """ Tests for StreamWriter """ +import io from unittest import TestCase @@ -11,13 +12,13 @@ class TestStreamWriter(TestCase): def test_must_write_to_stream(self): - buffer = "something" + buffer = b"something" stream_mock = Mock() writer = StreamWriter(stream_mock) - writer.write(buffer) + writer.write_bytes(buffer) - stream_mock.write.assert_called_once_with(buffer) + stream_mock.buffer.write.assert_called_once_with(buffer) def test_must_flush_underlying_stream(self): stream_mock = Mock() @@ -31,7 +32,7 @@ def test_auto_flush_must_be_off_by_default(self): stream_mock = Mock() writer = StreamWriter(stream_mock) - writer.write("something") + writer.write_str("something") stream_mock.flush.assert_not_called() @@ -46,6 +47,6 @@ def test_when_auto_flush_on_flush_after_each_write(self): writer = StreamWriter(stream_mock, True) for line in lines: - writer.write(line) + writer.write_str(line) flush_mock.assert_called_once_with() flush_mock.reset_mock() diff --git a/tests/unit/lib/utils/test_subprocess_utils.py b/tests/unit/lib/utils/test_subprocess_utils.py index 969f06085b..a9d39afdd2 100644 --- a/tests/unit/lib/utils/test_subprocess_utils.py +++ b/tests/unit/lib/utils/test_subprocess_utils.py @@ -11,6 +11,7 @@ from parameterized import parameterized from unittest.mock import patch, Mock, call, ANY +from samcli.lib.utils.stream_writer import StreamWriter from samcli.lib.utils.subprocess_utils import ( default_loading_pattern, invoke_subprocess_with_loading_pattern, @@ -64,7 +65,7 @@ def test_loader_stream_uses_passed_in_stdout( @patch("samcli.lib.utils.subprocess_utils.Popen") def test_loader_raises_exception_non_zero_exit_code(self, patched_Popen): standard_error = "an error has occurred" - mock_stream_writer = Mock() + mock_stream_writer = Mock(spec=StreamWriter) mock_process = Mock() mock_process.returncode = 1 mock_process.stdout = None @@ -74,7 +75,7 @@ def test_loader_raises_exception_non_zero_exit_code(self, patched_Popen): with self.assertRaises(LoadingPatternError) as ex: invoke_subprocess_with_loading_pattern({"args": ["ls"]}, mock_pattern, mock_stream_writer) self.assertIn(standard_error, ex.exception.message) - mock_stream_writer.write.assert_called_once_with(os.linesep) + mock_stream_writer.write_str.assert_called_once_with(os.linesep) mock_stream_writer.flush.assert_called_once_with() @patch("samcli.lib.utils.subprocess_utils.Popen") @@ -95,19 +96,19 @@ def test_loader_raises_exception_bad_process(self, patched_Popen): @patch("samcli.lib.utils.subprocess_utils.StreamWriter") def test_default_pattern_default_stream_writer(self, patched_stream_writer): - stream_writer_mock = Mock() + stream_writer_mock = Mock(spec=StreamWriter) patched_stream_writer.return_value = stream_writer_mock default_loading_pattern(loading_pattern_rate=0.01) patched_stream_writer.assert_called_once_with(sys.stderr) - stream_writer_mock.write.assert_called_once_with(".") + stream_writer_mock.write_str.assert_called_once_with(".") stream_writer_mock.flush.assert_called_once_with() @patch("samcli.lib.utils.subprocess_utils.StreamWriter") def test_default_pattern(self, patched_stream_writer): - stream_writer_mock = Mock() + stream_writer_mock = Mock(spec=StreamWriter) default_loading_pattern(stream_writer_mock, 0.01) patched_stream_writer.assert_not_called() - stream_writer_mock.write.assert_called_once_with(".") + stream_writer_mock.write_str.assert_called_once_with(".") stream_writer_mock.flush.assert_called_once_with() @parameterized.expand([("hello".encode("utf-8"), "hello"), ("hello", "hello")]) diff --git a/tests/unit/local/docker/test_container.py b/tests/unit/local/docker/test_container.py index b7b7311563..064bb845cb 100644 --- a/tests/unit/local/docker/test_container.py +++ b/tests/unit/local/docker/test_container.py @@ -9,6 +9,7 @@ from requests import RequestException from samcli.lib.utils.packagetype import IMAGE +from samcli.lib.utils.stream_writer import StreamWriter from samcli.local.docker.container import ( Container, ContainerResponseException, @@ -721,17 +722,17 @@ def test_wait_for_result_waits_for_socket_before_post_request(self, patched_time self.assertEqual(mock_requests.post.call_count, 0) def test_write_container_output_successful(self): - stdout_mock = Mock() - stderr_mock = Mock() + stdout_mock = Mock(spec=StreamWriter) + stderr_mock = Mock(spec=StreamWriter) def _output_iterator(): - yield "Hello", None - yield None, "World" + yield b"Hello", None + yield None, b"World" raise ValueError("The pipe has been ended.") Container._write_container_output(_output_iterator(), stdout_mock, stderr_mock) - stdout_mock.assert_has_calls([call.write("Hello")]) - stderr_mock.assert_has_calls([call.write("World")]) + stdout_mock.assert_has_calls([call.write_bytes(b"Hello")]) + stderr_mock.assert_has_calls([call.write_bytes(b"World")]) class TestContainer_wait_for_logs(TestCase): @@ -785,33 +786,33 @@ class TestContainer_write_container_output(TestCase): def setUp(self): self.output_itr = [(b"stdout1", None), (None, b"stderr1"), (b"stdout2", b"stderr2"), (None, None)] - self.stdout_mock = Mock() - self.stderr_mock = Mock() + self.stdout_mock = Mock(spec=StreamWriter) + self.stderr_mock = Mock(spec=StreamWriter) def test_must_write_stdout_and_stderr_data(self): # All the invalid frames must be ignored Container._write_container_output(self.output_itr, stdout=self.stdout_mock, stderr=self.stderr_mock) - self.stdout_mock.write.assert_has_calls([call(b"stdout1"), call(b"stdout2")]) + self.stdout_mock.write_bytes.assert_has_calls([call(b"stdout1"), call(b"stdout2")]) - self.stderr_mock.write.assert_has_calls([call(b"stderr1"), call(b"stderr2")]) + self.stderr_mock.write_bytes.assert_has_calls([call(b"stderr1"), call(b"stderr2")]) def test_must_write_only_stderr(self): # All the invalid frames must be ignored Container._write_container_output(self.output_itr, stdout=None, stderr=self.stderr_mock) - self.stdout_mock.write.assert_not_called() + self.stdout_mock.write_bytes.assert_not_called() - self.stderr_mock.write.assert_has_calls([call(b"stderr1"), call(b"stderr2")]) + self.stderr_mock.write_bytes.assert_has_calls([call(b"stderr1"), call(b"stderr2")]) def test_must_write_only_stdout(self): Container._write_container_output(self.output_itr, stdout=self.stdout_mock, stderr=None) - self.stdout_mock.write.assert_has_calls([call(b"stdout1"), call(b"stdout2")]) + self.stdout_mock.write_bytes.assert_has_calls([call(b"stdout1"), call(b"stdout2")]) - self.stderr_mock.write.assert_not_called() # stderr must never be called + self.stderr_mock.write_bytes.assert_not_called() # stderr must never be called class TestContainer_wait_for_socket_connection(TestCase): diff --git a/tests/unit/local/docker/test_lambda_image.py b/tests/unit/local/docker/test_lambda_image.py index 1e8f936d98..03b57be804 100644 --- a/tests/unit/local/docker/test_lambda_image.py +++ b/tests/unit/local/docker/test_lambda_image.py @@ -1,4 +1,3 @@ -import io import tempfile from unittest import TestCase @@ -271,7 +270,7 @@ def test_force_building_image_that_doesnt_already_exists( docker_client_mock.images.get.side_effect = ImageNotFound("image not found") docker_client_mock.images.list.return_value = [] - stream = io.StringIO() + stream = Mock() lambda_image = LambdaImage(layer_downloader_mock, False, True, docker_client=docker_client_mock) actual_image_id = lambda_image.build( @@ -311,7 +310,7 @@ def test_force_building_image_on_daemon_404( docker_client_mock.images.get.side_effect = NotFound("image not found") docker_client_mock.images.list.return_value = [] - stream = io.StringIO() + stream = Mock() lambda_image = LambdaImage(layer_downloader_mock, False, True, docker_client=docker_client_mock) actual_image_id = lambda_image.build( @@ -351,7 +350,7 @@ def test_docker_distribution_api_error_on_daemon_api_error( docker_client_mock.images.get.side_effect = APIError("error from docker daemon") docker_client_mock.images.list.return_value = [] - stream = io.StringIO() + stream = Mock() lambda_image = LambdaImage(layer_downloader_mock, False, True, docker_client=docker_client_mock) with self.assertRaises(DockerDistributionAPIError): @@ -377,7 +376,7 @@ def test_not_force_building_image_that_doesnt_already_exists( docker_client_mock.images.get.side_effect = ImageNotFound("image not found") docker_client_mock.images.list.return_value = [] - stream = io.StringIO() + stream = Mock() lambda_image = LambdaImage(layer_downloader_mock, False, False, docker_client=docker_client_mock) actual_image_id = lambda_image.build( diff --git a/tests/unit/local/docker/test_manager.py b/tests/unit/local/docker/test_manager.py index ada69903ea..4cb42bbd02 100644 --- a/tests/unit/local/docker/test_manager.py +++ b/tests/unit/local/docker/test_manager.py @@ -1,8 +1,6 @@ """ Tests container manager """ - -import io import importlib from unittest import TestCase from unittest.mock import Mock, patch, MagicMock, ANY, call @@ -218,17 +216,29 @@ def setUp(self): self.manager = ContainerManager(docker_client=self.mock_docker_client) def test_must_pull_and_print_progress_dots(self): - stream = io.StringIO() + stream = Mock() pull_result = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0] self.mock_docker_client.api.pull.return_value = pull_result - expected_stream_output = "\nFetching {}:latest Docker container image...{}\n".format( - self.image_name, "." * len(pull_result) # Progress bar will print one dot per response from pull API - ) + expected_stream_calls = [ + call(f"\nFetching {self.image_name}:latest Docker container image..."), + call("."), + call("."), + call("."), + call("."), + call("."), + call("."), + call("."), + call("."), + call("."), + call("."), + call("\n"), + ] self.manager.pull_image(self.image_name, stream=stream) self.mock_docker_client.api.pull.assert_called_with(self.image_name, stream=True, decode=True, tag="latest") - self.assertEqual(stream.getvalue(), expected_stream_output) + + stream.write_str.assert_has_calls(expected_stream_calls) def test_must_raise_if_image_not_found(self): msg = "some error" diff --git a/tests/unit/local/services/test_base_local_service.py b/tests/unit/local/services/test_base_local_service.py index fec13e25c9..34bc44c193 100644 --- a/tests/unit/local/services/test_base_local_service.py +++ b/tests/unit/local/services/test_base_local_service.py @@ -66,17 +66,17 @@ def test_create_returns_not_implemented(self): class TestLambdaOutputParser(TestCase): @parameterized.expand( [ - param("with mixed data and json response", b'data\n{"a": "b"}', 'data\n{"a": "b"}'), - param("with response as string", b"response", "response"), - param("with json response only", b'{"a": "b"}', '{"a": "b"}'), - param("with one new line and json", b'\n{"a": "b"}', '\n{"a": "b"}'), - param("with response only as string", b"this is the response line", "this is the response line"), - param("with whitespaces", b'data\n{"a": "b"} \n\n\n', 'data\n{"a": "b"} \n\n\n'), - param("with empty data", b"", ""), - param("with just new lines", b"\n\n", "\n\n"), + param("with mixed data and json response", 'data\n{"a": "b"}', 'data\n{"a": "b"}'), + param("with response as string", "response", "response"), + param("with json response only", '{"a": "b"}', '{"a": "b"}'), + param("with one new line and json", '\n{"a": "b"}', '\n{"a": "b"}'), + param("with response only as string", "this is the response line", "this is the response line"), + param("with whitespaces", 'data\n{"a": "b"} \n\n\n', 'data\n{"a": "b"} \n\n\n'), + param("with empty data", "", ""), + param("with just new lines", "\n\n", "\n\n"), param( "with whitespaces", - b"\n \n \n", + "\n \n \n", "\n \n \n", ), ] From 27eb2e1e35da226236a2ea2eba2c8d6c8dbb31e1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 2 Aug 2023 13:42:30 +0300 Subject: [PATCH 05/13] chore(deps): bump cryptography from 41.0.2 to 41.0.3 in /requirements (#5675) Bumps [cryptography](https://github.com/pyca/cryptography) from 41.0.2 to 41.0.3. - [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pyca/cryptography/compare/41.0.2...41.0.3) --- updated-dependencies: - dependency-name: cryptography dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements/reproducible-linux.txt | 48 ++++++++++++++--------------- requirements/reproducible-mac.txt | 48 ++++++++++++++--------------- 2 files changed, 48 insertions(+), 48 deletions(-) diff --git a/requirements/reproducible-linux.txt b/requirements/reproducible-linux.txt index 354b363df0..821e88a926 100644 --- a/requirements/reproducible-linux.txt +++ b/requirements/reproducible-linux.txt @@ -219,30 +219,30 @@ cookiecutter==2.1.1 \ --hash=sha256:9f3ab027cec4f70916e28f03470bdb41e637a3ad354b4d65c765d93aad160022 \ --hash=sha256:f3982be8d9c53dac1261864013fdec7f83afd2e42ede6f6dd069c5e149c540d5 # via aws-sam-cli (setup.py) -cryptography==41.0.2 \ - --hash=sha256:01f1d9e537f9a15b037d5d9ee442b8c22e3ae11ce65ea1f3316a41c78756b711 \ - --hash=sha256:079347de771f9282fbfe0e0236c716686950c19dee1b76240ab09ce1624d76d7 \ - --hash=sha256:182be4171f9332b6741ee818ec27daff9fb00349f706629f5cbf417bd50e66fd \ - --hash=sha256:192255f539d7a89f2102d07d7375b1e0a81f7478925b3bc2e0549ebf739dae0e \ - --hash=sha256:2a034bf7d9ca894720f2ec1d8b7b5832d7e363571828037f9e0c4f18c1b58a58 \ - --hash=sha256:342f3767e25876751e14f8459ad85e77e660537ca0a066e10e75df9c9e9099f0 \ - --hash=sha256:439c3cc4c0d42fa999b83ded80a9a1fb54d53c58d6e59234cfe97f241e6c781d \ - --hash=sha256:49c3222bb8f8e800aead2e376cbef687bc9e3cb9b58b29a261210456a7783d83 \ - --hash=sha256:674b669d5daa64206c38e507808aae49904c988fa0a71c935e7006a3e1e83831 \ - --hash=sha256:7a9a3bced53b7f09da251685224d6a260c3cb291768f54954e28f03ef14e3766 \ - --hash=sha256:7af244b012711a26196450d34f483357e42aeddb04128885d95a69bd8b14b69b \ - --hash=sha256:7d230bf856164de164ecb615ccc14c7fc6de6906ddd5b491f3af90d3514c925c \ - --hash=sha256:84609ade00a6ec59a89729e87a503c6e36af98ddcd566d5f3be52e29ba993182 \ - --hash=sha256:9a6673c1828db6270b76b22cc696f40cde9043eb90373da5c2f8f2158957f42f \ - --hash=sha256:9b6d717393dbae53d4e52684ef4f022444fc1cce3c48c38cb74fca29e1f08eaa \ - --hash=sha256:9c3fe6534d59d071ee82081ca3d71eed3210f76ebd0361798c74abc2bcf347d4 \ - --hash=sha256:a719399b99377b218dac6cf547b6ec54e6ef20207b6165126a280b0ce97e0d2a \ - --hash=sha256:b332cba64d99a70c1e0836902720887fb4529ea49ea7f5462cf6640e095e11d2 \ - --hash=sha256:d124682c7a23c9764e54ca9ab5b308b14b18eba02722b8659fb238546de83a76 \ - --hash=sha256:d73f419a56d74fef257955f51b18d046f3506270a5fd2ac5febbfa259d6c0fa5 \ - --hash=sha256:f0dc40e6f7aa37af01aba07277d3d64d5a03dc66d682097541ec4da03cc140ee \ - --hash=sha256:f14ad275364c8b4e525d018f6716537ae7b6d369c094805cae45300847e0894f \ - --hash=sha256:f772610fe364372de33d76edcd313636a25684edb94cee53fd790195f5989d14 +cryptography==41.0.3 \ + --hash=sha256:0d09fb5356f975974dbcb595ad2d178305e5050656affb7890a1583f5e02a306 \ + --hash=sha256:23c2d778cf829f7d0ae180600b17e9fceea3c2ef8b31a99e3c694cbbf3a24b84 \ + --hash=sha256:3fb248989b6363906827284cd20cca63bb1a757e0a2864d4c1682a985e3dca47 \ + --hash=sha256:41d7aa7cdfded09b3d73a47f429c298e80796c8e825ddfadc84c8a7f12df212d \ + --hash=sha256:42cb413e01a5d36da9929baa9d70ca90d90b969269e5a12d39c1e0d475010116 \ + --hash=sha256:4c2f0d35703d61002a2bbdcf15548ebb701cfdd83cdc12471d2bae80878a4207 \ + --hash=sha256:4fd871184321100fb400d759ad0cddddf284c4b696568204d281c902fc7b0d81 \ + --hash=sha256:5259cb659aa43005eb55a0e4ff2c825ca111a0da1814202c64d28a985d33b087 \ + --hash=sha256:57a51b89f954f216a81c9d057bf1a24e2f36e764a1ca9a501a6964eb4a6800dd \ + --hash=sha256:652627a055cb52a84f8c448185922241dd5217443ca194d5739b44612c5e6507 \ + --hash=sha256:67e120e9a577c64fe1f611e53b30b3e69744e5910ff3b6e97e935aeb96005858 \ + --hash=sha256:6af1c6387c531cd364b72c28daa29232162010d952ceb7e5ca8e2827526aceae \ + --hash=sha256:6d192741113ef5e30d89dcb5b956ef4e1578f304708701b8b73d38e3e1461f34 \ + --hash=sha256:7efe8041897fe7a50863e51b77789b657a133c75c3b094e51b5e4b5cec7bf906 \ + --hash=sha256:84537453d57f55a50a5b6835622ee405816999a7113267739a1b4581f83535bd \ + --hash=sha256:8f09daa483aedea50d249ef98ed500569841d6498aa9c9f4b0531b9964658922 \ + --hash=sha256:95dd7f261bb76948b52a5330ba5202b91a26fbac13ad0e9fc8a3ac04752058c7 \ + --hash=sha256:a74fbcdb2a0d46fe00504f571a2a540532f4c188e6ccf26f1f178480117b33c4 \ + --hash=sha256:a983e441a00a9d57a4d7c91b3116a37ae602907a7618b882c8013b5762e80574 \ + --hash=sha256:ab8de0d091acbf778f74286f4989cf3d1528336af1b59f3e5d2ebca8b5fe49e1 \ + --hash=sha256:aeb57c421b34af8f9fe830e1955bf493a86a7996cc1338fe41b30047d16e962c \ + --hash=sha256:ce785cf81a7bdade534297ef9e490ddff800d956625020ab2ec2780a556c313e \ + --hash=sha256:d0d651aa754ef58d75cec6edfbd21259d93810b73f6ec246436a21b7841908de # via pyopenssl dateparser==1.1.8 \ --hash=sha256:070b29b5bbf4b1ec2cd51c96ea040dc68a614de703910a91ad1abba18f9f379f \ diff --git a/requirements/reproducible-mac.txt b/requirements/reproducible-mac.txt index 08062fd84e..718796b407 100644 --- a/requirements/reproducible-mac.txt +++ b/requirements/reproducible-mac.txt @@ -237,30 +237,30 @@ cookiecutter==2.1.1 \ --hash=sha256:9f3ab027cec4f70916e28f03470bdb41e637a3ad354b4d65c765d93aad160022 \ --hash=sha256:f3982be8d9c53dac1261864013fdec7f83afd2e42ede6f6dd069c5e149c540d5 # via aws-sam-cli (setup.py) -cryptography==41.0.2 \ - --hash=sha256:01f1d9e537f9a15b037d5d9ee442b8c22e3ae11ce65ea1f3316a41c78756b711 \ - --hash=sha256:079347de771f9282fbfe0e0236c716686950c19dee1b76240ab09ce1624d76d7 \ - --hash=sha256:182be4171f9332b6741ee818ec27daff9fb00349f706629f5cbf417bd50e66fd \ - --hash=sha256:192255f539d7a89f2102d07d7375b1e0a81f7478925b3bc2e0549ebf739dae0e \ - --hash=sha256:2a034bf7d9ca894720f2ec1d8b7b5832d7e363571828037f9e0c4f18c1b58a58 \ - --hash=sha256:342f3767e25876751e14f8459ad85e77e660537ca0a066e10e75df9c9e9099f0 \ - --hash=sha256:439c3cc4c0d42fa999b83ded80a9a1fb54d53c58d6e59234cfe97f241e6c781d \ - --hash=sha256:49c3222bb8f8e800aead2e376cbef687bc9e3cb9b58b29a261210456a7783d83 \ - --hash=sha256:674b669d5daa64206c38e507808aae49904c988fa0a71c935e7006a3e1e83831 \ - --hash=sha256:7a9a3bced53b7f09da251685224d6a260c3cb291768f54954e28f03ef14e3766 \ - --hash=sha256:7af244b012711a26196450d34f483357e42aeddb04128885d95a69bd8b14b69b \ - --hash=sha256:7d230bf856164de164ecb615ccc14c7fc6de6906ddd5b491f3af90d3514c925c \ - --hash=sha256:84609ade00a6ec59a89729e87a503c6e36af98ddcd566d5f3be52e29ba993182 \ - --hash=sha256:9a6673c1828db6270b76b22cc696f40cde9043eb90373da5c2f8f2158957f42f \ - --hash=sha256:9b6d717393dbae53d4e52684ef4f022444fc1cce3c48c38cb74fca29e1f08eaa \ - --hash=sha256:9c3fe6534d59d071ee82081ca3d71eed3210f76ebd0361798c74abc2bcf347d4 \ - --hash=sha256:a719399b99377b218dac6cf547b6ec54e6ef20207b6165126a280b0ce97e0d2a \ - --hash=sha256:b332cba64d99a70c1e0836902720887fb4529ea49ea7f5462cf6640e095e11d2 \ - --hash=sha256:d124682c7a23c9764e54ca9ab5b308b14b18eba02722b8659fb238546de83a76 \ - --hash=sha256:d73f419a56d74fef257955f51b18d046f3506270a5fd2ac5febbfa259d6c0fa5 \ - --hash=sha256:f0dc40e6f7aa37af01aba07277d3d64d5a03dc66d682097541ec4da03cc140ee \ - --hash=sha256:f14ad275364c8b4e525d018f6716537ae7b6d369c094805cae45300847e0894f \ - --hash=sha256:f772610fe364372de33d76edcd313636a25684edb94cee53fd790195f5989d14 +cryptography==41.0.3 \ + --hash=sha256:0d09fb5356f975974dbcb595ad2d178305e5050656affb7890a1583f5e02a306 \ + --hash=sha256:23c2d778cf829f7d0ae180600b17e9fceea3c2ef8b31a99e3c694cbbf3a24b84 \ + --hash=sha256:3fb248989b6363906827284cd20cca63bb1a757e0a2864d4c1682a985e3dca47 \ + --hash=sha256:41d7aa7cdfded09b3d73a47f429c298e80796c8e825ddfadc84c8a7f12df212d \ + --hash=sha256:42cb413e01a5d36da9929baa9d70ca90d90b969269e5a12d39c1e0d475010116 \ + --hash=sha256:4c2f0d35703d61002a2bbdcf15548ebb701cfdd83cdc12471d2bae80878a4207 \ + --hash=sha256:4fd871184321100fb400d759ad0cddddf284c4b696568204d281c902fc7b0d81 \ + --hash=sha256:5259cb659aa43005eb55a0e4ff2c825ca111a0da1814202c64d28a985d33b087 \ + --hash=sha256:57a51b89f954f216a81c9d057bf1a24e2f36e764a1ca9a501a6964eb4a6800dd \ + --hash=sha256:652627a055cb52a84f8c448185922241dd5217443ca194d5739b44612c5e6507 \ + --hash=sha256:67e120e9a577c64fe1f611e53b30b3e69744e5910ff3b6e97e935aeb96005858 \ + --hash=sha256:6af1c6387c531cd364b72c28daa29232162010d952ceb7e5ca8e2827526aceae \ + --hash=sha256:6d192741113ef5e30d89dcb5b956ef4e1578f304708701b8b73d38e3e1461f34 \ + --hash=sha256:7efe8041897fe7a50863e51b77789b657a133c75c3b094e51b5e4b5cec7bf906 \ + --hash=sha256:84537453d57f55a50a5b6835622ee405816999a7113267739a1b4581f83535bd \ + --hash=sha256:8f09daa483aedea50d249ef98ed500569841d6498aa9c9f4b0531b9964658922 \ + --hash=sha256:95dd7f261bb76948b52a5330ba5202b91a26fbac13ad0e9fc8a3ac04752058c7 \ + --hash=sha256:a74fbcdb2a0d46fe00504f571a2a540532f4c188e6ccf26f1f178480117b33c4 \ + --hash=sha256:a983e441a00a9d57a4d7c91b3116a37ae602907a7618b882c8013b5762e80574 \ + --hash=sha256:ab8de0d091acbf778f74286f4989cf3d1528336af1b59f3e5d2ebca8b5fe49e1 \ + --hash=sha256:aeb57c421b34af8f9fe830e1955bf493a86a7996cc1338fe41b30047d16e962c \ + --hash=sha256:ce785cf81a7bdade534297ef9e490ddff800d956625020ab2ec2780a556c313e \ + --hash=sha256:d0d651aa754ef58d75cec6edfbd21259d93810b73f6ec246436a21b7841908de # via pyopenssl dateparser==1.1.8 \ --hash=sha256:070b29b5bbf4b1ec2cd51c96ea040dc68a614de703910a91ad1abba18f9f379f \ From 135da3a1c4facb0117fd5d4ef4aebc81a8a1696d Mon Sep 17 00:00:00 2001 From: Jacob Fuss <32497805+jfuss@users.noreply.github.com> Date: Wed, 2 Aug 2023 13:02:48 -0500 Subject: [PATCH 06/13] fix(test): Force reading file with utf8 in tests for windows (#5679) Co-authored-by: Jacob Fuss --- tests/integration/local/invoke/test_integrations_cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/local/invoke/test_integrations_cli.py b/tests/integration/local/invoke/test_integrations_cli.py index 70711459d6..be015469d0 100644 --- a/tests/integration/local/invoke/test_integrations_cli.py +++ b/tests/integration/local/invoke/test_integrations_cli.py @@ -306,7 +306,7 @@ def test_invoke_returns_utf8(self): process_stdout = stdout.strip() - with open(self.event_utf8_path) as f: + with open(self.event_utf8_path, encoding="utf8") as f: expected_output = json.dumps(json.load(f), ensure_ascii=False) self.assertEqual(process.returncode, 0) From b282cebb2c0cab4056dc8ed43def1515901c0bf6 Mon Sep 17 00:00:00 2001 From: Jacob Fuss <32497805+jfuss@users.noreply.github.com> Date: Wed, 2 Aug 2023 13:02:58 -0500 Subject: [PATCH 07/13] fix(test): Increase max execution time for timeout tests (#5680) Co-authored-by: Jacob Fuss --- tests/integration/local/invoke/test_integrations_cli.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/integration/local/invoke/test_integrations_cli.py b/tests/integration/local/invoke/test_integrations_cli.py index be015469d0..b295d81f6c 100644 --- a/tests/integration/local/invoke/test_integrations_cli.py +++ b/tests/integration/local/invoke/test_integrations_cli.py @@ -160,7 +160,9 @@ def test_invoke_with_timeout_set(self, function_name): # validate the time of the cli (timeout is set to 5s) self.assertGreater(wall_clock_cli_duration, 5) - self.assertLess(wall_clock_cli_duration, 20) + # validate the the duration is roughly under the timeout (with some additional + # time to take in account time for SAM CLI to do work) + self.assertLess(wall_clock_cli_duration, 25) self.assertEqual(process.returncode, 0) self.assertEqual( From 8b6771384e48408af892ac43bac6eca7d4cd7b6e Mon Sep 17 00:00:00 2001 From: Mehmet Nuri Deveci <5735811+mndeveci@users.noreply.github.com> Date: Thu, 3 Aug 2023 20:18:32 +0300 Subject: [PATCH 08/13] chore: auto update reproducible requirements when there is a dependency change (#5677) * chore: add reproducible gha * format * formatting v2 * format v3 * use win make target * update windows job * update win paths * why windows why * remove if stmt for now * test with direct paths * update windows paths again * bring back activate * add dummy win file and push changes * update base.txt for testing * Update reproducibles * run jobs sequentially * print changed flag * check changes again * run git status before moving forward * refresh index before checking any changed files * Update reproducibles * commit or skip * Update reproducibles * rerun build & pyinstaller jobs once update reproducible finishes * add more details to commit message * nuke all reproducibles to trigger the CI * Update reproducibles: update-reproducible-linux-reqs * Update reproducibles: update-reproducible-mac-reqs * Update reproducibles: update-reproducible-win-reqs * change lb version for testing * update permissions and limit only for aws/aws-sam-cli * Update reproducibles: update-reproducible-linux-reqs * Update reproducibles: update-reproducible-mac-reqs * Update reproducibles: update-reproducible-win-reqs * update other jobs as well * run without file filter * Update reproducibles: update-reproducible-linux-reqs * Update reproducibles: update-reproducible-mac-reqs * Update reproducibles: update-reproducible-win-reqs * put the file filter back --------- Co-authored-by: GitHub Action --- .../automated-updates-to-sam-cli.yml | 16 +- .github/workflows/update-reproducibles.yml | 42 + Makefile | 9 + requirements/reproducible-linux.txt | 530 +++++------ requirements/reproducible-mac.txt | 539 +++++------ requirements/reproducible-win.txt | 893 ++++++++++++++++++ 6 files changed, 1481 insertions(+), 548 deletions(-) create mode 100644 .github/workflows/update-reproducibles.yml create mode 100644 requirements/reproducible-win.txt diff --git a/.github/workflows/automated-updates-to-sam-cli.yml b/.github/workflows/automated-updates-to-sam-cli.yml index a42123ea5b..e05fa57675 100644 --- a/.github/workflows/automated-updates-to-sam-cli.yml +++ b/.github/workflows/automated-updates-to-sam-cli.yml @@ -71,12 +71,6 @@ jobs: with: repository: aws/aws-sam-cli path: aws-sam-cli - - - uses: actions/setup-python@v4 # used for make update-reproducible-reqs below - with: - python-version: | - 3.8 - 3.11 - name: Update aws-sam-translator & commit run: | @@ -90,7 +84,7 @@ jobs: SAM_T_PRE_VERSION=$(grep "aws-sam-translator=" requirements/base.txt) echo "SAM-T pre version is $SAM_T_PRE_VERSION" git reset --hard develop - sed -i "s/$SAM_T_PRE_VERSION/aws-sam-translator==$SAM_T_CUR_VERSION/g" requirements/base.txt; make update-reproducible-reqs + sed -i "s/$SAM_T_PRE_VERSION/aws-sam-translator==$SAM_T_CUR_VERSION/g" requirements/base.txt cp -r ../serverless-application-model/tests/translator/input ./tests/functional/commands/validate/lib/models git status git diff --quiet && exit 0 # exit if there is no change @@ -129,12 +123,6 @@ jobs: repository: aws/aws-sam-cli path: aws-sam-cli - - uses: actions/setup-python@v4 # used for make update-reproducible-reqs below - with: - python-version: | - 3.8 - 3.11 - - name: Upgrade aws_lambda_builders & commit run: | git config --global user.email "action@github.com" @@ -147,7 +135,7 @@ jobs: BUILDERS_PRE_VERSION=$(grep "aws_lambda_builders=" requirements/base.txt) echo "Lambda Builders pre version is $BUILDERS_PRE_VERSION" git reset --hard develop - sed -i "s/$BUILDERS_PRE_VERSION/aws_lambda_builders==$BUILDERS_CUR_VERSION/g" requirements/base.txt; make update-reproducible-reqs + sed -i "s/$BUILDERS_PRE_VERSION/aws_lambda_builders==$BUILDERS_CUR_VERSION/g" requirements/base.txt git status git diff --quiet && exit 0 # exit if there is no change echo "is_new_lambda_builders=1" >> $GITHUB_ENV # set env variable for next step run decision diff --git a/.github/workflows/update-reproducibles.yml b/.github/workflows/update-reproducibles.yml new file mode 100644 index 0000000000..8a89137a57 --- /dev/null +++ b/.github/workflows/update-reproducibles.yml @@ -0,0 +1,42 @@ +name: Update reproducible requirements +on: + pull_request: + branches: [develop] + paths: + - requirements/base.txt # run this GHA only if requirements file is changed + +jobs: + update-reqs: + permissions: + pull-requests: write + contents: write + if: github.repository_owner == 'aws' + strategy: + matrix: + include: + - os: ubuntu-latest + python: 3.11 + target: update-reproducible-linux-reqs + - os: macos-latest + python: 3.8 + target: update-reproducible-mac-reqs + - os: windows-latest + python: 3.8 + target: update-reproducible-win-reqs + max-parallel: 1 + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v3 + with: + ref: ${{ github.head_ref }} + - uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python }} + - run: make ${{ matrix.target }} + - name: Push changes + run: | + git config --global user.email "action@github.com" + git config --global user.name "GitHub Action" + git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }} + git commit -am "Update reproducibles: ${{ matrix.target }}" || echo "nothing to commit" + git push \ No newline at end of file diff --git a/Makefile b/Makefile index dd80957cae..c65a27de88 100644 --- a/Makefile +++ b/Makefile @@ -70,4 +70,13 @@ update-reproducible-mac-reqs: venv-update-reproducible-mac/bin/pip install -r requirements/base.txt venv-update-reproducible-mac/bin/pip-compile --generate-hashes --allow-unsafe -o requirements/reproducible-mac.txt +# note that this should be run on a windows environment with python3.8 as default interpreter +update-reproducible-win-reqs: + python -m venv venv-update-reproducible-win + .\venv-update-reproducible-win\Scripts\activate + pip install --upgrade pip-tools pip + pip install -r requirements\base.txt + pip-compile --generate-hashes --allow-unsafe -o requirements\reproducible-win.txt + + update-reproducible-reqs: update-reproducible-linux-reqs update-reproducible-mac-reqs \ No newline at end of file diff --git a/requirements/reproducible-linux.txt b/requirements/reproducible-linux.txt index 821e88a926..208c24b2cc 100644 --- a/requirements/reproducible-linux.txt +++ b/requirements/reproducible-linux.txt @@ -29,9 +29,9 @@ binaryornot==0.4.4 \ --hash=sha256:359501dfc9d40632edc9fac890e19542db1a287bbcfa58175b66658392018061 \ --hash=sha256:b8b71173c917bddcd2c16070412e369c3ed7f0528926f70cac18a6c97fd563e4 # via cookiecutter -boto3==1.28.2 \ - --hash=sha256:0d53fe604dc30edded21906bc56b30a7684f0715f4f6897307d53f8184997368 \ - --hash=sha256:9933e40dc9ac72deac45cecce2df020e3bf8d0d537538d2b361c17d1cee807cc +boto3==1.28.17 \ + --hash=sha256:90f7cfb5e1821af95b1fc084bc50e6c47fa3edc99f32de1a2591faa0c546bea7 \ + --hash=sha256:bca0526f819e0f19c0f1e6eba3e2d1d6b6a92a45129f98c0d716e5aab6d9444b # via # aws-sam-cli (setup.py) # aws-sam-translator @@ -39,15 +39,15 @@ boto3-stubs[apigateway,cloudformation,ecr,iam,lambda,s3,schemas,secretsmanager,s --hash=sha256:b140f56315cd99c659a2cbae32dc4ae1ee44073b4250e1ad391d03ecf4b5eb40 \ --hash=sha256:bcef1fcbd758de6078e75b036d3632dd95eaef00311e6688554b5b883a194563 # via aws-sam-cli (setup.py) -botocore==1.31.7 \ - --hash=sha256:f211ef5714bec8ae24b3fe737b8689611ef4d0dbea0ab46ef8328e112dd10ada \ - --hash=sha256:f4473f66c153c262b8262404d737f4249366daf00fb068b495577a24b830ebcb +botocore==1.31.17 \ + --hash=sha256:396459065dba4339eb4da4ec8b4e6599728eb89b7caaceea199e26f7d824a41c \ + --hash=sha256:6ac34a1d34aa3750e78b77b8596617e2bab938964694d651939dba2cbde2c12b # via # boto3 # s3transfer -botocore-stubs==1.31.12.post1 \ - --hash=sha256:aee5472654fbc0a0e6a78971d9918e71a3f3f48bc0f4f65116576ac6df796c49 \ - --hash=sha256:f3764c25bac463fe3c67b2d1c983dfebd4aae05ada94d41def2675e09dee970c +botocore-stubs==1.31.17 \ + --hash=sha256:0ccba9a9cee311e354c164fa8e8044a4b4150d7e536f0f09ae37637950391fbc \ + --hash=sha256:4a5c9415bd82fc22ad9b2e298022c96065ca1f330fc48b145fc1daa25fe10ff8 # via boto3-stubs certifi==2023.7.22 \ --hash=sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082 \ @@ -123,86 +123,86 @@ cfn-lint==0.79.5 \ --hash=sha256:3054a2e407f77b3115c41de49fe2c11d728d53ab7be4ae478c1b5ff0e21331b7 \ --hash=sha256:7a00dba8f70b8a92c38bfc8f45e2ab20cedad5c49054a46f1ce931e48fc1cd0c # via aws-sam-cli (setup.py) -chardet==5.1.0 \ - --hash=sha256:0d62712b956bc154f85fb0a266e2a3c5913c2967e00348701b32411d6def31e5 \ - --hash=sha256:362777fb014af596ad31334fde1e8c327dfdb076e1960d1694662d46a6917ab9 +chardet==5.2.0 \ + --hash=sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7 \ + --hash=sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970 # via binaryornot -charset-normalizer==3.1.0 \ - --hash=sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6 \ - --hash=sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1 \ - --hash=sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e \ - --hash=sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373 \ - --hash=sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62 \ - --hash=sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230 \ - --hash=sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be \ - --hash=sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c \ - --hash=sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0 \ - --hash=sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448 \ - --hash=sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f \ - --hash=sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649 \ - --hash=sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d \ - --hash=sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0 \ - --hash=sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706 \ - --hash=sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a \ - --hash=sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59 \ - --hash=sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23 \ - --hash=sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5 \ - --hash=sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb \ - --hash=sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e \ - --hash=sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e \ - --hash=sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c \ - --hash=sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28 \ - --hash=sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d \ - --hash=sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41 \ - --hash=sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974 \ - --hash=sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce \ - --hash=sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f \ - --hash=sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1 \ - --hash=sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d \ - --hash=sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8 \ - --hash=sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017 \ - --hash=sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31 \ - --hash=sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7 \ - --hash=sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8 \ - --hash=sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e \ - --hash=sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14 \ - --hash=sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd \ - --hash=sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d \ - --hash=sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795 \ - --hash=sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b \ - --hash=sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b \ - --hash=sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b \ - --hash=sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203 \ - --hash=sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f \ - --hash=sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19 \ - --hash=sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1 \ - --hash=sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a \ - --hash=sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac \ - --hash=sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9 \ - --hash=sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0 \ - --hash=sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137 \ - --hash=sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f \ - --hash=sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6 \ - --hash=sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5 \ - --hash=sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909 \ - --hash=sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f \ - --hash=sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0 \ - --hash=sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324 \ - --hash=sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755 \ - --hash=sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb \ - --hash=sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854 \ - --hash=sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c \ - --hash=sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60 \ - --hash=sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84 \ - --hash=sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0 \ - --hash=sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b \ - --hash=sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1 \ - --hash=sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531 \ - --hash=sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1 \ - --hash=sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11 \ - --hash=sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326 \ - --hash=sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df \ - --hash=sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab +charset-normalizer==3.2.0 \ + --hash=sha256:04e57ab9fbf9607b77f7d057974694b4f6b142da9ed4a199859d9d4d5c63fe96 \ + --hash=sha256:09393e1b2a9461950b1c9a45d5fd251dc7c6f228acab64da1c9c0165d9c7765c \ + --hash=sha256:0b87549028f680ca955556e3bd57013ab47474c3124dc069faa0b6545b6c9710 \ + --hash=sha256:1000fba1057b92a65daec275aec30586c3de2401ccdcd41f8a5c1e2c87078706 \ + --hash=sha256:1249cbbf3d3b04902ff081ffbb33ce3377fa6e4c7356f759f3cd076cc138d020 \ + --hash=sha256:1920d4ff15ce893210c1f0c0e9d19bfbecb7983c76b33f046c13a8ffbd570252 \ + --hash=sha256:193cbc708ea3aca45e7221ae58f0fd63f933753a9bfb498a3b474878f12caaad \ + --hash=sha256:1a100c6d595a7f316f1b6f01d20815d916e75ff98c27a01ae817439ea7726329 \ + --hash=sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a \ + --hash=sha256:203f0c8871d5a7987be20c72442488a0b8cfd0f43b7973771640fc593f56321f \ + --hash=sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6 \ + --hash=sha256:2dee8e57f052ef5353cf608e0b4c871aee320dd1b87d351c28764fc0ca55f9f4 \ + --hash=sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a \ + --hash=sha256:2f4ac36d8e2b4cc1aa71df3dd84ff8efbe3bfb97ac41242fbcfc053c67434f46 \ + --hash=sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2 \ + --hash=sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23 \ + --hash=sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace \ + --hash=sha256:3bb7fda7260735efe66d5107fb7e6af6a7c04c7fce9b2514e04b7a74b06bf5dd \ + --hash=sha256:41b25eaa7d15909cf3ac4c96088c1f266a9a93ec44f87f1d13d4a0e86c81b982 \ + --hash=sha256:45de3f87179c1823e6d9e32156fb14c1927fcc9aba21433f088fdfb555b77c10 \ + --hash=sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2 \ + --hash=sha256:48021783bdf96e3d6de03a6e39a1171ed5bd7e8bb93fc84cc649d11490f87cea \ + --hash=sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09 \ + --hash=sha256:5e86d77b090dbddbe78867a0275cb4df08ea195e660f1f7f13435a4649e954e5 \ + --hash=sha256:6339d047dab2780cc6220f46306628e04d9750f02f983ddb37439ca47ced7149 \ + --hash=sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489 \ + --hash=sha256:6c409c0deba34f147f77efaa67b8e4bb83d2f11c8806405f76397ae5b8c0d1c9 \ + --hash=sha256:7095f6fbfaa55defb6b733cfeb14efaae7a29f0b59d8cf213be4e7ca0b857b80 \ + --hash=sha256:70c610f6cbe4b9fce272c407dd9d07e33e6bf7b4aa1b7ffb6f6ded8e634e3592 \ + --hash=sha256:72814c01533f51d68702802d74f77ea026b5ec52793c791e2da806a3844a46c3 \ + --hash=sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6 \ + --hash=sha256:7c70087bfee18a42b4040bb9ec1ca15a08242cf5867c58726530bdf3945672ed \ + --hash=sha256:855eafa5d5a2034b4621c74925d89c5efef61418570e5ef9b37717d9c796419c \ + --hash=sha256:8700f06d0ce6f128de3ccdbc1acaea1ee264d2caa9ca05daaf492fde7c2a7200 \ + --hash=sha256:89f1b185a01fe560bc8ae5f619e924407efca2191b56ce749ec84982fc59a32a \ + --hash=sha256:8b2c760cfc7042b27ebdb4a43a4453bd829a5742503599144d54a032c5dc7e9e \ + --hash=sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d \ + --hash=sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6 \ + --hash=sha256:94aea8eff76ee6d1cdacb07dd2123a68283cb5569e0250feab1240058f53b623 \ + --hash=sha256:95eb302ff792e12aba9a8b8f8474ab229a83c103d74a750ec0bd1c1eea32e669 \ + --hash=sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3 \ + --hash=sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa \ + --hash=sha256:a103b3a7069b62f5d4890ae1b8f0597618f628b286b03d4bc9195230b154bfa9 \ + --hash=sha256:a386ebe437176aab38c041de1260cd3ea459c6ce5263594399880bbc398225b2 \ + --hash=sha256:a38856a971c602f98472050165cea2cdc97709240373041b69030be15047691f \ + --hash=sha256:a401b4598e5d3f4a9a811f3daf42ee2291790c7f9d74b18d75d6e21dda98a1a1 \ + --hash=sha256:a7647ebdfb9682b7bb97e2a5e7cb6ae735b1c25008a70b906aecca294ee96cf4 \ + --hash=sha256:aaf63899c94de41fe3cf934601b0f7ccb6b428c6e4eeb80da72c58eab077b19a \ + --hash=sha256:b0dac0ff919ba34d4df1b6131f59ce95b08b9065233446be7e459f95554c0dc8 \ + --hash=sha256:baacc6aee0b2ef6f3d308e197b5d7a81c0e70b06beae1f1fcacffdbd124fe0e3 \ + --hash=sha256:bf420121d4c8dce6b889f0e8e4ec0ca34b7f40186203f06a946fa0276ba54029 \ + --hash=sha256:c04a46716adde8d927adb9457bbe39cf473e1e2c2f5d0a16ceb837e5d841ad4f \ + --hash=sha256:c0b21078a4b56965e2b12f247467b234734491897e99c1d51cee628da9786959 \ + --hash=sha256:c1c76a1743432b4b60ab3358c937a3fe1341c828ae6194108a94c69028247f22 \ + --hash=sha256:c4983bf937209c57240cff65906b18bb35e64ae872da6a0db937d7b4af845dd7 \ + --hash=sha256:c4fb39a81950ec280984b3a44f5bd12819953dc5fa3a7e6fa7a80db5ee853952 \ + --hash=sha256:c57921cda3a80d0f2b8aec7e25c8aa14479ea92b5b51b6876d975d925a2ea346 \ + --hash=sha256:c8063cf17b19661471ecbdb3df1c84f24ad2e389e326ccaf89e3fb2484d8dd7e \ + --hash=sha256:ccd16eb18a849fd8dcb23e23380e2f0a354e8daa0c984b8a732d9cfaba3a776d \ + --hash=sha256:cd6dbe0238f7743d0efe563ab46294f54f9bc8f4b9bcf57c3c666cc5bc9d1299 \ + --hash=sha256:d62e51710986674142526ab9f78663ca2b0726066ae26b78b22e0f5e571238dd \ + --hash=sha256:db901e2ac34c931d73054d9797383d0f8009991e723dab15109740a63e7f902a \ + --hash=sha256:e03b8895a6990c9ab2cdcd0f2fe44088ca1c65ae592b8f795c3294af00a461c3 \ + --hash=sha256:e1c8a2f4c69e08e89632defbfabec2feb8a8d99edc9f89ce33c4b9e36ab63037 \ + --hash=sha256:e4b749b9cc6ee664a3300bb3a273c1ca8068c46be705b6c31cf5d276f8628a94 \ + --hash=sha256:e6a5bf2cba5ae1bb80b154ed68a3cfa2fa00fde979a7f50d6598d3e17d9ac20c \ + --hash=sha256:e857a2232ba53ae940d3456f7533ce6ca98b81917d47adc3c7fd55dad8fab858 \ + --hash=sha256:ee4006268ed33370957f55bf2e6f4d263eaf4dc3cfc473d1d90baff6ed36ce4a \ + --hash=sha256:eef9df1eefada2c09a5e7a40991b9fc6ac6ef20b1372abd48d2794a316dc0449 \ + --hash=sha256:f058f6963fd82eb143c692cecdc89e075fa0828db2e5b291070485390b2f1c9c \ + --hash=sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918 \ + --hash=sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1 \ + --hash=sha256:f7560358a6811e52e9c4d142d497f1a6e10103d3a6881f18d04dbce3729c0e2c \ + --hash=sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac \ + --hash=sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa # via requests chevron==0.14.0 \ --hash=sha256:87613aafdf6d77b6a90ff073165a61ae5086e21ad49057aa0e53681601800ebf \ @@ -286,17 +286,17 @@ jschema-to-python==1.2.3 \ --hash=sha256:76ff14fe5d304708ccad1284e4b11f96a658949a31ee7faed9e0995279549b91 \ --hash=sha256:8a703ca7604d42d74b2815eecf99a33359a8dccbb80806cce386d5e2dd992b05 # via cfn-lint -jsonpatch==1.32 \ - --hash=sha256:26ac385719ac9f54df8a2f0827bb8253aa3ea8ab7b3368457bcdb8c14595a397 \ - --hash=sha256:b6ddfe6c3db30d81a96aaeceb6baf916094ffa23d7dd5fa2c13e13f8b6e600c2 +jsonpatch==1.33 \ + --hash=sha256:0ae28c0cd062bbd8b8ecc26d7d164fbbea9652a1a3693f3b956c1eae5145dade \ + --hash=sha256:9fcd4009c41e6d12348b4a0ff2563ba56a2923a7dfee731d004e212e1ee5030c # via cfn-lint jsonpickle==3.0.1 \ --hash=sha256:032538804795e73b94ead410800ac387fdb6de98f8882ac957fcd247e3a85200 \ --hash=sha256:130d8b293ea0add3845de311aaba55e6d706d0bb17bc123bd2c8baf8a39ac77c # via jschema-to-python -jsonpointer==2.3 \ - --hash=sha256:51801e558539b4e9cd268638c078c6c5746c9ac96bc38152d443400e4f3793e9 \ - --hash=sha256:97cba51526c829282218feb99dab1b1e6bdf8efd1c43dc9d57be093c0d69c99a +jsonpointer==2.4 \ + --hash=sha256:15d51bba20eea3165644553647711d150376234112651b4f1811022aecad7d7a \ + --hash=sha256:585cee82b70211fa9e6043b7bb89db6e1aa49524340dde8ad6b63206ea689d88 # via jsonpatch jsonschema==4.17.3 \ --hash=sha256:0f864437ab8b6076ba6707453ef8f98a6a0d512a80e93f8abdb676f737ecb60d \ @@ -375,53 +375,53 @@ mpmath==1.3.0 \ --hash=sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f \ --hash=sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c # via sympy -mypy-boto3-apigateway==1.28.12 \ - --hash=sha256:83d7e8b5f07952992f36c6ec021d0a8abe0d107943a6a178c53c444f269094c9 \ - --hash=sha256:a580a886d93658fb0f056d576615fe8de2b0a1fb7239c2b1c918080b0be2d1bb +mypy-boto3-apigateway==1.28.16 \ + --hash=sha256:4193124b6ab5b92de0affdd59f1485a17d68ecefff17b411f73a08ea5d5db92d \ + --hash=sha256:82491d942530ab9dabc4c811e188c6ab546c3e658c5718bab58fb45cadef6d0b # via boto3-stubs -mypy-boto3-cloudformation==1.28.0 \ - --hash=sha256:0d2ead02c352bc97ae59b65ae8b00d5ce186435b7cf5736213a52f58df192511 \ - --hash=sha256:99d5db7d6b220ba016757670a917bdfdab1c475593153833ed6c5cdd9a9aa9ba +mypy-boto3-cloudformation==1.28.16 \ + --hash=sha256:228cb6e9096f64d36abd912c34e465545ff848bb837498112dc30235ca19750c \ + --hash=sha256:a5202db1ea76aa499a27b971745e0130e5cb88c2b323c48cca30cd01713d963a # via boto3-stubs -mypy-boto3-ecr==1.28.0 \ - --hash=sha256:46b493af9024e230f7b81c7dc1ca2b52d5cca168f867be60a55ce0b86a3999f7 \ - --hash=sha256:d4cbad3f4d33abbfe0a7d7504b38f01d256c5200d754b5289d1f373bcd595bf4 +mypy-boto3-ecr==1.28.16 \ + --hash=sha256:412aa7e26d20e7502267e5fec4d94f0bc48db0ced24f65d207911fe70585a4cd \ + --hash=sha256:b3252c5eda47ca1e90980e0158410e8a76c8acdfbda0907f545ddfddaea95258 # via boto3-stubs -mypy-boto3-iam==1.28.3.post2 \ - --hash=sha256:16d642b5507067bd2cfae5e3fd149b9ccf7070bc98e7214058cae40c478eaccf \ - --hash=sha256:32ed5e5d961d628c0f5bad06e3b3342df6d3bec0d9a6dd5d746fce53a7d5f6dc +mypy-boto3-iam==1.28.16 \ + --hash=sha256:1416df5e838be7cc8b65def4721097faf691f8f0c65f58fe417d18b9e6b8de61 \ + --hash=sha256:8ef9ef9a9fabcc1058a46bbd6b1408960a70d72e45a024862676e5a896c446b3 # via boto3-stubs -mypy-boto3-lambda==1.28.0 \ - --hash=sha256:5fd38df6418829b2f3a184918fc8ad1d49b6738509f1832cdc71f33588efbdfb \ - --hash=sha256:a3abaf98e514f2cabed2cf0b1e77c94c81f0fbbba8a549b3c073577a9f9ac196 +mypy-boto3-lambda==1.28.16 \ + --hash=sha256:c1b688c1ea7cbb9b79b8a1dcaaa7459791ae7ebc608490251f58a07edb31170c \ + --hash=sha256:c7c647139e6710da694aba4a644f69f4a06c6e43419168d69cc57f3dc6e5e607 # via boto3-stubs -mypy-boto3-s3==1.28.3.post2 \ - --hash=sha256:02dc6b9edf799afa160be1e3a9b38a383af6fcd80a97abd75d09410b26621e70 \ - --hash=sha256:c23b7802b80a0388a146d7e8025552f21d44e349026a18fb751d9c698ed714b1 +mypy-boto3-s3==1.28.16 \ + --hash=sha256:4e55fdad729b6e6f45211e354bd1a0a745a565fe9d1e462737f775c28849cfb5 \ + --hash=sha256:855f7848186c45adbd3c474fec2d75db17f4cd7200c0a2235473250454ec4686 # via boto3-stubs -mypy-boto3-schemas==1.28.0 \ - --hash=sha256:371972ab1301f03cb504ea16a0aa566e9c889a436b5b1a221c15d04f5710f47f \ - --hash=sha256:d15c838e812a8e1b20c7a6ce7d794231e1d9cc73b65cbbf9385f3d2984f4e929 +mypy-boto3-schemas==1.28.16 \ + --hash=sha256:4f4b4fc784452b5186ab31199e4cb5546d314f3fc666cb698c960ba89e33448e \ + --hash=sha256:7898f9624af46be956bd8e1dffc6fc01d6e2141e067444156bddd2c412ef8084 # via boto3-stubs -mypy-boto3-secretsmanager==1.28.3.post2 \ - --hash=sha256:3a5e5619ee945f244d2dfefcb382c85874171a18b46f75403465622095284d25 \ - --hash=sha256:f359f6446ac856d0887e40cb0f5bc6e0a60873524be5dd4b68be1d0fc4ac513e +mypy-boto3-secretsmanager==1.28.16 \ + --hash=sha256:05508c3a96d96e482e5aff21b508319a1911e6662aea5be96aa7f7089b8dbfd4 \ + --hash=sha256:07f443b31d2114ac363cfbdbc5f4b97934ca48fb99734bbd06d5c39bce244b83 # via boto3-stubs -mypy-boto3-signer==1.28.0 \ - --hash=sha256:55288fed77e2ae3121c4ecb15b64d4cc3984f069ff4671d5dbd9b14fc9b6f5f1 \ - --hash=sha256:c24d4fd291b194248c61f7696d1bb56c5e8db13f792dff1720126c208f922539 +mypy-boto3-signer==1.28.16 \ + --hash=sha256:78d9bacf72b865221c6d11a946a0d6aad3b14904475c886fafd08cd1dd54c5d7 \ + --hash=sha256:a67206f20189105a24deee995ab130123fa1af75c39c13c17e404ff74b9ec1fc # via boto3-stubs -mypy-boto3-stepfunctions==1.28.0 \ - --hash=sha256:47ab107c76513a04d241357157ee6886c3e8b7965ccd7fcce66ec44efbd2b43a \ - --hash=sha256:7a3f702287ae4d311ffa34643318257c9dbf25490131d244e1e085c222c33465 +mypy-boto3-stepfunctions==1.28.16 \ + --hash=sha256:8b2b6578ca38dc0f13d73292b92afd7f3cf11a8999a33886d4c4ab6822f0020a \ + --hash=sha256:962c80b1bac778b64c6334df50a3860bf4d0a5d17560fac765e7913615926b2b # via boto3-stubs -mypy-boto3-sts==1.28.0 \ - --hash=sha256:161acaf4ac14282f3a1accfe06e372b1ee902840d32c2bad4e4eebbf7dd66607 \ - --hash=sha256:81daa1e27e1c07b70eccc8de8d95f2676593dd6f7fd217a22f269d94b9b81e36 +mypy-boto3-sts==1.28.16 \ + --hash=sha256:7cd388a7451611813730b83c78179759eb5701b849618d82c3ec7e95576bedb9 \ + --hash=sha256:a00bc7f69d8675058db0fb2c39d4d9dbb3a3c14ae1d0d83fbf930a2a0498629a # via boto3-stubs -mypy-boto3-xray==1.28.0 \ - --hash=sha256:64cd601a829c274665b977853f85b27464986e9eec1ebc03f5bc4530a400b2f6 \ - --hash=sha256:8ce07598f7eeabe66e8dc8cb7e906efb96198b9102f58e9315e6daf166abf3e7 +mypy-boto3-xray==1.28.16 \ + --hash=sha256:4bc7dfd46cb71ca6a9d46b47453d59a08ac80c872cc429dacb45a93abd737172 \ + --hash=sha256:6ddd4acccf272bf663522c5fcd31b9b7dacbed4a01c91e44e4e8c0abb2343c0a # via boto3-stubs networkx==3.1 \ --hash=sha256:4f33f68cb2afcf86f28a45f43efc27a9386b535d567d2127f8f61d51dec58d36 \ @@ -441,43 +441,43 @@ pycparser==2.21 \ --hash=sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9 \ --hash=sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206 # via cffi -pydantic==1.10.8 \ - --hash=sha256:052d8654cb65174d6f9490cc9b9a200083a82cf5c3c5d3985db765757eb3b375 \ - --hash=sha256:0c6fafa0965b539d7aab0a673a046466d23b86e4b0e8019d25fd53f4df62c277 \ - --hash=sha256:1243d28e9b05003a89d72e7915fdb26ffd1d39bdd39b00b7dbe4afae4b557f9d \ - --hash=sha256:12f7b0bf8553e310e530e9f3a2f5734c68699f42218bf3568ef49cd9b0e44df4 \ - --hash=sha256:1410275520dfa70effadf4c21811d755e7ef9bb1f1d077a21958153a92c8d9ca \ - --hash=sha256:16f8c3e33af1e9bb16c7a91fc7d5fa9fe27298e9f299cff6cb744d89d573d62c \ - --hash=sha256:17aef11cc1b997f9d574b91909fed40761e13fac438d72b81f902226a69dac01 \ - --hash=sha256:191ba419b605f897ede9892f6c56fb182f40a15d309ef0142212200a10af4c18 \ - --hash=sha256:1952526ba40b220b912cdc43c1c32bcf4a58e3f192fa313ee665916b26befb68 \ - --hash=sha256:1ced8375969673929809d7f36ad322934c35de4af3b5e5b09ec967c21f9f7887 \ - --hash=sha256:2e4148e635994d57d834be1182a44bdb07dd867fa3c2d1b37002000646cc5459 \ - --hash=sha256:34d327c81e68a1ecb52fe9c8d50c8a9b3e90d3c8ad991bfc8f953fb477d42fb4 \ - --hash=sha256:35db5301b82e8661fa9c505c800d0990bc14e9f36f98932bb1d248c0ac5cada5 \ - --hash=sha256:3e59417ba8a17265e632af99cc5f35ec309de5980c440c255ab1ca3ae96a3e0e \ - --hash=sha256:42aa0c4b5c3025483240a25b09f3c09a189481ddda2ea3a831a9d25f444e03c1 \ - --hash=sha256:666bdf6066bf6dbc107b30d034615d2627e2121506c555f73f90b54a463d1f33 \ - --hash=sha256:66a703d1983c675a6e0fed8953b0971c44dba48a929a2000a493c3772eb61a5a \ - --hash=sha256:6a82d6cda82258efca32b40040228ecf43a548671cb174a1e81477195ed3ed56 \ - --hash=sha256:6f2e754d5566f050954727c77f094e01793bcb5725b663bf628fa6743a5a9108 \ - --hash=sha256:7456eb22ed9aaa24ff3e7b4757da20d9e5ce2a81018c1b3ebd81a0b88a18f3b2 \ - --hash=sha256:7b1f6cb446470b7ddf86c2e57cd119a24959af2b01e552f60705910663af09a4 \ - --hash=sha256:7d5b8641c24886d764a74ec541d2fc2c7fb19f6da2a4001e6d580ba4a38f7878 \ - --hash=sha256:84d80219c3f8d4cad44575e18404099c76851bc924ce5ab1c4c8bb5e2a2227d0 \ - --hash=sha256:88f195f582851e8db960b4a94c3e3ad25692c1c1539e2552f3df7a9e972ef60e \ - --hash=sha256:93e6bcfccbd831894a6a434b0aeb1947f9e70b7468f274154d03d71fabb1d7c6 \ - --hash=sha256:93e766b4a8226e0708ef243e843105bf124e21331694367f95f4e3b4a92bbb3f \ - --hash=sha256:ab523c31e22943713d80d8d342d23b6f6ac4b792a1e54064a8d0cf78fd64e800 \ - --hash=sha256:bb14388ec45a7a0dc429e87def6396f9e73c8c77818c927b6a60706603d5f2ea \ - --hash=sha256:c0ab53b609c11dfc0c060d94335993cc2b95b2150e25583bec37a49b2d6c6c3f \ - --hash=sha256:c33b60054b2136aef8cf190cd4c52a3daa20b2263917c49adad20eaf381e823b \ - --hash=sha256:ceb6a23bf1ba4b837d0cfe378329ad3f351b5897c8d4914ce95b85fba96da5a1 \ - --hash=sha256:d532bf00f381bd6bc62cabc7d1372096b75a33bc197a312b03f5838b4fb84edd \ - --hash=sha256:df7800cb1984d8f6e249351139667a8c50a379009271ee6236138a22a0c0f319 \ - --hash=sha256:e82d4566fcd527eae8b244fa952d99f2ca3172b7e97add0b43e2d97ee77f81ab \ - --hash=sha256:f90c1e29f447557e9e26afb1c4dbf8768a10cc676e3781b6a577841ade126b85 \ - --hash=sha256:f9613fadad06b4f3bc5db2653ce2f22e0de84a7c6c293909b48f6ed37b83c61f +pydantic==1.10.12 \ + --hash=sha256:0fe8a415cea8f340e7a9af9c54fc71a649b43e8ca3cc732986116b3cb135d303 \ + --hash=sha256:1289c180abd4bd4555bb927c42ee42abc3aee02b0fb2d1223fb7c6e5bef87dbe \ + --hash=sha256:1eb2085c13bce1612da8537b2d90f549c8cbb05c67e8f22854e201bde5d98a47 \ + --hash=sha256:2031de0967c279df0d8a1c72b4ffc411ecd06bac607a212892757db7462fc494 \ + --hash=sha256:2a7bac939fa326db1ab741c9d7f44c565a1d1e80908b3797f7f81a4f86bc8d33 \ + --hash=sha256:2d5a58feb9a39f481eda4d5ca220aa8b9d4f21a41274760b9bc66bfd72595b86 \ + --hash=sha256:2f9a6fab5f82ada41d56b0602606a5506aab165ca54e52bc4545028382ef1c5d \ + --hash=sha256:2fcfb5296d7877af406ba1547dfde9943b1256d8928732267e2653c26938cd9c \ + --hash=sha256:549a8e3d81df0a85226963611950b12d2d334f214436a19537b2efed61b7639a \ + --hash=sha256:598da88dfa127b666852bef6d0d796573a8cf5009ffd62104094a4fe39599565 \ + --hash=sha256:5d1197e462e0364906cbc19681605cb7c036f2475c899b6f296104ad42b9f5fb \ + --hash=sha256:69328e15cfda2c392da4e713443c7dbffa1505bc9d566e71e55abe14c97ddc62 \ + --hash=sha256:6a9dfa722316f4acf4460afdf5d41d5246a80e249c7ff475c43a3a1e9d75cf62 \ + --hash=sha256:6b30bcb8cbfccfcf02acb8f1a261143fab622831d9c0989707e0e659f77a18e0 \ + --hash=sha256:6c076be61cd0177a8433c0adcb03475baf4ee91edf5a4e550161ad57fc90f523 \ + --hash=sha256:771735dc43cf8383959dc9b90aa281f0b6092321ca98677c5fb6125a6f56d58d \ + --hash=sha256:795e34e6cc065f8f498c89b894a3c6da294a936ee71e644e4bd44de048af1405 \ + --hash=sha256:87afda5539d5140cb8ba9e8b8c8865cb5b1463924d38490d73d3ccfd80896b3f \ + --hash=sha256:8fb2aa3ab3728d950bcc885a2e9eff6c8fc40bc0b7bb434e555c215491bcf48b \ + --hash=sha256:a1fcb59f2f355ec350073af41d927bf83a63b50e640f4dbaa01053a28b7a7718 \ + --hash=sha256:a5e7add47a5b5a40c49b3036d464e3c7802f8ae0d1e66035ea16aa5b7a3923ed \ + --hash=sha256:a73f489aebd0c2121ed974054cb2759af8a9f747de120acd2c3394cf84176ccb \ + --hash=sha256:ab26038b8375581dc832a63c948f261ae0aa21f1d34c1293469f135fa92972a5 \ + --hash=sha256:b0d191db0f92dfcb1dec210ca244fdae5cbe918c6050b342d619c09d31eea0cc \ + --hash=sha256:b749a43aa51e32839c9d71dc67eb1e4221bb04af1033a32e3923d46f9effa942 \ + --hash=sha256:b7ccf02d7eb340b216ec33e53a3a629856afe1c6e0ef91d84a4e6f2fb2ca70fe \ + --hash=sha256:ba5b2e6fe6ca2b7e013398bc7d7b170e21cce322d266ffcd57cca313e54fb246 \ + --hash=sha256:ba5c4a8552bff16c61882db58544116d021d0b31ee7c66958d14cf386a5b5350 \ + --hash=sha256:c79e6a11a07da7374f46970410b41d5e266f7f38f6a17a9c4823db80dadf4303 \ + --hash=sha256:ca48477862372ac3770969b9d75f1bf66131d386dba79506c46d75e6b48c1e09 \ + --hash=sha256:dea7adcc33d5d105896401a1f37d56b47d443a2b2605ff8a969a0ed5543f7e33 \ + --hash=sha256:e0a16d274b588767602b7646fa05af2782576a6cf1022f4ba74cbb4db66f6ca8 \ + --hash=sha256:e4129b528c6baa99a429f97ce733fff478ec955513630e61b49804b6cf9b224a \ + --hash=sha256:e5f805d2d5d0a41633651a73fa4ecdd0b3d7a49de4ec3fadf062fe16501ddbf1 \ + --hash=sha256:ef6c96b2baa2100ec91a4b428f80d8f28a3c9e53568219b6c298c1125572ebc6 \ + --hash=sha256:fdbdd1d630195689f325c9ef1a12900524dceb503b00a987663ff4f58669b93d # via aws-sam-translator pygments==2.15.1 \ --hash=sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c \ @@ -576,95 +576,95 @@ pyyaml==6.0.1 \ # aws-sam-cli (setup.py) # cfn-lint # cookiecutter -regex==2023.5.5 \ - --hash=sha256:02f4541550459c08fdd6f97aa4e24c6f1932eec780d58a2faa2068253df7d6ff \ - --hash=sha256:0a69cf0c00c4d4a929c6c7717fd918414cab0d6132a49a6d8fc3ded1988ed2ea \ - --hash=sha256:0bbd5dcb19603ab8d2781fac60114fb89aee8494f4505ae7ad141a3314abb1f9 \ - --hash=sha256:10250a093741ec7bf74bcd2039e697f519b028518f605ff2aa7ac1e9c9f97423 \ - --hash=sha256:10374c84ee58c44575b667310d5bbfa89fb2e64e52349720a0182c0017512f6c \ - --hash=sha256:1189fbbb21e2c117fda5303653b61905aeeeea23de4a94d400b0487eb16d2d60 \ - --hash=sha256:1307aa4daa1cbb23823d8238e1f61292fd07e4e5d8d38a6efff00b67a7cdb764 \ - --hash=sha256:144b5b017646b5a9392a5554a1e5db0000ae637be4971c9747566775fc96e1b2 \ - --hash=sha256:171c52e320fe29260da550d81c6b99f6f8402450dc7777ef5ced2e848f3b6f8f \ - --hash=sha256:18196c16a584619c7c1d843497c069955d7629ad4a3fdee240eb347f4a2c9dbe \ - --hash=sha256:18f05d14f14a812fe9723f13afafefe6b74ca042d99f8884e62dbd34dcccf3e2 \ - --hash=sha256:1ecf3dcff71f0c0fe3e555201cbe749fa66aae8d18f80d2cc4de8e66df37390a \ - --hash=sha256:21e90a288e6ba4bf44c25c6a946cb9b0f00b73044d74308b5e0afd190338297c \ - --hash=sha256:23d86ad2121b3c4fc78c58f95e19173790e22ac05996df69b84e12da5816cb17 \ - --hash=sha256:256f7f4c6ba145f62f7a441a003c94b8b1af78cee2cccacfc1e835f93bc09426 \ - --hash=sha256:290fd35219486dfbc00b0de72f455ecdd63e59b528991a6aec9fdfc0ce85672e \ - --hash=sha256:2e9c4f778514a560a9c9aa8e5538bee759b55f6c1dcd35613ad72523fd9175b8 \ - --hash=sha256:338994d3d4ca4cf12f09822e025731a5bdd3a37aaa571fa52659e85ca793fb67 \ - --hash=sha256:33d430a23b661629661f1fe8395be2004006bc792bb9fc7c53911d661b69dd7e \ - --hash=sha256:385992d5ecf1a93cb85adff2f73e0402dd9ac29b71b7006d342cc920816e6f32 \ - --hash=sha256:3d45864693351c15531f7e76f545ec35000d50848daa833cead96edae1665559 \ - --hash=sha256:40005cbd383438aecf715a7b47fe1e3dcbc889a36461ed416bdec07e0ef1db66 \ - --hash=sha256:4035d6945cb961c90c3e1c1ca2feb526175bcfed44dfb1cc77db4fdced060d3e \ - --hash=sha256:445d6f4fc3bd9fc2bf0416164454f90acab8858cd5a041403d7a11e3356980e8 \ - --hash=sha256:48c9ec56579d4ba1c88f42302194b8ae2350265cb60c64b7b9a88dcb7fbde309 \ - --hash=sha256:4a5059bd585e9e9504ef9c07e4bc15b0a621ba20504388875d66b8b30a5c4d18 \ - --hash=sha256:4a6e4b0e0531223f53bad07ddf733af490ba2b8367f62342b92b39b29f72735a \ - --hash=sha256:4b870b6f632fc74941cadc2a0f3064ed8409e6f8ee226cdfd2a85ae50473aa94 \ - --hash=sha256:50fd2d9b36938d4dcecbd684777dd12a407add4f9f934f235c66372e630772b0 \ - --hash=sha256:53e22e4460f0245b468ee645156a4f84d0fc35a12d9ba79bd7d79bdcd2f9629d \ - --hash=sha256:586a011f77f8a2da4b888774174cd266e69e917a67ba072c7fc0e91878178a80 \ - --hash=sha256:59597cd6315d3439ed4b074febe84a439c33928dd34396941b4d377692eca810 \ - --hash=sha256:59e4b729eae1a0919f9e4c0fc635fbcc9db59c74ad98d684f4877be3d2607dd6 \ - --hash=sha256:5a0f874ee8c0bc820e649c900243c6d1e6dc435b81da1492046716f14f1a2a96 \ - --hash=sha256:5ac2b7d341dc1bd102be849d6dd33b09701223a851105b2754339e390be0627a \ - --hash=sha256:5e3f4468b8c6fd2fd33c218bbd0a1559e6a6fcf185af8bb0cc43f3b5bfb7d636 \ - --hash=sha256:6164d4e2a82f9ebd7752a06bd6c504791bedc6418c0196cd0a23afb7f3e12b2d \ - --hash=sha256:6893544e06bae009916a5658ce7207e26ed17385149f35a3125f5259951f1bbe \ - --hash=sha256:690a17db524ee6ac4a27efc5406530dd90e7a7a69d8360235323d0e5dafb8f5b \ - --hash=sha256:6b8d0c153f07a953636b9cdb3011b733cadd4178123ef728ccc4d5969e67f3c2 \ - --hash=sha256:72a28979cc667e5f82ef433db009184e7ac277844eea0f7f4d254b789517941d \ - --hash=sha256:72aa4746993a28c841e05889f3f1b1e5d14df8d3daa157d6001a34c98102b393 \ - --hash=sha256:732176f5427e72fa2325b05c58ad0b45af341c459910d766f814b0584ac1f9ac \ - --hash=sha256:7918a1b83dd70dc04ab5ed24c78ae833ae8ea228cef84e08597c408286edc926 \ - --hash=sha256:7923470d6056a9590247ff729c05e8e0f06bbd4efa6569c916943cb2d9b68b91 \ - --hash=sha256:7d76a8a1fc9da08296462a18f16620ba73bcbf5909e42383b253ef34d9d5141e \ - --hash=sha256:811040d7f3dd9c55eb0d8b00b5dcb7fd9ae1761c454f444fd9f37fe5ec57143a \ - --hash=sha256:821a88b878b6589c5068f4cc2cfeb2c64e343a196bc9d7ac68ea8c2a776acd46 \ - --hash=sha256:84397d3f750d153ebd7f958efaa92b45fea170200e2df5e0e1fd4d85b7e3f58a \ - --hash=sha256:844671c9c1150fcdac46d43198364034b961bd520f2c4fdaabfc7c7d7138a2dd \ - --hash=sha256:890a09cb0a62198bff92eda98b2b507305dd3abf974778bae3287f98b48907d3 \ - --hash=sha256:8f08276466fedb9e36e5193a96cb944928301152879ec20c2d723d1031cd4ddd \ - --hash=sha256:8f5e06df94fff8c4c85f98c6487f6636848e1dc85ce17ab7d1931df4a081f657 \ - --hash=sha256:921473a93bcea4d00295799ab929522fc650e85c6b9f27ae1e6bb32a790ea7d3 \ - --hash=sha256:941b3f1b2392f0bcd6abf1bc7a322787d6db4e7457be6d1ffd3a693426a755f2 \ - --hash=sha256:9b320677521aabf666cdd6e99baee4fb5ac3996349c3b7f8e7c4eee1c00dfe3a \ - --hash=sha256:9c3efee9bb53cbe7b285760c81f28ac80dc15fa48b5fe7e58b52752e642553f1 \ - --hash=sha256:9fda3e50abad8d0f48df621cf75adc73c63f7243cbe0e3b2171392b445401550 \ - --hash=sha256:a4c5da39bca4f7979eefcbb36efea04471cd68db2d38fcbb4ee2c6d440699833 \ - --hash=sha256:a56c18f21ac98209da9c54ae3ebb3b6f6e772038681d6cb43b8d53da3b09ee81 \ - --hash=sha256:a623564d810e7a953ff1357f7799c14bc9beeab699aacc8b7ab7822da1e952b8 \ - --hash=sha256:a8906669b03c63266b6a7693d1f487b02647beb12adea20f8840c1a087e2dfb5 \ - --hash=sha256:a99757ad7fe5c8a2bb44829fc57ced11253e10f462233c1255fe03888e06bc19 \ - --hash=sha256:aa7d032c1d84726aa9edeb6accf079b4caa87151ca9fabacef31fa028186c66d \ - --hash=sha256:aad5524c2aedaf9aa14ef1bc9327f8abd915699dea457d339bebbe2f0d218f86 \ - --hash=sha256:afb1c70ec1e594a547f38ad6bf5e3d60304ce7539e677c1429eebab115bce56e \ - --hash=sha256:b6365703e8cf1644b82104cdd05270d1a9f043119a168d66c55684b1b557d008 \ - --hash=sha256:b8b942d8b3ce765dbc3b1dad0a944712a89b5de290ce8f72681e22b3c55f3cc8 \ - --hash=sha256:ba73a14e9c8f9ac409863543cde3290dba39098fc261f717dc337ea72d3ebad2 \ - --hash=sha256:bd7b68fd2e79d59d86dcbc1ccd6e2ca09c505343445daaa4e07f43c8a9cc34da \ - --hash=sha256:bd966475e963122ee0a7118ec9024388c602d12ac72860f6eea119a3928be053 \ - --hash=sha256:c2ce65bdeaf0a386bb3b533a28de3994e8e13b464ac15e1e67e4603dd88787fa \ - --hash=sha256:c64d5abe91a3dfe5ff250c6bb267ef00dbc01501518225b45a5f9def458f31fb \ - --hash=sha256:c8c143a65ce3ca42e54d8e6fcaf465b6b672ed1c6c90022794a802fb93105d22 \ - --hash=sha256:cd46f30e758629c3ee91713529cfbe107ac50d27110fdcc326a42ce2acf4dafc \ - --hash=sha256:ced02e3bd55e16e89c08bbc8128cff0884d96e7f7a5633d3dc366b6d95fcd1d6 \ - --hash=sha256:cf123225945aa58b3057d0fba67e8061c62d14cc8a4202630f8057df70189051 \ - --hash=sha256:d19e57f888b00cd04fc38f5e18d0efbd91ccba2d45039453ab2236e6eec48d4d \ - --hash=sha256:d1cbe6b5be3b9b698d8cc4ee4dee7e017ad655e83361cd0ea8e653d65e469468 \ - --hash=sha256:db09e6c18977a33fea26fe67b7a842f706c67cf8bda1450974d0ae0dd63570df \ - --hash=sha256:de2f780c3242ea114dd01f84848655356af4dd561501896c751d7b885ea6d3a1 \ - --hash=sha256:e2205a81f815b5bb17e46e74cc946c575b484e5f0acfcb805fb252d67e22938d \ - --hash=sha256:e645c757183ee0e13f0bbe56508598e2d9cd42b8abc6c0599d53b0d0b8dd1479 \ - --hash=sha256:f2910502f718828cecc8beff004917dcf577fc5f8f5dd40ffb1ea7612124547b \ - --hash=sha256:f764e4dfafa288e2eba21231f455d209f4709436baeebb05bdecfb5d8ddc3d35 \ - --hash=sha256:f83fe9e10f9d0b6cf580564d4d23845b9d692e4c91bd8be57733958e4c602956 \ - --hash=sha256:fb2b495dd94b02de8215625948132cc2ea360ae84fe6634cd19b6567709c8ae2 \ - --hash=sha256:fee0016cc35a8a91e8cc9312ab26a6fe638d484131a7afa79e1ce6165328a135 +regex==2023.6.3 \ + --hash=sha256:0385e73da22363778ef2324950e08b689abdf0b108a7d8decb403ad7f5191938 \ + --hash=sha256:051da80e6eeb6e239e394ae60704d2b566aa6a7aed6f2890a7967307267a5dc6 \ + --hash=sha256:05ed27acdf4465c95826962528f9e8d41dbf9b1aa8531a387dee6ed215a3e9ef \ + --hash=sha256:0654bca0cdf28a5956c83839162692725159f4cda8d63e0911a2c0dc76166525 \ + --hash=sha256:09e4a1a6acc39294a36b7338819b10baceb227f7f7dbbea0506d419b5a1dd8af \ + --hash=sha256:0b49c764f88a79160fa64f9a7b425620e87c9f46095ef9c9920542ab2495c8bc \ + --hash=sha256:0b71e63226e393b534105fcbdd8740410dc6b0854c2bfa39bbda6b0d40e59a54 \ + --hash=sha256:0c29ca1bd61b16b67be247be87390ef1d1ef702800f91fbd1991f5c4421ebae8 \ + --hash=sha256:10590510780b7541969287512d1b43f19f965c2ece6c9b1c00fc367b29d8dce7 \ + --hash=sha256:10cb847aeb1728412c666ab2e2000ba6f174f25b2bdc7292e7dd71b16db07568 \ + --hash=sha256:12b74fbbf6cbbf9dbce20eb9b5879469e97aeeaa874145517563cca4029db65c \ + --hash=sha256:20326216cc2afe69b6e98528160b225d72f85ab080cbdf0b11528cbbaba2248f \ + --hash=sha256:2239d95d8e243658b8dbb36b12bd10c33ad6e6933a54d36ff053713f129aa536 \ + --hash=sha256:25be746a8ec7bc7b082783216de8e9473803706723b3f6bef34b3d0ed03d57e2 \ + --hash=sha256:271f0bdba3c70b58e6f500b205d10a36fb4b58bd06ac61381b68de66442efddb \ + --hash=sha256:29cdd471ebf9e0f2fb3cac165efedc3c58db841d83a518b082077e612d3ee5df \ + --hash=sha256:2d44dc13229905ae96dd2ae2dd7cebf824ee92bc52e8cf03dcead37d926da019 \ + --hash=sha256:3676f1dd082be28b1266c93f618ee07741b704ab7b68501a173ce7d8d0d0ca18 \ + --hash=sha256:36efeba71c6539d23c4643be88295ce8c82c88bbd7c65e8a24081d2ca123da3f \ + --hash=sha256:3e5219bf9e75993d73ab3d25985c857c77e614525fac9ae02b1bebd92f7cecac \ + --hash=sha256:43e1dd9d12df9004246bacb79a0e5886b3b6071b32e41f83b0acbf293f820ee8 \ + --hash=sha256:457b6cce21bee41ac292d6753d5e94dcbc5c9e3e3a834da285b0bde7aa4a11e9 \ + --hash=sha256:463b6a3ceb5ca952e66550a4532cef94c9a0c80dc156c4cc343041951aec1697 \ + --hash=sha256:4959e8bcbfda5146477d21c3a8ad81b185cd252f3d0d6e4724a5ef11c012fb06 \ + --hash=sha256:4d3850beab9f527f06ccc94b446c864059c57651b3f911fddb8d9d3ec1d1b25d \ + --hash=sha256:5708089ed5b40a7b2dc561e0c8baa9535b77771b64a8330b684823cfd5116036 \ + --hash=sha256:5c6b48d0fa50d8f4df3daf451be7f9689c2bde1a52b1225c5926e3f54b6a9ed1 \ + --hash=sha256:61474f0b41fe1a80e8dfa70f70ea1e047387b7cd01c85ec88fa44f5d7561d787 \ + --hash=sha256:6343c6928282c1f6a9db41f5fd551662310e8774c0e5ebccb767002fcf663ca9 \ + --hash=sha256:65ba8603753cec91c71de423a943ba506363b0e5c3fdb913ef8f9caa14b2c7e0 \ + --hash=sha256:687ea9d78a4b1cf82f8479cab23678aff723108df3edeac098e5b2498879f4a7 \ + --hash=sha256:6b2675068c8b56f6bfd5a2bda55b8accbb96c02fd563704732fd1c95e2083461 \ + --hash=sha256:7117d10690c38a622e54c432dfbbd3cbd92f09401d622902c32f6d377e2300ee \ + --hash=sha256:7178bbc1b2ec40eaca599d13c092079bf529679bf0371c602edaa555e10b41c3 \ + --hash=sha256:72d1a25bf36d2050ceb35b517afe13864865268dfb45910e2e17a84be6cbfeb0 \ + --hash=sha256:742e19a90d9bb2f4a6cf2862b8b06dea5e09b96c9f2df1779e53432d7275331f \ + --hash=sha256:74390d18c75054947e4194019077e243c06fbb62e541d8817a0fa822ea310c14 \ + --hash=sha256:74419d2b50ecb98360cfaa2974da8689cb3b45b9deff0dcf489c0d333bcc1477 \ + --hash=sha256:824bf3ac11001849aec3fa1d69abcb67aac3e150a933963fb12bda5151fe1bfd \ + --hash=sha256:83320a09188e0e6c39088355d423aa9d056ad57a0b6c6381b300ec1a04ec3d16 \ + --hash=sha256:837328d14cde912af625d5f303ec29f7e28cdab588674897baafaf505341f2fc \ + --hash=sha256:841d6e0e5663d4c7b4c8099c9997be748677d46cbf43f9f471150e560791f7ff \ + --hash=sha256:87b2a5bb5e78ee0ad1de71c664d6eb536dc3947a46a69182a90f4410f5e3f7dd \ + --hash=sha256:890e5a11c97cf0d0c550eb661b937a1e45431ffa79803b942a057c4fb12a2da2 \ + --hash=sha256:8abbc5d54ea0ee80e37fef009e3cec5dafd722ed3c829126253d3e22f3846f1e \ + --hash=sha256:8e3f1316c2293e5469f8f09dc2d76efb6c3982d3da91ba95061a7e69489a14ef \ + --hash=sha256:8f56fcb7ff7bf7404becdfc60b1e81a6d0561807051fd2f1860b0d0348156a07 \ + --hash=sha256:9427a399501818a7564f8c90eced1e9e20709ece36be701f394ada99890ea4b3 \ + --hash=sha256:976d7a304b59ede34ca2921305b57356694f9e6879db323fd90a80f865d355a3 \ + --hash=sha256:9a5bfb3004f2144a084a16ce19ca56b8ac46e6fd0651f54269fc9e230edb5e4a \ + --hash=sha256:9beb322958aaca059f34975b0df135181f2e5d7a13b84d3e0e45434749cb20f7 \ + --hash=sha256:9edcbad1f8a407e450fbac88d89e04e0b99a08473f666a3f3de0fd292badb6aa \ + --hash=sha256:9edce5281f965cf135e19840f4d93d55b3835122aa76ccacfd389e880ba4cf82 \ + --hash=sha256:a4c3b7fa4cdaa69268748665a1a6ff70c014d39bb69c50fda64b396c9116cf77 \ + --hash=sha256:a8105e9af3b029f243ab11ad47c19b566482c150c754e4c717900a798806b222 \ + --hash=sha256:a99b50300df5add73d307cf66abea093304a07eb017bce94f01e795090dea87c \ + --hash=sha256:aad51907d74fc183033ad796dd4c2e080d1adcc4fd3c0fd4fd499f30c03011cd \ + --hash=sha256:af4dd387354dc83a3bff67127a124c21116feb0d2ef536805c454721c5d7993d \ + --hash=sha256:b28f5024a3a041009eb4c333863d7894d191215b39576535c6734cd88b0fcb68 \ + --hash=sha256:b4598b1897837067a57b08147a68ac026c1e73b31ef6e36deeeb1fa60b2933c9 \ + --hash=sha256:b6192d5af2ccd2a38877bfef086d35e6659566a335b1492786ff254c168b1693 \ + --hash=sha256:b862c2b9d5ae38a68b92e215b93f98d4c5e9454fa36aae4450f61dd33ff48487 \ + --hash=sha256:b956231ebdc45f5b7a2e1f90f66a12be9610ce775fe1b1d50414aac1e9206c06 \ + --hash=sha256:bb60b503ec8a6e4e3e03a681072fa3a5adcbfa5479fa2d898ae2b4a8e24c4591 \ + --hash=sha256:bbb02fd4462f37060122e5acacec78e49c0fbb303c30dd49c7f493cf21fc5b27 \ + --hash=sha256:bdff5eab10e59cf26bc479f565e25ed71a7d041d1ded04ccf9aee1d9f208487a \ + --hash=sha256:c123f662be8ec5ab4ea72ea300359023a5d1df095b7ead76fedcd8babbedf969 \ + --hash=sha256:c2b867c17a7a7ae44c43ebbeb1b5ff406b3e8d5b3e14662683e5e66e6cc868d3 \ + --hash=sha256:c5f8037000eb21e4823aa485149f2299eb589f8d1fe4b448036d230c3f4e68e0 \ + --hash=sha256:c6a57b742133830eec44d9b2290daf5cbe0a2f1d6acee1b3c7b1c7b2f3606df7 \ + --hash=sha256:ccf91346b7bd20c790310c4147eee6ed495a54ddb6737162a36ce9dbef3e4751 \ + --hash=sha256:cf67ca618b4fd34aee78740bea954d7c69fdda419eb208c2c0c7060bb822d747 \ + --hash=sha256:d2da3abc88711bce7557412310dfa50327d5769a31d1c894b58eb256459dc289 \ + --hash=sha256:d4f03bb71d482f979bda92e1427f3ec9b220e62a7dd337af0aa6b47bf4498f72 \ + --hash=sha256:d54af539295392611e7efbe94e827311eb8b29668e2b3f4cadcfe6f46df9c777 \ + --hash=sha256:d77f09bc4b55d4bf7cc5eba785d87001d6757b7c9eec237fe2af57aba1a071d9 \ + --hash=sha256:d831c2f8ff278179705ca59f7e8524069c1a989e716a1874d6d1aab6119d91d1 \ + --hash=sha256:dbbbfce33cd98f97f6bffb17801b0576e653f4fdb1d399b2ea89638bc8d08ae1 \ + --hash=sha256:dcba6dae7de533c876255317c11f3abe4907ba7d9aa15d13e3d9710d4315ec0e \ + --hash=sha256:e0bb18053dfcfed432cc3ac632b5e5e5c5b7e55fb3f8090e867bfd9b054dbcbf \ + --hash=sha256:e2fbd6236aae3b7f9d514312cdb58e6494ee1c76a9948adde6eba33eb1c4264f \ + --hash=sha256:e5087a3c59eef624a4591ef9eaa6e9a8d8a94c779dade95d27c0bc24650261cd \ + --hash=sha256:e8915cc96abeb8983cea1df3c939e3c6e1ac778340c17732eb63bb96247b91d2 \ + --hash=sha256:ea353ecb6ab5f7e7d2f4372b1e779796ebd7b37352d290096978fea83c4dba0c \ + --hash=sha256:ee2d1a9a253b1729bb2de27d41f696ae893507c7db224436abe83ee25356f5c1 \ + --hash=sha256:f415f802fbcafed5dcc694c13b1292f07fe0befdb94aa8a52905bd115ff41e88 \ + --hash=sha256:fb5ec16523dc573a4b277663a2b5a364e2099902d3944c9419a40ebd56a118f9 \ + --hash=sha256:fea75c3710d4f31389eed3c02f62d0b66a9da282521075061ce875eb5300cf23 # via # aws-sam-cli (setup.py) # cfn-lint @@ -749,9 +749,9 @@ tomlkit==0.11.8 \ --hash=sha256:8c726c4c202bdb148667835f68d68780b9a003a9ec34167b6c673b38eff2a171 \ --hash=sha256:9330fc7faa1db67b541b28e62018c17d20be733177d290a13b24c62d1614e0c3 # via aws-sam-cli (setup.py) -types-awscrt==0.16.26 \ - --hash=sha256:011b0efc054cddb542416f4a38452a3cab3f2d6cef7af0cd124c03a89634f101 \ - --hash=sha256:47bcfd741465196e000e5a29ea98516765d2e93803d3fb67f9d6be79a632ee98 +types-awscrt==0.17.0 \ + --hash=sha256:278c1a913098e226769cd28dc37643a2f360907353a7e8918e1bcdf93d4e34f2 \ + --hash=sha256:4214783a747af900a5f98ec020d52ecae5910b470fd636813637a45b82a97516 # via # botocore-stubs # types-s3transfer @@ -772,9 +772,9 @@ tzlocal==3.0 \ # via # aws-sam-cli (setup.py) # dateparser -urllib3==1.26.15 \ - --hash=sha256:8a388717b9476f934a21484e8c8e61875ab60644d29b9b39e11e4b9dc1c6b305 \ - --hash=sha256:aa751d169e23c7479ce47a0cb0da579e3ede798f994f5816a74e4f4500dcea42 +urllib3==1.26.16 \ + --hash=sha256:8d36afa7616d8ab714608411b4a3b13e58f463aee519024578e062e141dce20f \ + --hash=sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14 # via # botocore # docker @@ -806,9 +806,9 @@ werkzeug==2.3.6 \ --hash=sha256:935539fa1413afbb9195b24880778422ed620c0fc09670945185cce4d91a8890 \ --hash=sha256:98c774df2f91b05550078891dee5f0eb0cb797a522c757a2452b9cee5b202330 # via flask -wheel==0.40.0 \ - --hash=sha256:cd1196f3faee2b31968d626e1731c94f99cbdb67cf5a46e4f5656cbee7738873 \ - --hash=sha256:d236b20e7cb522daf2390fa84c55eea81c5c30190f90f29ae2ca1ad8355bf247 +wheel==0.41.0 \ + --hash=sha256:55a0f0a5a84869bce5ba775abfd9c462e3a6b1b7b7ec69d72c0b83d673a5114d \ + --hash=sha256:7e9be3bbd0078f6147d82ed9ed957e323e7708f57e134743d2edef3a7b7972a9 # via aws-lambda-builders # The following packages are considered to be unsafe in a requirements file: diff --git a/requirements/reproducible-mac.txt b/requirements/reproducible-mac.txt index 718796b407..86f4095038 100644 --- a/requirements/reproducible-mac.txt +++ b/requirements/reproducible-mac.txt @@ -47,9 +47,9 @@ binaryornot==0.4.4 \ --hash=sha256:359501dfc9d40632edc9fac890e19542db1a287bbcfa58175b66658392018061 \ --hash=sha256:b8b71173c917bddcd2c16070412e369c3ed7f0528926f70cac18a6c97fd563e4 # via cookiecutter -boto3==1.28.2 \ - --hash=sha256:0d53fe604dc30edded21906bc56b30a7684f0715f4f6897307d53f8184997368 \ - --hash=sha256:9933e40dc9ac72deac45cecce2df020e3bf8d0d537538d2b361c17d1cee807cc +boto3==1.28.17 \ + --hash=sha256:90f7cfb5e1821af95b1fc084bc50e6c47fa3edc99f32de1a2591faa0c546bea7 \ + --hash=sha256:bca0526f819e0f19c0f1e6eba3e2d1d6b6a92a45129f98c0d716e5aab6d9444b # via # aws-sam-cli (setup.py) # aws-sam-translator @@ -57,15 +57,15 @@ boto3-stubs[apigateway,cloudformation,ecr,iam,lambda,s3,schemas,secretsmanager,s --hash=sha256:b140f56315cd99c659a2cbae32dc4ae1ee44073b4250e1ad391d03ecf4b5eb40 \ --hash=sha256:bcef1fcbd758de6078e75b036d3632dd95eaef00311e6688554b5b883a194563 # via aws-sam-cli (setup.py) -botocore==1.31.7 \ - --hash=sha256:f211ef5714bec8ae24b3fe737b8689611ef4d0dbea0ab46ef8328e112dd10ada \ - --hash=sha256:f4473f66c153c262b8262404d737f4249366daf00fb068b495577a24b830ebcb +botocore==1.31.17 \ + --hash=sha256:396459065dba4339eb4da4ec8b4e6599728eb89b7caaceea199e26f7d824a41c \ + --hash=sha256:6ac34a1d34aa3750e78b77b8596617e2bab938964694d651939dba2cbde2c12b # via # boto3 # s3transfer -botocore-stubs==1.31.12.post1 \ - --hash=sha256:aee5472654fbc0a0e6a78971d9918e71a3f3f48bc0f4f65116576ac6df796c49 \ - --hash=sha256:f3764c25bac463fe3c67b2d1c983dfebd4aae05ada94d41def2675e09dee970c +botocore-stubs==1.31.17 \ + --hash=sha256:0ccba9a9cee311e354c164fa8e8044a4b4150d7e536f0f09ae37637950391fbc \ + --hash=sha256:4a5c9415bd82fc22ad9b2e298022c96065ca1f330fc48b145fc1daa25fe10ff8 # via boto3-stubs certifi==2023.7.22 \ --hash=sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082 \ @@ -141,86 +141,86 @@ cfn-lint==0.79.5 \ --hash=sha256:3054a2e407f77b3115c41de49fe2c11d728d53ab7be4ae478c1b5ff0e21331b7 \ --hash=sha256:7a00dba8f70b8a92c38bfc8f45e2ab20cedad5c49054a46f1ce931e48fc1cd0c # via aws-sam-cli (setup.py) -chardet==5.1.0 \ - --hash=sha256:0d62712b956bc154f85fb0a266e2a3c5913c2967e00348701b32411d6def31e5 \ - --hash=sha256:362777fb014af596ad31334fde1e8c327dfdb076e1960d1694662d46a6917ab9 +chardet==5.2.0 \ + --hash=sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7 \ + --hash=sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970 # via binaryornot -charset-normalizer==3.1.0 \ - --hash=sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6 \ - --hash=sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1 \ - --hash=sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e \ - --hash=sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373 \ - --hash=sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62 \ - --hash=sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230 \ - --hash=sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be \ - --hash=sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c \ - --hash=sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0 \ - --hash=sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448 \ - --hash=sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f \ - --hash=sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649 \ - --hash=sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d \ - --hash=sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0 \ - --hash=sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706 \ - --hash=sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a \ - --hash=sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59 \ - --hash=sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23 \ - --hash=sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5 \ - --hash=sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb \ - --hash=sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e \ - --hash=sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e \ - --hash=sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c \ - --hash=sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28 \ - --hash=sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d \ - --hash=sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41 \ - --hash=sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974 \ - --hash=sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce \ - --hash=sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f \ - --hash=sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1 \ - --hash=sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d \ - --hash=sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8 \ - --hash=sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017 \ - --hash=sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31 \ - --hash=sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7 \ - --hash=sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8 \ - --hash=sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e \ - --hash=sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14 \ - --hash=sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd \ - --hash=sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d \ - --hash=sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795 \ - --hash=sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b \ - --hash=sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b \ - --hash=sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b \ - --hash=sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203 \ - --hash=sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f \ - --hash=sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19 \ - --hash=sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1 \ - --hash=sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a \ - --hash=sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac \ - --hash=sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9 \ - --hash=sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0 \ - --hash=sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137 \ - --hash=sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f \ - --hash=sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6 \ - --hash=sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5 \ - --hash=sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909 \ - --hash=sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f \ - --hash=sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0 \ - --hash=sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324 \ - --hash=sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755 \ - --hash=sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb \ - --hash=sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854 \ - --hash=sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c \ - --hash=sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60 \ - --hash=sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84 \ - --hash=sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0 \ - --hash=sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b \ - --hash=sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1 \ - --hash=sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531 \ - --hash=sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1 \ - --hash=sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11 \ - --hash=sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326 \ - --hash=sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df \ - --hash=sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab +charset-normalizer==3.2.0 \ + --hash=sha256:04e57ab9fbf9607b77f7d057974694b4f6b142da9ed4a199859d9d4d5c63fe96 \ + --hash=sha256:09393e1b2a9461950b1c9a45d5fd251dc7c6f228acab64da1c9c0165d9c7765c \ + --hash=sha256:0b87549028f680ca955556e3bd57013ab47474c3124dc069faa0b6545b6c9710 \ + --hash=sha256:1000fba1057b92a65daec275aec30586c3de2401ccdcd41f8a5c1e2c87078706 \ + --hash=sha256:1249cbbf3d3b04902ff081ffbb33ce3377fa6e4c7356f759f3cd076cc138d020 \ + --hash=sha256:1920d4ff15ce893210c1f0c0e9d19bfbecb7983c76b33f046c13a8ffbd570252 \ + --hash=sha256:193cbc708ea3aca45e7221ae58f0fd63f933753a9bfb498a3b474878f12caaad \ + --hash=sha256:1a100c6d595a7f316f1b6f01d20815d916e75ff98c27a01ae817439ea7726329 \ + --hash=sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a \ + --hash=sha256:203f0c8871d5a7987be20c72442488a0b8cfd0f43b7973771640fc593f56321f \ + --hash=sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6 \ + --hash=sha256:2dee8e57f052ef5353cf608e0b4c871aee320dd1b87d351c28764fc0ca55f9f4 \ + --hash=sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a \ + --hash=sha256:2f4ac36d8e2b4cc1aa71df3dd84ff8efbe3bfb97ac41242fbcfc053c67434f46 \ + --hash=sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2 \ + --hash=sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23 \ + --hash=sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace \ + --hash=sha256:3bb7fda7260735efe66d5107fb7e6af6a7c04c7fce9b2514e04b7a74b06bf5dd \ + --hash=sha256:41b25eaa7d15909cf3ac4c96088c1f266a9a93ec44f87f1d13d4a0e86c81b982 \ + --hash=sha256:45de3f87179c1823e6d9e32156fb14c1927fcc9aba21433f088fdfb555b77c10 \ + --hash=sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2 \ + --hash=sha256:48021783bdf96e3d6de03a6e39a1171ed5bd7e8bb93fc84cc649d11490f87cea \ + --hash=sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09 \ + --hash=sha256:5e86d77b090dbddbe78867a0275cb4df08ea195e660f1f7f13435a4649e954e5 \ + --hash=sha256:6339d047dab2780cc6220f46306628e04d9750f02f983ddb37439ca47ced7149 \ + --hash=sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489 \ + --hash=sha256:6c409c0deba34f147f77efaa67b8e4bb83d2f11c8806405f76397ae5b8c0d1c9 \ + --hash=sha256:7095f6fbfaa55defb6b733cfeb14efaae7a29f0b59d8cf213be4e7ca0b857b80 \ + --hash=sha256:70c610f6cbe4b9fce272c407dd9d07e33e6bf7b4aa1b7ffb6f6ded8e634e3592 \ + --hash=sha256:72814c01533f51d68702802d74f77ea026b5ec52793c791e2da806a3844a46c3 \ + --hash=sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6 \ + --hash=sha256:7c70087bfee18a42b4040bb9ec1ca15a08242cf5867c58726530bdf3945672ed \ + --hash=sha256:855eafa5d5a2034b4621c74925d89c5efef61418570e5ef9b37717d9c796419c \ + --hash=sha256:8700f06d0ce6f128de3ccdbc1acaea1ee264d2caa9ca05daaf492fde7c2a7200 \ + --hash=sha256:89f1b185a01fe560bc8ae5f619e924407efca2191b56ce749ec84982fc59a32a \ + --hash=sha256:8b2c760cfc7042b27ebdb4a43a4453bd829a5742503599144d54a032c5dc7e9e \ + --hash=sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d \ + --hash=sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6 \ + --hash=sha256:94aea8eff76ee6d1cdacb07dd2123a68283cb5569e0250feab1240058f53b623 \ + --hash=sha256:95eb302ff792e12aba9a8b8f8474ab229a83c103d74a750ec0bd1c1eea32e669 \ + --hash=sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3 \ + --hash=sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa \ + --hash=sha256:a103b3a7069b62f5d4890ae1b8f0597618f628b286b03d4bc9195230b154bfa9 \ + --hash=sha256:a386ebe437176aab38c041de1260cd3ea459c6ce5263594399880bbc398225b2 \ + --hash=sha256:a38856a971c602f98472050165cea2cdc97709240373041b69030be15047691f \ + --hash=sha256:a401b4598e5d3f4a9a811f3daf42ee2291790c7f9d74b18d75d6e21dda98a1a1 \ + --hash=sha256:a7647ebdfb9682b7bb97e2a5e7cb6ae735b1c25008a70b906aecca294ee96cf4 \ + --hash=sha256:aaf63899c94de41fe3cf934601b0f7ccb6b428c6e4eeb80da72c58eab077b19a \ + --hash=sha256:b0dac0ff919ba34d4df1b6131f59ce95b08b9065233446be7e459f95554c0dc8 \ + --hash=sha256:baacc6aee0b2ef6f3d308e197b5d7a81c0e70b06beae1f1fcacffdbd124fe0e3 \ + --hash=sha256:bf420121d4c8dce6b889f0e8e4ec0ca34b7f40186203f06a946fa0276ba54029 \ + --hash=sha256:c04a46716adde8d927adb9457bbe39cf473e1e2c2f5d0a16ceb837e5d841ad4f \ + --hash=sha256:c0b21078a4b56965e2b12f247467b234734491897e99c1d51cee628da9786959 \ + --hash=sha256:c1c76a1743432b4b60ab3358c937a3fe1341c828ae6194108a94c69028247f22 \ + --hash=sha256:c4983bf937209c57240cff65906b18bb35e64ae872da6a0db937d7b4af845dd7 \ + --hash=sha256:c4fb39a81950ec280984b3a44f5bd12819953dc5fa3a7e6fa7a80db5ee853952 \ + --hash=sha256:c57921cda3a80d0f2b8aec7e25c8aa14479ea92b5b51b6876d975d925a2ea346 \ + --hash=sha256:c8063cf17b19661471ecbdb3df1c84f24ad2e389e326ccaf89e3fb2484d8dd7e \ + --hash=sha256:ccd16eb18a849fd8dcb23e23380e2f0a354e8daa0c984b8a732d9cfaba3a776d \ + --hash=sha256:cd6dbe0238f7743d0efe563ab46294f54f9bc8f4b9bcf57c3c666cc5bc9d1299 \ + --hash=sha256:d62e51710986674142526ab9f78663ca2b0726066ae26b78b22e0f5e571238dd \ + --hash=sha256:db901e2ac34c931d73054d9797383d0f8009991e723dab15109740a63e7f902a \ + --hash=sha256:e03b8895a6990c9ab2cdcd0f2fe44088ca1c65ae592b8f795c3294af00a461c3 \ + --hash=sha256:e1c8a2f4c69e08e89632defbfabec2feb8a8d99edc9f89ce33c4b9e36ab63037 \ + --hash=sha256:e4b749b9cc6ee664a3300bb3a273c1ca8068c46be705b6c31cf5d276f8628a94 \ + --hash=sha256:e6a5bf2cba5ae1bb80b154ed68a3cfa2fa00fde979a7f50d6598d3e17d9ac20c \ + --hash=sha256:e857a2232ba53ae940d3456f7533ce6ca98b81917d47adc3c7fd55dad8fab858 \ + --hash=sha256:ee4006268ed33370957f55bf2e6f4d263eaf4dc3cfc473d1d90baff6ed36ce4a \ + --hash=sha256:eef9df1eefada2c09a5e7a40991b9fc6ac6ef20b1372abd48d2794a316dc0449 \ + --hash=sha256:f058f6963fd82eb143c692cecdc89e075fa0828db2e5b291070485390b2f1c9c \ + --hash=sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918 \ + --hash=sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1 \ + --hash=sha256:f7560358a6811e52e9c4d142d497f1a6e10103d3a6881f18d04dbce3729c0e2c \ + --hash=sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac \ + --hash=sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa # via requests chevron==0.14.0 \ --hash=sha256:87613aafdf6d77b6a90ff073165a61ae5086e21ad49057aa0e53681601800ebf \ @@ -312,17 +312,17 @@ jschema-to-python==1.2.3 \ --hash=sha256:76ff14fe5d304708ccad1284e4b11f96a658949a31ee7faed9e0995279549b91 \ --hash=sha256:8a703ca7604d42d74b2815eecf99a33359a8dccbb80806cce386d5e2dd992b05 # via cfn-lint -jsonpatch==1.32 \ - --hash=sha256:26ac385719ac9f54df8a2f0827bb8253aa3ea8ab7b3368457bcdb8c14595a397 \ - --hash=sha256:b6ddfe6c3db30d81a96aaeceb6baf916094ffa23d7dd5fa2c13e13f8b6e600c2 +jsonpatch==1.33 \ + --hash=sha256:0ae28c0cd062bbd8b8ecc26d7d164fbbea9652a1a3693f3b956c1eae5145dade \ + --hash=sha256:9fcd4009c41e6d12348b4a0ff2563ba56a2923a7dfee731d004e212e1ee5030c # via cfn-lint jsonpickle==3.0.1 \ --hash=sha256:032538804795e73b94ead410800ac387fdb6de98f8882ac957fcd247e3a85200 \ --hash=sha256:130d8b293ea0add3845de311aaba55e6d706d0bb17bc123bd2c8baf8a39ac77c # via jschema-to-python -jsonpointer==2.3 \ - --hash=sha256:51801e558539b4e9cd268638c078c6c5746c9ac96bc38152d443400e4f3793e9 \ - --hash=sha256:97cba51526c829282218feb99dab1b1e6bdf8efd1c43dc9d57be093c0d69c99a +jsonpointer==2.4 \ + --hash=sha256:15d51bba20eea3165644553647711d150376234112651b4f1811022aecad7d7a \ + --hash=sha256:585cee82b70211fa9e6043b7bb89db6e1aa49524340dde8ad6b63206ea689d88 # via jsonpatch jsonschema==4.17.3 \ --hash=sha256:0f864437ab8b6076ba6707453ef8f98a6a0d512a80e93f8abdb676f737ecb60d \ @@ -401,53 +401,53 @@ mpmath==1.3.0 \ --hash=sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f \ --hash=sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c # via sympy -mypy-boto3-apigateway==1.28.12 \ - --hash=sha256:83d7e8b5f07952992f36c6ec021d0a8abe0d107943a6a178c53c444f269094c9 \ - --hash=sha256:a580a886d93658fb0f056d576615fe8de2b0a1fb7239c2b1c918080b0be2d1bb +mypy-boto3-apigateway==1.28.16 \ + --hash=sha256:4193124b6ab5b92de0affdd59f1485a17d68ecefff17b411f73a08ea5d5db92d \ + --hash=sha256:82491d942530ab9dabc4c811e188c6ab546c3e658c5718bab58fb45cadef6d0b # via boto3-stubs -mypy-boto3-cloudformation==1.28.0 \ - --hash=sha256:0d2ead02c352bc97ae59b65ae8b00d5ce186435b7cf5736213a52f58df192511 \ - --hash=sha256:99d5db7d6b220ba016757670a917bdfdab1c475593153833ed6c5cdd9a9aa9ba +mypy-boto3-cloudformation==1.28.16 \ + --hash=sha256:228cb6e9096f64d36abd912c34e465545ff848bb837498112dc30235ca19750c \ + --hash=sha256:a5202db1ea76aa499a27b971745e0130e5cb88c2b323c48cca30cd01713d963a # via boto3-stubs -mypy-boto3-ecr==1.28.0 \ - --hash=sha256:46b493af9024e230f7b81c7dc1ca2b52d5cca168f867be60a55ce0b86a3999f7 \ - --hash=sha256:d4cbad3f4d33abbfe0a7d7504b38f01d256c5200d754b5289d1f373bcd595bf4 +mypy-boto3-ecr==1.28.16 \ + --hash=sha256:412aa7e26d20e7502267e5fec4d94f0bc48db0ced24f65d207911fe70585a4cd \ + --hash=sha256:b3252c5eda47ca1e90980e0158410e8a76c8acdfbda0907f545ddfddaea95258 # via boto3-stubs -mypy-boto3-iam==1.28.3.post2 \ - --hash=sha256:16d642b5507067bd2cfae5e3fd149b9ccf7070bc98e7214058cae40c478eaccf \ - --hash=sha256:32ed5e5d961d628c0f5bad06e3b3342df6d3bec0d9a6dd5d746fce53a7d5f6dc +mypy-boto3-iam==1.28.16 \ + --hash=sha256:1416df5e838be7cc8b65def4721097faf691f8f0c65f58fe417d18b9e6b8de61 \ + --hash=sha256:8ef9ef9a9fabcc1058a46bbd6b1408960a70d72e45a024862676e5a896c446b3 # via boto3-stubs -mypy-boto3-lambda==1.28.0 \ - --hash=sha256:5fd38df6418829b2f3a184918fc8ad1d49b6738509f1832cdc71f33588efbdfb \ - --hash=sha256:a3abaf98e514f2cabed2cf0b1e77c94c81f0fbbba8a549b3c073577a9f9ac196 +mypy-boto3-lambda==1.28.16 \ + --hash=sha256:c1b688c1ea7cbb9b79b8a1dcaaa7459791ae7ebc608490251f58a07edb31170c \ + --hash=sha256:c7c647139e6710da694aba4a644f69f4a06c6e43419168d69cc57f3dc6e5e607 # via boto3-stubs -mypy-boto3-s3==1.28.3.post2 \ - --hash=sha256:02dc6b9edf799afa160be1e3a9b38a383af6fcd80a97abd75d09410b26621e70 \ - --hash=sha256:c23b7802b80a0388a146d7e8025552f21d44e349026a18fb751d9c698ed714b1 +mypy-boto3-s3==1.28.16 \ + --hash=sha256:4e55fdad729b6e6f45211e354bd1a0a745a565fe9d1e462737f775c28849cfb5 \ + --hash=sha256:855f7848186c45adbd3c474fec2d75db17f4cd7200c0a2235473250454ec4686 # via boto3-stubs -mypy-boto3-schemas==1.28.0 \ - --hash=sha256:371972ab1301f03cb504ea16a0aa566e9c889a436b5b1a221c15d04f5710f47f \ - --hash=sha256:d15c838e812a8e1b20c7a6ce7d794231e1d9cc73b65cbbf9385f3d2984f4e929 +mypy-boto3-schemas==1.28.16 \ + --hash=sha256:4f4b4fc784452b5186ab31199e4cb5546d314f3fc666cb698c960ba89e33448e \ + --hash=sha256:7898f9624af46be956bd8e1dffc6fc01d6e2141e067444156bddd2c412ef8084 # via boto3-stubs -mypy-boto3-secretsmanager==1.28.3.post2 \ - --hash=sha256:3a5e5619ee945f244d2dfefcb382c85874171a18b46f75403465622095284d25 \ - --hash=sha256:f359f6446ac856d0887e40cb0f5bc6e0a60873524be5dd4b68be1d0fc4ac513e +mypy-boto3-secretsmanager==1.28.16 \ + --hash=sha256:05508c3a96d96e482e5aff21b508319a1911e6662aea5be96aa7f7089b8dbfd4 \ + --hash=sha256:07f443b31d2114ac363cfbdbc5f4b97934ca48fb99734bbd06d5c39bce244b83 # via boto3-stubs -mypy-boto3-signer==1.28.0 \ - --hash=sha256:55288fed77e2ae3121c4ecb15b64d4cc3984f069ff4671d5dbd9b14fc9b6f5f1 \ - --hash=sha256:c24d4fd291b194248c61f7696d1bb56c5e8db13f792dff1720126c208f922539 +mypy-boto3-signer==1.28.16 \ + --hash=sha256:78d9bacf72b865221c6d11a946a0d6aad3b14904475c886fafd08cd1dd54c5d7 \ + --hash=sha256:a67206f20189105a24deee995ab130123fa1af75c39c13c17e404ff74b9ec1fc # via boto3-stubs -mypy-boto3-stepfunctions==1.28.0 \ - --hash=sha256:47ab107c76513a04d241357157ee6886c3e8b7965ccd7fcce66ec44efbd2b43a \ - --hash=sha256:7a3f702287ae4d311ffa34643318257c9dbf25490131d244e1e085c222c33465 +mypy-boto3-stepfunctions==1.28.16 \ + --hash=sha256:8b2b6578ca38dc0f13d73292b92afd7f3cf11a8999a33886d4c4ab6822f0020a \ + --hash=sha256:962c80b1bac778b64c6334df50a3860bf4d0a5d17560fac765e7913615926b2b # via boto3-stubs -mypy-boto3-sts==1.28.0 \ - --hash=sha256:161acaf4ac14282f3a1accfe06e372b1ee902840d32c2bad4e4eebbf7dd66607 \ - --hash=sha256:81daa1e27e1c07b70eccc8de8d95f2676593dd6f7fd217a22f269d94b9b81e36 +mypy-boto3-sts==1.28.16 \ + --hash=sha256:7cd388a7451611813730b83c78179759eb5701b849618d82c3ec7e95576bedb9 \ + --hash=sha256:a00bc7f69d8675058db0fb2c39d4d9dbb3a3c14ae1d0d83fbf930a2a0498629a # via boto3-stubs -mypy-boto3-xray==1.28.0 \ - --hash=sha256:64cd601a829c274665b977853f85b27464986e9eec1ebc03f5bc4530a400b2f6 \ - --hash=sha256:8ce07598f7eeabe66e8dc8cb7e906efb96198b9102f58e9315e6daf166abf3e7 +mypy-boto3-xray==1.28.16 \ + --hash=sha256:4bc7dfd46cb71ca6a9d46b47453d59a08ac80c872cc429dacb45a93abd737172 \ + --hash=sha256:6ddd4acccf272bf663522c5fcd31b9b7dacbed4a01c91e44e4e8c0abb2343c0a # via boto3-stubs networkx==3.1 \ --hash=sha256:4f33f68cb2afcf86f28a45f43efc27a9386b535d567d2127f8f61d51dec58d36 \ @@ -471,43 +471,43 @@ pycparser==2.21 \ --hash=sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9 \ --hash=sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206 # via cffi -pydantic==1.10.8 \ - --hash=sha256:052d8654cb65174d6f9490cc9b9a200083a82cf5c3c5d3985db765757eb3b375 \ - --hash=sha256:0c6fafa0965b539d7aab0a673a046466d23b86e4b0e8019d25fd53f4df62c277 \ - --hash=sha256:1243d28e9b05003a89d72e7915fdb26ffd1d39bdd39b00b7dbe4afae4b557f9d \ - --hash=sha256:12f7b0bf8553e310e530e9f3a2f5734c68699f42218bf3568ef49cd9b0e44df4 \ - --hash=sha256:1410275520dfa70effadf4c21811d755e7ef9bb1f1d077a21958153a92c8d9ca \ - --hash=sha256:16f8c3e33af1e9bb16c7a91fc7d5fa9fe27298e9f299cff6cb744d89d573d62c \ - --hash=sha256:17aef11cc1b997f9d574b91909fed40761e13fac438d72b81f902226a69dac01 \ - --hash=sha256:191ba419b605f897ede9892f6c56fb182f40a15d309ef0142212200a10af4c18 \ - --hash=sha256:1952526ba40b220b912cdc43c1c32bcf4a58e3f192fa313ee665916b26befb68 \ - --hash=sha256:1ced8375969673929809d7f36ad322934c35de4af3b5e5b09ec967c21f9f7887 \ - --hash=sha256:2e4148e635994d57d834be1182a44bdb07dd867fa3c2d1b37002000646cc5459 \ - --hash=sha256:34d327c81e68a1ecb52fe9c8d50c8a9b3e90d3c8ad991bfc8f953fb477d42fb4 \ - --hash=sha256:35db5301b82e8661fa9c505c800d0990bc14e9f36f98932bb1d248c0ac5cada5 \ - --hash=sha256:3e59417ba8a17265e632af99cc5f35ec309de5980c440c255ab1ca3ae96a3e0e \ - --hash=sha256:42aa0c4b5c3025483240a25b09f3c09a189481ddda2ea3a831a9d25f444e03c1 \ - --hash=sha256:666bdf6066bf6dbc107b30d034615d2627e2121506c555f73f90b54a463d1f33 \ - --hash=sha256:66a703d1983c675a6e0fed8953b0971c44dba48a929a2000a493c3772eb61a5a \ - --hash=sha256:6a82d6cda82258efca32b40040228ecf43a548671cb174a1e81477195ed3ed56 \ - --hash=sha256:6f2e754d5566f050954727c77f094e01793bcb5725b663bf628fa6743a5a9108 \ - --hash=sha256:7456eb22ed9aaa24ff3e7b4757da20d9e5ce2a81018c1b3ebd81a0b88a18f3b2 \ - --hash=sha256:7b1f6cb446470b7ddf86c2e57cd119a24959af2b01e552f60705910663af09a4 \ - --hash=sha256:7d5b8641c24886d764a74ec541d2fc2c7fb19f6da2a4001e6d580ba4a38f7878 \ - --hash=sha256:84d80219c3f8d4cad44575e18404099c76851bc924ce5ab1c4c8bb5e2a2227d0 \ - --hash=sha256:88f195f582851e8db960b4a94c3e3ad25692c1c1539e2552f3df7a9e972ef60e \ - --hash=sha256:93e6bcfccbd831894a6a434b0aeb1947f9e70b7468f274154d03d71fabb1d7c6 \ - --hash=sha256:93e766b4a8226e0708ef243e843105bf124e21331694367f95f4e3b4a92bbb3f \ - --hash=sha256:ab523c31e22943713d80d8d342d23b6f6ac4b792a1e54064a8d0cf78fd64e800 \ - --hash=sha256:bb14388ec45a7a0dc429e87def6396f9e73c8c77818c927b6a60706603d5f2ea \ - --hash=sha256:c0ab53b609c11dfc0c060d94335993cc2b95b2150e25583bec37a49b2d6c6c3f \ - --hash=sha256:c33b60054b2136aef8cf190cd4c52a3daa20b2263917c49adad20eaf381e823b \ - --hash=sha256:ceb6a23bf1ba4b837d0cfe378329ad3f351b5897c8d4914ce95b85fba96da5a1 \ - --hash=sha256:d532bf00f381bd6bc62cabc7d1372096b75a33bc197a312b03f5838b4fb84edd \ - --hash=sha256:df7800cb1984d8f6e249351139667a8c50a379009271ee6236138a22a0c0f319 \ - --hash=sha256:e82d4566fcd527eae8b244fa952d99f2ca3172b7e97add0b43e2d97ee77f81ab \ - --hash=sha256:f90c1e29f447557e9e26afb1c4dbf8768a10cc676e3781b6a577841ade126b85 \ - --hash=sha256:f9613fadad06b4f3bc5db2653ce2f22e0de84a7c6c293909b48f6ed37b83c61f +pydantic==1.10.12 \ + --hash=sha256:0fe8a415cea8f340e7a9af9c54fc71a649b43e8ca3cc732986116b3cb135d303 \ + --hash=sha256:1289c180abd4bd4555bb927c42ee42abc3aee02b0fb2d1223fb7c6e5bef87dbe \ + --hash=sha256:1eb2085c13bce1612da8537b2d90f549c8cbb05c67e8f22854e201bde5d98a47 \ + --hash=sha256:2031de0967c279df0d8a1c72b4ffc411ecd06bac607a212892757db7462fc494 \ + --hash=sha256:2a7bac939fa326db1ab741c9d7f44c565a1d1e80908b3797f7f81a4f86bc8d33 \ + --hash=sha256:2d5a58feb9a39f481eda4d5ca220aa8b9d4f21a41274760b9bc66bfd72595b86 \ + --hash=sha256:2f9a6fab5f82ada41d56b0602606a5506aab165ca54e52bc4545028382ef1c5d \ + --hash=sha256:2fcfb5296d7877af406ba1547dfde9943b1256d8928732267e2653c26938cd9c \ + --hash=sha256:549a8e3d81df0a85226963611950b12d2d334f214436a19537b2efed61b7639a \ + --hash=sha256:598da88dfa127b666852bef6d0d796573a8cf5009ffd62104094a4fe39599565 \ + --hash=sha256:5d1197e462e0364906cbc19681605cb7c036f2475c899b6f296104ad42b9f5fb \ + --hash=sha256:69328e15cfda2c392da4e713443c7dbffa1505bc9d566e71e55abe14c97ddc62 \ + --hash=sha256:6a9dfa722316f4acf4460afdf5d41d5246a80e249c7ff475c43a3a1e9d75cf62 \ + --hash=sha256:6b30bcb8cbfccfcf02acb8f1a261143fab622831d9c0989707e0e659f77a18e0 \ + --hash=sha256:6c076be61cd0177a8433c0adcb03475baf4ee91edf5a4e550161ad57fc90f523 \ + --hash=sha256:771735dc43cf8383959dc9b90aa281f0b6092321ca98677c5fb6125a6f56d58d \ + --hash=sha256:795e34e6cc065f8f498c89b894a3c6da294a936ee71e644e4bd44de048af1405 \ + --hash=sha256:87afda5539d5140cb8ba9e8b8c8865cb5b1463924d38490d73d3ccfd80896b3f \ + --hash=sha256:8fb2aa3ab3728d950bcc885a2e9eff6c8fc40bc0b7bb434e555c215491bcf48b \ + --hash=sha256:a1fcb59f2f355ec350073af41d927bf83a63b50e640f4dbaa01053a28b7a7718 \ + --hash=sha256:a5e7add47a5b5a40c49b3036d464e3c7802f8ae0d1e66035ea16aa5b7a3923ed \ + --hash=sha256:a73f489aebd0c2121ed974054cb2759af8a9f747de120acd2c3394cf84176ccb \ + --hash=sha256:ab26038b8375581dc832a63c948f261ae0aa21f1d34c1293469f135fa92972a5 \ + --hash=sha256:b0d191db0f92dfcb1dec210ca244fdae5cbe918c6050b342d619c09d31eea0cc \ + --hash=sha256:b749a43aa51e32839c9d71dc67eb1e4221bb04af1033a32e3923d46f9effa942 \ + --hash=sha256:b7ccf02d7eb340b216ec33e53a3a629856afe1c6e0ef91d84a4e6f2fb2ca70fe \ + --hash=sha256:ba5b2e6fe6ca2b7e013398bc7d7b170e21cce322d266ffcd57cca313e54fb246 \ + --hash=sha256:ba5c4a8552bff16c61882db58544116d021d0b31ee7c66958d14cf386a5b5350 \ + --hash=sha256:c79e6a11a07da7374f46970410b41d5e266f7f38f6a17a9c4823db80dadf4303 \ + --hash=sha256:ca48477862372ac3770969b9d75f1bf66131d386dba79506c46d75e6b48c1e09 \ + --hash=sha256:dea7adcc33d5d105896401a1f37d56b47d443a2b2605ff8a969a0ed5543f7e33 \ + --hash=sha256:e0a16d274b588767602b7646fa05af2782576a6cf1022f4ba74cbb4db66f6ca8 \ + --hash=sha256:e4129b528c6baa99a429f97ce733fff478ec955513630e61b49804b6cf9b224a \ + --hash=sha256:e5f805d2d5d0a41633651a73fa4ecdd0b3d7a49de4ec3fadf062fe16501ddbf1 \ + --hash=sha256:ef6c96b2baa2100ec91a4b428f80d8f28a3c9e53568219b6c298c1125572ebc6 \ + --hash=sha256:fdbdd1d630195689f325c9ef1a12900524dceb503b00a987663ff4f58669b93d # via aws-sam-translator pygments==2.15.1 \ --hash=sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c \ @@ -606,95 +606,95 @@ pyyaml==6.0.1 \ # aws-sam-cli (setup.py) # cfn-lint # cookiecutter -regex==2023.5.5 \ - --hash=sha256:02f4541550459c08fdd6f97aa4e24c6f1932eec780d58a2faa2068253df7d6ff \ - --hash=sha256:0a69cf0c00c4d4a929c6c7717fd918414cab0d6132a49a6d8fc3ded1988ed2ea \ - --hash=sha256:0bbd5dcb19603ab8d2781fac60114fb89aee8494f4505ae7ad141a3314abb1f9 \ - --hash=sha256:10250a093741ec7bf74bcd2039e697f519b028518f605ff2aa7ac1e9c9f97423 \ - --hash=sha256:10374c84ee58c44575b667310d5bbfa89fb2e64e52349720a0182c0017512f6c \ - --hash=sha256:1189fbbb21e2c117fda5303653b61905aeeeea23de4a94d400b0487eb16d2d60 \ - --hash=sha256:1307aa4daa1cbb23823d8238e1f61292fd07e4e5d8d38a6efff00b67a7cdb764 \ - --hash=sha256:144b5b017646b5a9392a5554a1e5db0000ae637be4971c9747566775fc96e1b2 \ - --hash=sha256:171c52e320fe29260da550d81c6b99f6f8402450dc7777ef5ced2e848f3b6f8f \ - --hash=sha256:18196c16a584619c7c1d843497c069955d7629ad4a3fdee240eb347f4a2c9dbe \ - --hash=sha256:18f05d14f14a812fe9723f13afafefe6b74ca042d99f8884e62dbd34dcccf3e2 \ - --hash=sha256:1ecf3dcff71f0c0fe3e555201cbe749fa66aae8d18f80d2cc4de8e66df37390a \ - --hash=sha256:21e90a288e6ba4bf44c25c6a946cb9b0f00b73044d74308b5e0afd190338297c \ - --hash=sha256:23d86ad2121b3c4fc78c58f95e19173790e22ac05996df69b84e12da5816cb17 \ - --hash=sha256:256f7f4c6ba145f62f7a441a003c94b8b1af78cee2cccacfc1e835f93bc09426 \ - --hash=sha256:290fd35219486dfbc00b0de72f455ecdd63e59b528991a6aec9fdfc0ce85672e \ - --hash=sha256:2e9c4f778514a560a9c9aa8e5538bee759b55f6c1dcd35613ad72523fd9175b8 \ - --hash=sha256:338994d3d4ca4cf12f09822e025731a5bdd3a37aaa571fa52659e85ca793fb67 \ - --hash=sha256:33d430a23b661629661f1fe8395be2004006bc792bb9fc7c53911d661b69dd7e \ - --hash=sha256:385992d5ecf1a93cb85adff2f73e0402dd9ac29b71b7006d342cc920816e6f32 \ - --hash=sha256:3d45864693351c15531f7e76f545ec35000d50848daa833cead96edae1665559 \ - --hash=sha256:40005cbd383438aecf715a7b47fe1e3dcbc889a36461ed416bdec07e0ef1db66 \ - --hash=sha256:4035d6945cb961c90c3e1c1ca2feb526175bcfed44dfb1cc77db4fdced060d3e \ - --hash=sha256:445d6f4fc3bd9fc2bf0416164454f90acab8858cd5a041403d7a11e3356980e8 \ - --hash=sha256:48c9ec56579d4ba1c88f42302194b8ae2350265cb60c64b7b9a88dcb7fbde309 \ - --hash=sha256:4a5059bd585e9e9504ef9c07e4bc15b0a621ba20504388875d66b8b30a5c4d18 \ - --hash=sha256:4a6e4b0e0531223f53bad07ddf733af490ba2b8367f62342b92b39b29f72735a \ - --hash=sha256:4b870b6f632fc74941cadc2a0f3064ed8409e6f8ee226cdfd2a85ae50473aa94 \ - --hash=sha256:50fd2d9b36938d4dcecbd684777dd12a407add4f9f934f235c66372e630772b0 \ - --hash=sha256:53e22e4460f0245b468ee645156a4f84d0fc35a12d9ba79bd7d79bdcd2f9629d \ - --hash=sha256:586a011f77f8a2da4b888774174cd266e69e917a67ba072c7fc0e91878178a80 \ - --hash=sha256:59597cd6315d3439ed4b074febe84a439c33928dd34396941b4d377692eca810 \ - --hash=sha256:59e4b729eae1a0919f9e4c0fc635fbcc9db59c74ad98d684f4877be3d2607dd6 \ - --hash=sha256:5a0f874ee8c0bc820e649c900243c6d1e6dc435b81da1492046716f14f1a2a96 \ - --hash=sha256:5ac2b7d341dc1bd102be849d6dd33b09701223a851105b2754339e390be0627a \ - --hash=sha256:5e3f4468b8c6fd2fd33c218bbd0a1559e6a6fcf185af8bb0cc43f3b5bfb7d636 \ - --hash=sha256:6164d4e2a82f9ebd7752a06bd6c504791bedc6418c0196cd0a23afb7f3e12b2d \ - --hash=sha256:6893544e06bae009916a5658ce7207e26ed17385149f35a3125f5259951f1bbe \ - --hash=sha256:690a17db524ee6ac4a27efc5406530dd90e7a7a69d8360235323d0e5dafb8f5b \ - --hash=sha256:6b8d0c153f07a953636b9cdb3011b733cadd4178123ef728ccc4d5969e67f3c2 \ - --hash=sha256:72a28979cc667e5f82ef433db009184e7ac277844eea0f7f4d254b789517941d \ - --hash=sha256:72aa4746993a28c841e05889f3f1b1e5d14df8d3daa157d6001a34c98102b393 \ - --hash=sha256:732176f5427e72fa2325b05c58ad0b45af341c459910d766f814b0584ac1f9ac \ - --hash=sha256:7918a1b83dd70dc04ab5ed24c78ae833ae8ea228cef84e08597c408286edc926 \ - --hash=sha256:7923470d6056a9590247ff729c05e8e0f06bbd4efa6569c916943cb2d9b68b91 \ - --hash=sha256:7d76a8a1fc9da08296462a18f16620ba73bcbf5909e42383b253ef34d9d5141e \ - --hash=sha256:811040d7f3dd9c55eb0d8b00b5dcb7fd9ae1761c454f444fd9f37fe5ec57143a \ - --hash=sha256:821a88b878b6589c5068f4cc2cfeb2c64e343a196bc9d7ac68ea8c2a776acd46 \ - --hash=sha256:84397d3f750d153ebd7f958efaa92b45fea170200e2df5e0e1fd4d85b7e3f58a \ - --hash=sha256:844671c9c1150fcdac46d43198364034b961bd520f2c4fdaabfc7c7d7138a2dd \ - --hash=sha256:890a09cb0a62198bff92eda98b2b507305dd3abf974778bae3287f98b48907d3 \ - --hash=sha256:8f08276466fedb9e36e5193a96cb944928301152879ec20c2d723d1031cd4ddd \ - --hash=sha256:8f5e06df94fff8c4c85f98c6487f6636848e1dc85ce17ab7d1931df4a081f657 \ - --hash=sha256:921473a93bcea4d00295799ab929522fc650e85c6b9f27ae1e6bb32a790ea7d3 \ - --hash=sha256:941b3f1b2392f0bcd6abf1bc7a322787d6db4e7457be6d1ffd3a693426a755f2 \ - --hash=sha256:9b320677521aabf666cdd6e99baee4fb5ac3996349c3b7f8e7c4eee1c00dfe3a \ - --hash=sha256:9c3efee9bb53cbe7b285760c81f28ac80dc15fa48b5fe7e58b52752e642553f1 \ - --hash=sha256:9fda3e50abad8d0f48df621cf75adc73c63f7243cbe0e3b2171392b445401550 \ - --hash=sha256:a4c5da39bca4f7979eefcbb36efea04471cd68db2d38fcbb4ee2c6d440699833 \ - --hash=sha256:a56c18f21ac98209da9c54ae3ebb3b6f6e772038681d6cb43b8d53da3b09ee81 \ - --hash=sha256:a623564d810e7a953ff1357f7799c14bc9beeab699aacc8b7ab7822da1e952b8 \ - --hash=sha256:a8906669b03c63266b6a7693d1f487b02647beb12adea20f8840c1a087e2dfb5 \ - --hash=sha256:a99757ad7fe5c8a2bb44829fc57ced11253e10f462233c1255fe03888e06bc19 \ - --hash=sha256:aa7d032c1d84726aa9edeb6accf079b4caa87151ca9fabacef31fa028186c66d \ - --hash=sha256:aad5524c2aedaf9aa14ef1bc9327f8abd915699dea457d339bebbe2f0d218f86 \ - --hash=sha256:afb1c70ec1e594a547f38ad6bf5e3d60304ce7539e677c1429eebab115bce56e \ - --hash=sha256:b6365703e8cf1644b82104cdd05270d1a9f043119a168d66c55684b1b557d008 \ - --hash=sha256:b8b942d8b3ce765dbc3b1dad0a944712a89b5de290ce8f72681e22b3c55f3cc8 \ - --hash=sha256:ba73a14e9c8f9ac409863543cde3290dba39098fc261f717dc337ea72d3ebad2 \ - --hash=sha256:bd7b68fd2e79d59d86dcbc1ccd6e2ca09c505343445daaa4e07f43c8a9cc34da \ - --hash=sha256:bd966475e963122ee0a7118ec9024388c602d12ac72860f6eea119a3928be053 \ - --hash=sha256:c2ce65bdeaf0a386bb3b533a28de3994e8e13b464ac15e1e67e4603dd88787fa \ - --hash=sha256:c64d5abe91a3dfe5ff250c6bb267ef00dbc01501518225b45a5f9def458f31fb \ - --hash=sha256:c8c143a65ce3ca42e54d8e6fcaf465b6b672ed1c6c90022794a802fb93105d22 \ - --hash=sha256:cd46f30e758629c3ee91713529cfbe107ac50d27110fdcc326a42ce2acf4dafc \ - --hash=sha256:ced02e3bd55e16e89c08bbc8128cff0884d96e7f7a5633d3dc366b6d95fcd1d6 \ - --hash=sha256:cf123225945aa58b3057d0fba67e8061c62d14cc8a4202630f8057df70189051 \ - --hash=sha256:d19e57f888b00cd04fc38f5e18d0efbd91ccba2d45039453ab2236e6eec48d4d \ - --hash=sha256:d1cbe6b5be3b9b698d8cc4ee4dee7e017ad655e83361cd0ea8e653d65e469468 \ - --hash=sha256:db09e6c18977a33fea26fe67b7a842f706c67cf8bda1450974d0ae0dd63570df \ - --hash=sha256:de2f780c3242ea114dd01f84848655356af4dd561501896c751d7b885ea6d3a1 \ - --hash=sha256:e2205a81f815b5bb17e46e74cc946c575b484e5f0acfcb805fb252d67e22938d \ - --hash=sha256:e645c757183ee0e13f0bbe56508598e2d9cd42b8abc6c0599d53b0d0b8dd1479 \ - --hash=sha256:f2910502f718828cecc8beff004917dcf577fc5f8f5dd40ffb1ea7612124547b \ - --hash=sha256:f764e4dfafa288e2eba21231f455d209f4709436baeebb05bdecfb5d8ddc3d35 \ - --hash=sha256:f83fe9e10f9d0b6cf580564d4d23845b9d692e4c91bd8be57733958e4c602956 \ - --hash=sha256:fb2b495dd94b02de8215625948132cc2ea360ae84fe6634cd19b6567709c8ae2 \ - --hash=sha256:fee0016cc35a8a91e8cc9312ab26a6fe638d484131a7afa79e1ce6165328a135 +regex==2023.6.3 \ + --hash=sha256:0385e73da22363778ef2324950e08b689abdf0b108a7d8decb403ad7f5191938 \ + --hash=sha256:051da80e6eeb6e239e394ae60704d2b566aa6a7aed6f2890a7967307267a5dc6 \ + --hash=sha256:05ed27acdf4465c95826962528f9e8d41dbf9b1aa8531a387dee6ed215a3e9ef \ + --hash=sha256:0654bca0cdf28a5956c83839162692725159f4cda8d63e0911a2c0dc76166525 \ + --hash=sha256:09e4a1a6acc39294a36b7338819b10baceb227f7f7dbbea0506d419b5a1dd8af \ + --hash=sha256:0b49c764f88a79160fa64f9a7b425620e87c9f46095ef9c9920542ab2495c8bc \ + --hash=sha256:0b71e63226e393b534105fcbdd8740410dc6b0854c2bfa39bbda6b0d40e59a54 \ + --hash=sha256:0c29ca1bd61b16b67be247be87390ef1d1ef702800f91fbd1991f5c4421ebae8 \ + --hash=sha256:10590510780b7541969287512d1b43f19f965c2ece6c9b1c00fc367b29d8dce7 \ + --hash=sha256:10cb847aeb1728412c666ab2e2000ba6f174f25b2bdc7292e7dd71b16db07568 \ + --hash=sha256:12b74fbbf6cbbf9dbce20eb9b5879469e97aeeaa874145517563cca4029db65c \ + --hash=sha256:20326216cc2afe69b6e98528160b225d72f85ab080cbdf0b11528cbbaba2248f \ + --hash=sha256:2239d95d8e243658b8dbb36b12bd10c33ad6e6933a54d36ff053713f129aa536 \ + --hash=sha256:25be746a8ec7bc7b082783216de8e9473803706723b3f6bef34b3d0ed03d57e2 \ + --hash=sha256:271f0bdba3c70b58e6f500b205d10a36fb4b58bd06ac61381b68de66442efddb \ + --hash=sha256:29cdd471ebf9e0f2fb3cac165efedc3c58db841d83a518b082077e612d3ee5df \ + --hash=sha256:2d44dc13229905ae96dd2ae2dd7cebf824ee92bc52e8cf03dcead37d926da019 \ + --hash=sha256:3676f1dd082be28b1266c93f618ee07741b704ab7b68501a173ce7d8d0d0ca18 \ + --hash=sha256:36efeba71c6539d23c4643be88295ce8c82c88bbd7c65e8a24081d2ca123da3f \ + --hash=sha256:3e5219bf9e75993d73ab3d25985c857c77e614525fac9ae02b1bebd92f7cecac \ + --hash=sha256:43e1dd9d12df9004246bacb79a0e5886b3b6071b32e41f83b0acbf293f820ee8 \ + --hash=sha256:457b6cce21bee41ac292d6753d5e94dcbc5c9e3e3a834da285b0bde7aa4a11e9 \ + --hash=sha256:463b6a3ceb5ca952e66550a4532cef94c9a0c80dc156c4cc343041951aec1697 \ + --hash=sha256:4959e8bcbfda5146477d21c3a8ad81b185cd252f3d0d6e4724a5ef11c012fb06 \ + --hash=sha256:4d3850beab9f527f06ccc94b446c864059c57651b3f911fddb8d9d3ec1d1b25d \ + --hash=sha256:5708089ed5b40a7b2dc561e0c8baa9535b77771b64a8330b684823cfd5116036 \ + --hash=sha256:5c6b48d0fa50d8f4df3daf451be7f9689c2bde1a52b1225c5926e3f54b6a9ed1 \ + --hash=sha256:61474f0b41fe1a80e8dfa70f70ea1e047387b7cd01c85ec88fa44f5d7561d787 \ + --hash=sha256:6343c6928282c1f6a9db41f5fd551662310e8774c0e5ebccb767002fcf663ca9 \ + --hash=sha256:65ba8603753cec91c71de423a943ba506363b0e5c3fdb913ef8f9caa14b2c7e0 \ + --hash=sha256:687ea9d78a4b1cf82f8479cab23678aff723108df3edeac098e5b2498879f4a7 \ + --hash=sha256:6b2675068c8b56f6bfd5a2bda55b8accbb96c02fd563704732fd1c95e2083461 \ + --hash=sha256:7117d10690c38a622e54c432dfbbd3cbd92f09401d622902c32f6d377e2300ee \ + --hash=sha256:7178bbc1b2ec40eaca599d13c092079bf529679bf0371c602edaa555e10b41c3 \ + --hash=sha256:72d1a25bf36d2050ceb35b517afe13864865268dfb45910e2e17a84be6cbfeb0 \ + --hash=sha256:742e19a90d9bb2f4a6cf2862b8b06dea5e09b96c9f2df1779e53432d7275331f \ + --hash=sha256:74390d18c75054947e4194019077e243c06fbb62e541d8817a0fa822ea310c14 \ + --hash=sha256:74419d2b50ecb98360cfaa2974da8689cb3b45b9deff0dcf489c0d333bcc1477 \ + --hash=sha256:824bf3ac11001849aec3fa1d69abcb67aac3e150a933963fb12bda5151fe1bfd \ + --hash=sha256:83320a09188e0e6c39088355d423aa9d056ad57a0b6c6381b300ec1a04ec3d16 \ + --hash=sha256:837328d14cde912af625d5f303ec29f7e28cdab588674897baafaf505341f2fc \ + --hash=sha256:841d6e0e5663d4c7b4c8099c9997be748677d46cbf43f9f471150e560791f7ff \ + --hash=sha256:87b2a5bb5e78ee0ad1de71c664d6eb536dc3947a46a69182a90f4410f5e3f7dd \ + --hash=sha256:890e5a11c97cf0d0c550eb661b937a1e45431ffa79803b942a057c4fb12a2da2 \ + --hash=sha256:8abbc5d54ea0ee80e37fef009e3cec5dafd722ed3c829126253d3e22f3846f1e \ + --hash=sha256:8e3f1316c2293e5469f8f09dc2d76efb6c3982d3da91ba95061a7e69489a14ef \ + --hash=sha256:8f56fcb7ff7bf7404becdfc60b1e81a6d0561807051fd2f1860b0d0348156a07 \ + --hash=sha256:9427a399501818a7564f8c90eced1e9e20709ece36be701f394ada99890ea4b3 \ + --hash=sha256:976d7a304b59ede34ca2921305b57356694f9e6879db323fd90a80f865d355a3 \ + --hash=sha256:9a5bfb3004f2144a084a16ce19ca56b8ac46e6fd0651f54269fc9e230edb5e4a \ + --hash=sha256:9beb322958aaca059f34975b0df135181f2e5d7a13b84d3e0e45434749cb20f7 \ + --hash=sha256:9edcbad1f8a407e450fbac88d89e04e0b99a08473f666a3f3de0fd292badb6aa \ + --hash=sha256:9edce5281f965cf135e19840f4d93d55b3835122aa76ccacfd389e880ba4cf82 \ + --hash=sha256:a4c3b7fa4cdaa69268748665a1a6ff70c014d39bb69c50fda64b396c9116cf77 \ + --hash=sha256:a8105e9af3b029f243ab11ad47c19b566482c150c754e4c717900a798806b222 \ + --hash=sha256:a99b50300df5add73d307cf66abea093304a07eb017bce94f01e795090dea87c \ + --hash=sha256:aad51907d74fc183033ad796dd4c2e080d1adcc4fd3c0fd4fd499f30c03011cd \ + --hash=sha256:af4dd387354dc83a3bff67127a124c21116feb0d2ef536805c454721c5d7993d \ + --hash=sha256:b28f5024a3a041009eb4c333863d7894d191215b39576535c6734cd88b0fcb68 \ + --hash=sha256:b4598b1897837067a57b08147a68ac026c1e73b31ef6e36deeeb1fa60b2933c9 \ + --hash=sha256:b6192d5af2ccd2a38877bfef086d35e6659566a335b1492786ff254c168b1693 \ + --hash=sha256:b862c2b9d5ae38a68b92e215b93f98d4c5e9454fa36aae4450f61dd33ff48487 \ + --hash=sha256:b956231ebdc45f5b7a2e1f90f66a12be9610ce775fe1b1d50414aac1e9206c06 \ + --hash=sha256:bb60b503ec8a6e4e3e03a681072fa3a5adcbfa5479fa2d898ae2b4a8e24c4591 \ + --hash=sha256:bbb02fd4462f37060122e5acacec78e49c0fbb303c30dd49c7f493cf21fc5b27 \ + --hash=sha256:bdff5eab10e59cf26bc479f565e25ed71a7d041d1ded04ccf9aee1d9f208487a \ + --hash=sha256:c123f662be8ec5ab4ea72ea300359023a5d1df095b7ead76fedcd8babbedf969 \ + --hash=sha256:c2b867c17a7a7ae44c43ebbeb1b5ff406b3e8d5b3e14662683e5e66e6cc868d3 \ + --hash=sha256:c5f8037000eb21e4823aa485149f2299eb589f8d1fe4b448036d230c3f4e68e0 \ + --hash=sha256:c6a57b742133830eec44d9b2290daf5cbe0a2f1d6acee1b3c7b1c7b2f3606df7 \ + --hash=sha256:ccf91346b7bd20c790310c4147eee6ed495a54ddb6737162a36ce9dbef3e4751 \ + --hash=sha256:cf67ca618b4fd34aee78740bea954d7c69fdda419eb208c2c0c7060bb822d747 \ + --hash=sha256:d2da3abc88711bce7557412310dfa50327d5769a31d1c894b58eb256459dc289 \ + --hash=sha256:d4f03bb71d482f979bda92e1427f3ec9b220e62a7dd337af0aa6b47bf4498f72 \ + --hash=sha256:d54af539295392611e7efbe94e827311eb8b29668e2b3f4cadcfe6f46df9c777 \ + --hash=sha256:d77f09bc4b55d4bf7cc5eba785d87001d6757b7c9eec237fe2af57aba1a071d9 \ + --hash=sha256:d831c2f8ff278179705ca59f7e8524069c1a989e716a1874d6d1aab6119d91d1 \ + --hash=sha256:dbbbfce33cd98f97f6bffb17801b0576e653f4fdb1d399b2ea89638bc8d08ae1 \ + --hash=sha256:dcba6dae7de533c876255317c11f3abe4907ba7d9aa15d13e3d9710d4315ec0e \ + --hash=sha256:e0bb18053dfcfed432cc3ac632b5e5e5c5b7e55fb3f8090e867bfd9b054dbcbf \ + --hash=sha256:e2fbd6236aae3b7f9d514312cdb58e6494ee1c76a9948adde6eba33eb1c4264f \ + --hash=sha256:e5087a3c59eef624a4591ef9eaa6e9a8d8a94c779dade95d27c0bc24650261cd \ + --hash=sha256:e8915cc96abeb8983cea1df3c939e3c6e1ac778340c17732eb63bb96247b91d2 \ + --hash=sha256:ea353ecb6ab5f7e7d2f4372b1e779796ebd7b37352d290096978fea83c4dba0c \ + --hash=sha256:ee2d1a9a253b1729bb2de27d41f696ae893507c7db224436abe83ee25356f5c1 \ + --hash=sha256:f415f802fbcafed5dcc694c13b1292f07fe0befdb94aa8a52905bd115ff41e88 \ + --hash=sha256:fb5ec16523dc573a4b277663a2b5a364e2099902d3944c9419a40ebd56a118f9 \ + --hash=sha256:fea75c3710d4f31389eed3c02f62d0b66a9da282521075061ce875eb5300cf23 # via # aws-sam-cli (setup.py) # cfn-lint @@ -718,6 +718,7 @@ ruamel-yaml-clib==0.2.7 \ --hash=sha256:045e0626baf1c52e5527bd5db361bc83180faaba2ff586e763d3d5982a876a9e \ --hash=sha256:15910ef4f3e537eea7fe45f8a5d19997479940d9196f357152a09031c5be59f3 \ --hash=sha256:184faeaec61dbaa3cace407cffc5819f7b977e75360e8d5ca19461cd851a5fc5 \ + --hash=sha256:1a6391a7cabb7641c32517539ca42cf84b87b667bad38b78d4d42dd23e957c81 \ --hash=sha256:1f08fd5a2bea9c4180db71678e850b995d2a5f4537be0e94557668cf0f5f9497 \ --hash=sha256:2aa261c29a5545adfef9296b7e33941f46aa5bbd21164228e833412af4c9c75f \ --hash=sha256:3110a99e0f94a4a3470ff67fc20d3f96c25b13d24c6980ff841e82bafe827cac \ @@ -728,13 +729,13 @@ ruamel-yaml-clib==0.2.7 \ --hash=sha256:4a4d8d417868d68b979076a9be6a38c676eca060785abaa6709c7b31593c35d1 \ --hash=sha256:4b3a93bb9bc662fc1f99c5c3ea8e623d8b23ad22f861eb6fce9377ac07ad6072 \ --hash=sha256:5bc0667c1eb8f83a3752b71b9c4ba55ef7c7058ae57022dd9b29065186a113d9 \ - --hash=sha256:721bc4ba4525f53f6a611ec0967bdcee61b31df5a56801281027a3a6d1c2daf5 \ --hash=sha256:763d65baa3b952479c4e972669f679fe490eee058d5aa85da483ebae2009d231 \ --hash=sha256:7bdb4c06b063f6fd55e472e201317a3bb6cdeeee5d5a38512ea5c01e1acbdd93 \ --hash=sha256:8831a2cedcd0f0927f788c5bdf6567d9dc9cc235646a434986a852af1cb54b4b \ --hash=sha256:91a789b4aa0097b78c93e3dc4b40040ba55bef518f84a40d4442f713b4094acb \ --hash=sha256:92460ce908546ab69770b2e576e4f99fbb4ce6ab4b245345a3869a0a0410488f \ --hash=sha256:99e77daab5d13a48a4054803d052ff40780278240a902b880dd37a51ba01a307 \ + --hash=sha256:9c7617df90c1365638916b98cdd9be833d31d337dbcd722485597b43c4a215bf \ --hash=sha256:a234a20ae07e8469da311e182e70ef6b199d0fbeb6c6cc2901204dd87fb867e8 \ --hash=sha256:a7b301ff08055d73223058b5c46c55638917f04d21577c95e00e0c4d79201a6b \ --hash=sha256:be2a7ad8fd8f7442b24323d24ba0b56c51219513cfa45b9ada3b87b76c374d4b \ @@ -778,9 +779,9 @@ tomlkit==0.11.8 \ --hash=sha256:8c726c4c202bdb148667835f68d68780b9a003a9ec34167b6c673b38eff2a171 \ --hash=sha256:9330fc7faa1db67b541b28e62018c17d20be733177d290a13b24c62d1614e0c3 # via aws-sam-cli (setup.py) -types-awscrt==0.16.26 \ - --hash=sha256:011b0efc054cddb542416f4a38452a3cab3f2d6cef7af0cd124c03a89634f101 \ - --hash=sha256:47bcfd741465196e000e5a29ea98516765d2e93803d3fb67f9d6be79a632ee98 +types-awscrt==0.17.0 \ + --hash=sha256:278c1a913098e226769cd28dc37643a2f360907353a7e8918e1bcdf93d4e34f2 \ + --hash=sha256:4214783a747af900a5f98ec020d52ecae5910b470fd636813637a45b82a97516 # via # botocore-stubs # types-s3transfer @@ -816,9 +817,9 @@ tzlocal==3.0 \ # via # aws-sam-cli (setup.py) # dateparser -urllib3==1.26.15 \ - --hash=sha256:8a388717b9476f934a21484e8c8e61875ab60644d29b9b39e11e4b9dc1c6b305 \ - --hash=sha256:aa751d169e23c7479ce47a0cb0da579e3ede798f994f5816a74e4f4500dcea42 +urllib3==1.26.16 \ + --hash=sha256:8d36afa7616d8ab714608411b4a3b13e58f463aee519024578e062e141dce20f \ + --hash=sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14 # via # botocore # docker @@ -850,13 +851,13 @@ werkzeug==2.3.6 \ --hash=sha256:935539fa1413afbb9195b24880778422ed620c0fc09670945185cce4d91a8890 \ --hash=sha256:98c774df2f91b05550078891dee5f0eb0cb797a522c757a2452b9cee5b202330 # via flask -wheel==0.40.0 \ - --hash=sha256:cd1196f3faee2b31968d626e1731c94f99cbdb67cf5a46e4f5656cbee7738873 \ - --hash=sha256:d236b20e7cb522daf2390fa84c55eea81c5c30190f90f29ae2ca1ad8355bf247 +wheel==0.41.0 \ + --hash=sha256:55a0f0a5a84869bce5ba775abfd9c462e3a6b1b7b7ec69d72c0b83d673a5114d \ + --hash=sha256:7e9be3bbd0078f6147d82ed9ed957e323e7708f57e134743d2edef3a7b7972a9 # via aws-lambda-builders -zipp==3.15.0 \ - --hash=sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b \ - --hash=sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556 +zipp==3.16.2 \ + --hash=sha256:679e51dd4403591b2d6838a48de3d283f3d188412a9782faadf845f298736ba0 \ + --hash=sha256:ebc15946aa78bd63458992fc81ec3b6f7b1e92d51c35e6de1c3804e73b799147 # via # importlib-metadata # importlib-resources diff --git a/requirements/reproducible-win.txt b/requirements/reproducible-win.txt new file mode 100644 index 0000000000..1129e344e8 --- /dev/null +++ b/requirements/reproducible-win.txt @@ -0,0 +1,893 @@ +# +# This file is autogenerated by pip-compile with Python 3.8 +# by the following command: +# +# pip-compile --allow-unsafe --generate-hashes --output-file='requirements\reproducible-win.txt' +# +arrow==1.2.3 \ + --hash=sha256:3934b30ca1b9f292376d9db15b19446088d12ec58629bc3f0da28fd55fb633a1 \ + --hash=sha256:5a49ab92e3b7b71d96cd6bfcc4df14efefc9dfa96ea19045815914a6ab6b1fe2 + # via jinja2-time +attrs==23.1.0 \ + --hash=sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04 \ + --hash=sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015 + # via + # jschema-to-python + # jsonschema + # sarif-om +aws-lambda-builders==1.36.0 \ + --hash=sha256:00ce31612a62dc8fa1a2dcd087648d125b6274ff8b18799d3ebe5bb4824f3e96 \ + --hash=sha256:b673b13d72ab9a85523e70a0980a8df86868bcf285d1ae1c032bb747bfc5b5d1 + # via aws-sam-cli (setup.py) +aws-sam-translator==1.71.0 \ + --hash=sha256:17fb87c8137d8d49e7a978396b2b3b279211819dee44618415aab1e99c2cb659 \ + --hash=sha256:a3ea80aeb116d7978b26ac916d2a5a24d012b742bf28262b17769c4b886e8fba + # via + # aws-sam-cli (setup.py) + # cfn-lint +backports-zoneinfo==0.2.1 \ + --hash=sha256:17746bd546106fa389c51dbea67c8b7c8f0d14b5526a579ca6ccf5ed72c526cf \ + --hash=sha256:1b13e654a55cd45672cb54ed12148cd33628f672548f373963b0bff67b217328 \ + --hash=sha256:1c5742112073a563c81f786e77514969acb58649bcdf6cdf0b4ed31a348d4546 \ + --hash=sha256:4a0f800587060bf8880f954dbef70de6c11bbe59c673c3d818921f042f9954a6 \ + --hash=sha256:5c144945a7752ca544b4b78c8c41544cdfaf9786f25fe5ffb10e838e19a27570 \ + --hash=sha256:7b0a64cda4145548fed9efc10322770f929b944ce5cee6c0dfe0c87bf4c0c8c9 \ + --hash=sha256:8439c030a11780786a2002261569bdf362264f605dfa4d65090b64b05c9f79a7 \ + --hash=sha256:8961c0f32cd0336fb8e8ead11a1f8cd99ec07145ec2931122faaac1c8f7fd987 \ + --hash=sha256:89a48c0d158a3cc3f654da4c2de1ceba85263fafb861b98b59040a5086259722 \ + --hash=sha256:a76b38c52400b762e48131494ba26be363491ac4f9a04c1b7e92483d169f6582 \ + --hash=sha256:da6013fd84a690242c310d77ddb8441a559e9cb3d3d59ebac9aca1a57b2e18bc \ + --hash=sha256:e55b384612d93be96506932a786bbcde5a2db7a9e6a4bb4bffe8b733f5b9036b \ + --hash=sha256:e81b76cace8eda1fca50e345242ba977f9be6ae3945af8d46326d776b4cf78d1 \ + --hash=sha256:e8236383a20872c0cdf5a62b554b27538db7fa1bbec52429d8d106effbaeca08 \ + --hash=sha256:f04e857b59d9d1ccc39ce2da1021d196e47234873820cbeaad210724b1ee28ac \ + --hash=sha256:fadbfe37f74051d024037f223b8e001611eac868b5c5b06144ef4d8b799862f2 + # via tzlocal +binaryornot==0.4.4 \ + --hash=sha256:359501dfc9d40632edc9fac890e19542db1a287bbcfa58175b66658392018061 \ + --hash=sha256:b8b71173c917bddcd2c16070412e369c3ed7f0528926f70cac18a6c97fd563e4 + # via cookiecutter +boto3==1.28.17 \ + --hash=sha256:90f7cfb5e1821af95b1fc084bc50e6c47fa3edc99f32de1a2591faa0c546bea7 \ + --hash=sha256:bca0526f819e0f19c0f1e6eba3e2d1d6b6a92a45129f98c0d716e5aab6d9444b + # via + # aws-sam-cli (setup.py) + # aws-sam-translator +boto3-stubs[apigateway,cloudformation,ecr,iam,lambda,s3,schemas,secretsmanager,signer,stepfunctions,sts,xray]==1.28.2 \ + --hash=sha256:b140f56315cd99c659a2cbae32dc4ae1ee44073b4250e1ad391d03ecf4b5eb40 \ + --hash=sha256:bcef1fcbd758de6078e75b036d3632dd95eaef00311e6688554b5b883a194563 + # via aws-sam-cli (setup.py) +botocore==1.31.17 \ + --hash=sha256:396459065dba4339eb4da4ec8b4e6599728eb89b7caaceea199e26f7d824a41c \ + --hash=sha256:6ac34a1d34aa3750e78b77b8596617e2bab938964694d651939dba2cbde2c12b + # via + # boto3 + # s3transfer +botocore-stubs==1.31.17 \ + --hash=sha256:0ccba9a9cee311e354c164fa8e8044a4b4150d7e536f0f09ae37637950391fbc \ + --hash=sha256:4a5c9415bd82fc22ad9b2e298022c96065ca1f330fc48b145fc1daa25fe10ff8 + # via boto3-stubs +certifi==2023.7.22 \ + --hash=sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082 \ + --hash=sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9 + # via requests +cffi==1.15.1 \ + --hash=sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5 \ + --hash=sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef \ + --hash=sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104 \ + --hash=sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426 \ + --hash=sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405 \ + --hash=sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375 \ + --hash=sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a \ + --hash=sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e \ + --hash=sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc \ + --hash=sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf \ + --hash=sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185 \ + --hash=sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497 \ + --hash=sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3 \ + --hash=sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35 \ + --hash=sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c \ + --hash=sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83 \ + --hash=sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21 \ + --hash=sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca \ + --hash=sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984 \ + --hash=sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac \ + --hash=sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd \ + --hash=sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee \ + --hash=sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a \ + --hash=sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2 \ + --hash=sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192 \ + --hash=sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7 \ + --hash=sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585 \ + --hash=sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f \ + --hash=sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e \ + --hash=sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27 \ + --hash=sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b \ + --hash=sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e \ + --hash=sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e \ + --hash=sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d \ + --hash=sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c \ + --hash=sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415 \ + --hash=sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82 \ + --hash=sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02 \ + --hash=sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314 \ + --hash=sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325 \ + --hash=sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c \ + --hash=sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3 \ + --hash=sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914 \ + --hash=sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045 \ + --hash=sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d \ + --hash=sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9 \ + --hash=sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5 \ + --hash=sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2 \ + --hash=sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c \ + --hash=sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3 \ + --hash=sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2 \ + --hash=sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8 \ + --hash=sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d \ + --hash=sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d \ + --hash=sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9 \ + --hash=sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162 \ + --hash=sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76 \ + --hash=sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4 \ + --hash=sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e \ + --hash=sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9 \ + --hash=sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6 \ + --hash=sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b \ + --hash=sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01 \ + --hash=sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0 + # via cryptography +cfn-lint==0.79.6 \ + --hash=sha256:09fc9cc497fc6d15e8b822a98fa0628ed6f8e9bcce6c289d95b2fc71d50aa63f \ + --hash=sha256:b67154460acb466e837590caa7a76bd95ec908961f21ba6de2d985309668ea29 + # via aws-sam-cli (setup.py) +chardet==5.2.0 \ + --hash=sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7 \ + --hash=sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970 + # via binaryornot +charset-normalizer==3.2.0 \ + --hash=sha256:04e57ab9fbf9607b77f7d057974694b4f6b142da9ed4a199859d9d4d5c63fe96 \ + --hash=sha256:09393e1b2a9461950b1c9a45d5fd251dc7c6f228acab64da1c9c0165d9c7765c \ + --hash=sha256:0b87549028f680ca955556e3bd57013ab47474c3124dc069faa0b6545b6c9710 \ + --hash=sha256:1000fba1057b92a65daec275aec30586c3de2401ccdcd41f8a5c1e2c87078706 \ + --hash=sha256:1249cbbf3d3b04902ff081ffbb33ce3377fa6e4c7356f759f3cd076cc138d020 \ + --hash=sha256:1920d4ff15ce893210c1f0c0e9d19bfbecb7983c76b33f046c13a8ffbd570252 \ + --hash=sha256:193cbc708ea3aca45e7221ae58f0fd63f933753a9bfb498a3b474878f12caaad \ + --hash=sha256:1a100c6d595a7f316f1b6f01d20815d916e75ff98c27a01ae817439ea7726329 \ + --hash=sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a \ + --hash=sha256:203f0c8871d5a7987be20c72442488a0b8cfd0f43b7973771640fc593f56321f \ + --hash=sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6 \ + --hash=sha256:2dee8e57f052ef5353cf608e0b4c871aee320dd1b87d351c28764fc0ca55f9f4 \ + --hash=sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a \ + --hash=sha256:2f4ac36d8e2b4cc1aa71df3dd84ff8efbe3bfb97ac41242fbcfc053c67434f46 \ + --hash=sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2 \ + --hash=sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23 \ + --hash=sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace \ + --hash=sha256:3bb7fda7260735efe66d5107fb7e6af6a7c04c7fce9b2514e04b7a74b06bf5dd \ + --hash=sha256:41b25eaa7d15909cf3ac4c96088c1f266a9a93ec44f87f1d13d4a0e86c81b982 \ + --hash=sha256:45de3f87179c1823e6d9e32156fb14c1927fcc9aba21433f088fdfb555b77c10 \ + --hash=sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2 \ + --hash=sha256:48021783bdf96e3d6de03a6e39a1171ed5bd7e8bb93fc84cc649d11490f87cea \ + --hash=sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09 \ + --hash=sha256:5e86d77b090dbddbe78867a0275cb4df08ea195e660f1f7f13435a4649e954e5 \ + --hash=sha256:6339d047dab2780cc6220f46306628e04d9750f02f983ddb37439ca47ced7149 \ + --hash=sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489 \ + --hash=sha256:6c409c0deba34f147f77efaa67b8e4bb83d2f11c8806405f76397ae5b8c0d1c9 \ + --hash=sha256:7095f6fbfaa55defb6b733cfeb14efaae7a29f0b59d8cf213be4e7ca0b857b80 \ + --hash=sha256:70c610f6cbe4b9fce272c407dd9d07e33e6bf7b4aa1b7ffb6f6ded8e634e3592 \ + --hash=sha256:72814c01533f51d68702802d74f77ea026b5ec52793c791e2da806a3844a46c3 \ + --hash=sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6 \ + --hash=sha256:7c70087bfee18a42b4040bb9ec1ca15a08242cf5867c58726530bdf3945672ed \ + --hash=sha256:855eafa5d5a2034b4621c74925d89c5efef61418570e5ef9b37717d9c796419c \ + --hash=sha256:8700f06d0ce6f128de3ccdbc1acaea1ee264d2caa9ca05daaf492fde7c2a7200 \ + --hash=sha256:89f1b185a01fe560bc8ae5f619e924407efca2191b56ce749ec84982fc59a32a \ + --hash=sha256:8b2c760cfc7042b27ebdb4a43a4453bd829a5742503599144d54a032c5dc7e9e \ + --hash=sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d \ + --hash=sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6 \ + --hash=sha256:94aea8eff76ee6d1cdacb07dd2123a68283cb5569e0250feab1240058f53b623 \ + --hash=sha256:95eb302ff792e12aba9a8b8f8474ab229a83c103d74a750ec0bd1c1eea32e669 \ + --hash=sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3 \ + --hash=sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa \ + --hash=sha256:a103b3a7069b62f5d4890ae1b8f0597618f628b286b03d4bc9195230b154bfa9 \ + --hash=sha256:a386ebe437176aab38c041de1260cd3ea459c6ce5263594399880bbc398225b2 \ + --hash=sha256:a38856a971c602f98472050165cea2cdc97709240373041b69030be15047691f \ + --hash=sha256:a401b4598e5d3f4a9a811f3daf42ee2291790c7f9d74b18d75d6e21dda98a1a1 \ + --hash=sha256:a7647ebdfb9682b7bb97e2a5e7cb6ae735b1c25008a70b906aecca294ee96cf4 \ + --hash=sha256:aaf63899c94de41fe3cf934601b0f7ccb6b428c6e4eeb80da72c58eab077b19a \ + --hash=sha256:b0dac0ff919ba34d4df1b6131f59ce95b08b9065233446be7e459f95554c0dc8 \ + --hash=sha256:baacc6aee0b2ef6f3d308e197b5d7a81c0e70b06beae1f1fcacffdbd124fe0e3 \ + --hash=sha256:bf420121d4c8dce6b889f0e8e4ec0ca34b7f40186203f06a946fa0276ba54029 \ + --hash=sha256:c04a46716adde8d927adb9457bbe39cf473e1e2c2f5d0a16ceb837e5d841ad4f \ + --hash=sha256:c0b21078a4b56965e2b12f247467b234734491897e99c1d51cee628da9786959 \ + --hash=sha256:c1c76a1743432b4b60ab3358c937a3fe1341c828ae6194108a94c69028247f22 \ + --hash=sha256:c4983bf937209c57240cff65906b18bb35e64ae872da6a0db937d7b4af845dd7 \ + --hash=sha256:c4fb39a81950ec280984b3a44f5bd12819953dc5fa3a7e6fa7a80db5ee853952 \ + --hash=sha256:c57921cda3a80d0f2b8aec7e25c8aa14479ea92b5b51b6876d975d925a2ea346 \ + --hash=sha256:c8063cf17b19661471ecbdb3df1c84f24ad2e389e326ccaf89e3fb2484d8dd7e \ + --hash=sha256:ccd16eb18a849fd8dcb23e23380e2f0a354e8daa0c984b8a732d9cfaba3a776d \ + --hash=sha256:cd6dbe0238f7743d0efe563ab46294f54f9bc8f4b9bcf57c3c666cc5bc9d1299 \ + --hash=sha256:d62e51710986674142526ab9f78663ca2b0726066ae26b78b22e0f5e571238dd \ + --hash=sha256:db901e2ac34c931d73054d9797383d0f8009991e723dab15109740a63e7f902a \ + --hash=sha256:e03b8895a6990c9ab2cdcd0f2fe44088ca1c65ae592b8f795c3294af00a461c3 \ + --hash=sha256:e1c8a2f4c69e08e89632defbfabec2feb8a8d99edc9f89ce33c4b9e36ab63037 \ + --hash=sha256:e4b749b9cc6ee664a3300bb3a273c1ca8068c46be705b6c31cf5d276f8628a94 \ + --hash=sha256:e6a5bf2cba5ae1bb80b154ed68a3cfa2fa00fde979a7f50d6598d3e17d9ac20c \ + --hash=sha256:e857a2232ba53ae940d3456f7533ce6ca98b81917d47adc3c7fd55dad8fab858 \ + --hash=sha256:ee4006268ed33370957f55bf2e6f4d263eaf4dc3cfc473d1d90baff6ed36ce4a \ + --hash=sha256:eef9df1eefada2c09a5e7a40991b9fc6ac6ef20b1372abd48d2794a316dc0449 \ + --hash=sha256:f058f6963fd82eb143c692cecdc89e075fa0828db2e5b291070485390b2f1c9c \ + --hash=sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918 \ + --hash=sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1 \ + --hash=sha256:f7560358a6811e52e9c4d142d497f1a6e10103d3a6881f18d04dbce3729c0e2c \ + --hash=sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac \ + --hash=sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa + # via requests +chevron==0.14.0 \ + --hash=sha256:87613aafdf6d77b6a90ff073165a61ae5086e21ad49057aa0e53681601800ebf \ + --hash=sha256:fbf996a709f8da2e745ef763f482ce2d311aa817d287593a5b990d6d6e4f0443 + # via aws-sam-cli (setup.py) +click==8.1.3 \ + --hash=sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e \ + --hash=sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48 + # via + # aws-sam-cli (setup.py) + # cookiecutter + # flask +colorama==0.4.6 \ + --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ + --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 + # via click +cookiecutter==2.1.1 \ + --hash=sha256:9f3ab027cec4f70916e28f03470bdb41e637a3ad354b4d65c765d93aad160022 \ + --hash=sha256:f3982be8d9c53dac1261864013fdec7f83afd2e42ede6f6dd069c5e149c540d5 + # via aws-sam-cli (setup.py) +cryptography==41.0.3 \ + --hash=sha256:0d09fb5356f975974dbcb595ad2d178305e5050656affb7890a1583f5e02a306 \ + --hash=sha256:23c2d778cf829f7d0ae180600b17e9fceea3c2ef8b31a99e3c694cbbf3a24b84 \ + --hash=sha256:3fb248989b6363906827284cd20cca63bb1a757e0a2864d4c1682a985e3dca47 \ + --hash=sha256:41d7aa7cdfded09b3d73a47f429c298e80796c8e825ddfadc84c8a7f12df212d \ + --hash=sha256:42cb413e01a5d36da9929baa9d70ca90d90b969269e5a12d39c1e0d475010116 \ + --hash=sha256:4c2f0d35703d61002a2bbdcf15548ebb701cfdd83cdc12471d2bae80878a4207 \ + --hash=sha256:4fd871184321100fb400d759ad0cddddf284c4b696568204d281c902fc7b0d81 \ + --hash=sha256:5259cb659aa43005eb55a0e4ff2c825ca111a0da1814202c64d28a985d33b087 \ + --hash=sha256:57a51b89f954f216a81c9d057bf1a24e2f36e764a1ca9a501a6964eb4a6800dd \ + --hash=sha256:652627a055cb52a84f8c448185922241dd5217443ca194d5739b44612c5e6507 \ + --hash=sha256:67e120e9a577c64fe1f611e53b30b3e69744e5910ff3b6e97e935aeb96005858 \ + --hash=sha256:6af1c6387c531cd364b72c28daa29232162010d952ceb7e5ca8e2827526aceae \ + --hash=sha256:6d192741113ef5e30d89dcb5b956ef4e1578f304708701b8b73d38e3e1461f34 \ + --hash=sha256:7efe8041897fe7a50863e51b77789b657a133c75c3b094e51b5e4b5cec7bf906 \ + --hash=sha256:84537453d57f55a50a5b6835622ee405816999a7113267739a1b4581f83535bd \ + --hash=sha256:8f09daa483aedea50d249ef98ed500569841d6498aa9c9f4b0531b9964658922 \ + --hash=sha256:95dd7f261bb76948b52a5330ba5202b91a26fbac13ad0e9fc8a3ac04752058c7 \ + --hash=sha256:a74fbcdb2a0d46fe00504f571a2a540532f4c188e6ccf26f1f178480117b33c4 \ + --hash=sha256:a983e441a00a9d57a4d7c91b3116a37ae602907a7618b882c8013b5762e80574 \ + --hash=sha256:ab8de0d091acbf778f74286f4989cf3d1528336af1b59f3e5d2ebca8b5fe49e1 \ + --hash=sha256:aeb57c421b34af8f9fe830e1955bf493a86a7996cc1338fe41b30047d16e962c \ + --hash=sha256:ce785cf81a7bdade534297ef9e490ddff800d956625020ab2ec2780a556c313e \ + --hash=sha256:d0d651aa754ef58d75cec6edfbd21259d93810b73f6ec246436a21b7841908de + # via pyopenssl +dateparser==1.1.8 \ + --hash=sha256:070b29b5bbf4b1ec2cd51c96ea040dc68a614de703910a91ad1abba18f9f379f \ + --hash=sha256:86b8b7517efcc558f085a142cdb7620f0921543fcabdb538c8a4c4001d8178e3 + # via aws-sam-cli (setup.py) +docker==6.1.3 \ + --hash=sha256:aa6d17830045ba5ef0168d5eaa34d37beeb113948c413affe1d5991fc11f9a20 \ + --hash=sha256:aecd2277b8bf8e506e484f6ab7aec39abe0038e29fa4a6d3ba86c3fe01844ed9 + # via aws-sam-cli (setup.py) +flask==2.2.5 \ + --hash=sha256:58107ed83443e86067e41eff4631b058178191a355886f8e479e347fa1285fdf \ + --hash=sha256:edee9b0a7ff26621bd5a8c10ff484ae28737a2410d99b0bb9a6850c7fb977aa0 + # via aws-sam-cli (setup.py) +idna==3.4 \ + --hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 \ + --hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2 + # via requests +importlib-metadata==6.8.0 \ + --hash=sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb \ + --hash=sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743 + # via flask +importlib-resources==6.0.0 \ + --hash=sha256:4cf94875a8368bd89531a756df9a9ebe1f150e0f885030b461237bc7f2d905f2 \ + --hash=sha256:d952faee11004c045f785bb5636e8f885bed30dc3c940d5d42798a2a4541c185 + # via jsonschema +itsdangerous==2.1.2 \ + --hash=sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44 \ + --hash=sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a + # via flask +jinja2==3.1.2 \ + --hash=sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852 \ + --hash=sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61 + # via + # cookiecutter + # flask + # jinja2-time +jinja2-time==0.2.0 \ + --hash=sha256:d14eaa4d315e7688daa4969f616f226614350c48730bfa1692d2caebd8c90d40 \ + --hash=sha256:d3eab6605e3ec8b7a0863df09cc1d23714908fa61aa6986a845c20ba488b4efa + # via cookiecutter +jmespath==1.0.1 \ + --hash=sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980 \ + --hash=sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe + # via + # aws-sam-cli (setup.py) + # boto3 + # botocore +jschema-to-python==1.2.3 \ + --hash=sha256:76ff14fe5d304708ccad1284e4b11f96a658949a31ee7faed9e0995279549b91 \ + --hash=sha256:8a703ca7604d42d74b2815eecf99a33359a8dccbb80806cce386d5e2dd992b05 + # via cfn-lint +jsonpatch==1.33 \ + --hash=sha256:0ae28c0cd062bbd8b8ecc26d7d164fbbea9652a1a3693f3b956c1eae5145dade \ + --hash=sha256:9fcd4009c41e6d12348b4a0ff2563ba56a2923a7dfee731d004e212e1ee5030c + # via cfn-lint +jsonpickle==3.0.1 \ + --hash=sha256:032538804795e73b94ead410800ac387fdb6de98f8882ac957fcd247e3a85200 \ + --hash=sha256:130d8b293ea0add3845de311aaba55e6d706d0bb17bc123bd2c8baf8a39ac77c + # via jschema-to-python +jsonpointer==2.4 \ + --hash=sha256:15d51bba20eea3165644553647711d150376234112651b4f1811022aecad7d7a \ + --hash=sha256:585cee82b70211fa9e6043b7bb89db6e1aa49524340dde8ad6b63206ea689d88 + # via jsonpatch +jsonschema==4.17.3 \ + --hash=sha256:0f864437ab8b6076ba6707453ef8f98a6a0d512a80e93f8abdb676f737ecb60d \ + --hash=sha256:a870ad254da1a8ca84b6a2905cac29d265f805acc57af304784962a2aa6508f6 + # via + # aws-sam-cli (setup.py) + # aws-sam-translator + # cfn-lint +junit-xml==1.9 \ + --hash=sha256:de16a051990d4e25a3982b2dd9e89d671067548718866416faec14d9de56db9f \ + --hash=sha256:ec5ca1a55aefdd76d28fcc0b135251d156c7106fa979686a4b48d62b761b4732 + # via cfn-lint +markdown-it-py==3.0.0 \ + --hash=sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1 \ + --hash=sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb + # via rich +markupsafe==2.1.3 \ + --hash=sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e \ + --hash=sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e \ + --hash=sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431 \ + --hash=sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686 \ + --hash=sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559 \ + --hash=sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc \ + --hash=sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c \ + --hash=sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0 \ + --hash=sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4 \ + --hash=sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9 \ + --hash=sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575 \ + --hash=sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba \ + --hash=sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d \ + --hash=sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3 \ + --hash=sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00 \ + --hash=sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155 \ + --hash=sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac \ + --hash=sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52 \ + --hash=sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f \ + --hash=sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8 \ + --hash=sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b \ + --hash=sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24 \ + --hash=sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea \ + --hash=sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198 \ + --hash=sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0 \ + --hash=sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee \ + --hash=sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be \ + --hash=sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2 \ + --hash=sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707 \ + --hash=sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6 \ + --hash=sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58 \ + --hash=sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779 \ + --hash=sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636 \ + --hash=sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c \ + --hash=sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad \ + --hash=sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee \ + --hash=sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc \ + --hash=sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2 \ + --hash=sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48 \ + --hash=sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7 \ + --hash=sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e \ + --hash=sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b \ + --hash=sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa \ + --hash=sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5 \ + --hash=sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e \ + --hash=sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb \ + --hash=sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9 \ + --hash=sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57 \ + --hash=sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc \ + --hash=sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2 + # via + # jinja2 + # werkzeug +mdurl==0.1.2 \ + --hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \ + --hash=sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba + # via markdown-it-py +mpmath==1.3.0 \ + --hash=sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f \ + --hash=sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c + # via sympy +mypy-boto3-apigateway==1.28.16 \ + --hash=sha256:4193124b6ab5b92de0affdd59f1485a17d68ecefff17b411f73a08ea5d5db92d \ + --hash=sha256:82491d942530ab9dabc4c811e188c6ab546c3e658c5718bab58fb45cadef6d0b + # via boto3-stubs +mypy-boto3-cloudformation==1.28.16 \ + --hash=sha256:228cb6e9096f64d36abd912c34e465545ff848bb837498112dc30235ca19750c \ + --hash=sha256:a5202db1ea76aa499a27b971745e0130e5cb88c2b323c48cca30cd01713d963a + # via boto3-stubs +mypy-boto3-ecr==1.28.16 \ + --hash=sha256:412aa7e26d20e7502267e5fec4d94f0bc48db0ced24f65d207911fe70585a4cd \ + --hash=sha256:b3252c5eda47ca1e90980e0158410e8a76c8acdfbda0907f545ddfddaea95258 + # via boto3-stubs +mypy-boto3-iam==1.28.16 \ + --hash=sha256:1416df5e838be7cc8b65def4721097faf691f8f0c65f58fe417d18b9e6b8de61 \ + --hash=sha256:8ef9ef9a9fabcc1058a46bbd6b1408960a70d72e45a024862676e5a896c446b3 + # via boto3-stubs +mypy-boto3-lambda==1.28.16 \ + --hash=sha256:c1b688c1ea7cbb9b79b8a1dcaaa7459791ae7ebc608490251f58a07edb31170c \ + --hash=sha256:c7c647139e6710da694aba4a644f69f4a06c6e43419168d69cc57f3dc6e5e607 + # via boto3-stubs +mypy-boto3-s3==1.28.16 \ + --hash=sha256:4e55fdad729b6e6f45211e354bd1a0a745a565fe9d1e462737f775c28849cfb5 \ + --hash=sha256:855f7848186c45adbd3c474fec2d75db17f4cd7200c0a2235473250454ec4686 + # via boto3-stubs +mypy-boto3-schemas==1.28.16 \ + --hash=sha256:4f4b4fc784452b5186ab31199e4cb5546d314f3fc666cb698c960ba89e33448e \ + --hash=sha256:7898f9624af46be956bd8e1dffc6fc01d6e2141e067444156bddd2c412ef8084 + # via boto3-stubs +mypy-boto3-secretsmanager==1.28.16 \ + --hash=sha256:05508c3a96d96e482e5aff21b508319a1911e6662aea5be96aa7f7089b8dbfd4 \ + --hash=sha256:07f443b31d2114ac363cfbdbc5f4b97934ca48fb99734bbd06d5c39bce244b83 + # via boto3-stubs +mypy-boto3-signer==1.28.16 \ + --hash=sha256:78d9bacf72b865221c6d11a946a0d6aad3b14904475c886fafd08cd1dd54c5d7 \ + --hash=sha256:a67206f20189105a24deee995ab130123fa1af75c39c13c17e404ff74b9ec1fc + # via boto3-stubs +mypy-boto3-stepfunctions==1.28.16 \ + --hash=sha256:8b2b6578ca38dc0f13d73292b92afd7f3cf11a8999a33886d4c4ab6822f0020a \ + --hash=sha256:962c80b1bac778b64c6334df50a3860bf4d0a5d17560fac765e7913615926b2b + # via boto3-stubs +mypy-boto3-sts==1.28.16 \ + --hash=sha256:7cd388a7451611813730b83c78179759eb5701b849618d82c3ec7e95576bedb9 \ + --hash=sha256:a00bc7f69d8675058db0fb2c39d4d9dbb3a3c14ae1d0d83fbf930a2a0498629a + # via boto3-stubs +mypy-boto3-xray==1.28.16 \ + --hash=sha256:4bc7dfd46cb71ca6a9d46b47453d59a08ac80c872cc429dacb45a93abd737172 \ + --hash=sha256:6ddd4acccf272bf663522c5fcd31b9b7dacbed4a01c91e44e4e8c0abb2343c0a + # via boto3-stubs +networkx==3.1 \ + --hash=sha256:4f33f68cb2afcf86f28a45f43efc27a9386b535d567d2127f8f61d51dec58d36 \ + --hash=sha256:de346335408f84de0eada6ff9fafafff9bcda11f0a0dfaa931133debb146ab61 + # via cfn-lint +packaging==23.1 \ + --hash=sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61 \ + --hash=sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f + # via docker +pbr==5.11.1 \ + --hash=sha256:567f09558bae2b3ab53cb3c1e2e33e726ff3338e7bae3db5dc954b3a44eef12b \ + --hash=sha256:aefc51675b0b533d56bb5fd1c8c6c0522fe31896679882e1c4c63d5e4a0fccb3 + # via + # jschema-to-python + # sarif-om +pkgutil-resolve-name==1.3.10 \ + --hash=sha256:357d6c9e6a755653cfd78893817c0853af365dd51ec97f3d358a819373bbd174 \ + --hash=sha256:ca27cc078d25c5ad71a9de0a7a330146c4e014c2462d9af19c6b828280649c5e + # via jsonschema +pycparser==2.21 \ + --hash=sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9 \ + --hash=sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206 + # via cffi +pydantic==1.10.12 \ + --hash=sha256:0fe8a415cea8f340e7a9af9c54fc71a649b43e8ca3cc732986116b3cb135d303 \ + --hash=sha256:1289c180abd4bd4555bb927c42ee42abc3aee02b0fb2d1223fb7c6e5bef87dbe \ + --hash=sha256:1eb2085c13bce1612da8537b2d90f549c8cbb05c67e8f22854e201bde5d98a47 \ + --hash=sha256:2031de0967c279df0d8a1c72b4ffc411ecd06bac607a212892757db7462fc494 \ + --hash=sha256:2a7bac939fa326db1ab741c9d7f44c565a1d1e80908b3797f7f81a4f86bc8d33 \ + --hash=sha256:2d5a58feb9a39f481eda4d5ca220aa8b9d4f21a41274760b9bc66bfd72595b86 \ + --hash=sha256:2f9a6fab5f82ada41d56b0602606a5506aab165ca54e52bc4545028382ef1c5d \ + --hash=sha256:2fcfb5296d7877af406ba1547dfde9943b1256d8928732267e2653c26938cd9c \ + --hash=sha256:549a8e3d81df0a85226963611950b12d2d334f214436a19537b2efed61b7639a \ + --hash=sha256:598da88dfa127b666852bef6d0d796573a8cf5009ffd62104094a4fe39599565 \ + --hash=sha256:5d1197e462e0364906cbc19681605cb7c036f2475c899b6f296104ad42b9f5fb \ + --hash=sha256:69328e15cfda2c392da4e713443c7dbffa1505bc9d566e71e55abe14c97ddc62 \ + --hash=sha256:6a9dfa722316f4acf4460afdf5d41d5246a80e249c7ff475c43a3a1e9d75cf62 \ + --hash=sha256:6b30bcb8cbfccfcf02acb8f1a261143fab622831d9c0989707e0e659f77a18e0 \ + --hash=sha256:6c076be61cd0177a8433c0adcb03475baf4ee91edf5a4e550161ad57fc90f523 \ + --hash=sha256:771735dc43cf8383959dc9b90aa281f0b6092321ca98677c5fb6125a6f56d58d \ + --hash=sha256:795e34e6cc065f8f498c89b894a3c6da294a936ee71e644e4bd44de048af1405 \ + --hash=sha256:87afda5539d5140cb8ba9e8b8c8865cb5b1463924d38490d73d3ccfd80896b3f \ + --hash=sha256:8fb2aa3ab3728d950bcc885a2e9eff6c8fc40bc0b7bb434e555c215491bcf48b \ + --hash=sha256:a1fcb59f2f355ec350073af41d927bf83a63b50e640f4dbaa01053a28b7a7718 \ + --hash=sha256:a5e7add47a5b5a40c49b3036d464e3c7802f8ae0d1e66035ea16aa5b7a3923ed \ + --hash=sha256:a73f489aebd0c2121ed974054cb2759af8a9f747de120acd2c3394cf84176ccb \ + --hash=sha256:ab26038b8375581dc832a63c948f261ae0aa21f1d34c1293469f135fa92972a5 \ + --hash=sha256:b0d191db0f92dfcb1dec210ca244fdae5cbe918c6050b342d619c09d31eea0cc \ + --hash=sha256:b749a43aa51e32839c9d71dc67eb1e4221bb04af1033a32e3923d46f9effa942 \ + --hash=sha256:b7ccf02d7eb340b216ec33e53a3a629856afe1c6e0ef91d84a4e6f2fb2ca70fe \ + --hash=sha256:ba5b2e6fe6ca2b7e013398bc7d7b170e21cce322d266ffcd57cca313e54fb246 \ + --hash=sha256:ba5c4a8552bff16c61882db58544116d021d0b31ee7c66958d14cf386a5b5350 \ + --hash=sha256:c79e6a11a07da7374f46970410b41d5e266f7f38f6a17a9c4823db80dadf4303 \ + --hash=sha256:ca48477862372ac3770969b9d75f1bf66131d386dba79506c46d75e6b48c1e09 \ + --hash=sha256:dea7adcc33d5d105896401a1f37d56b47d443a2b2605ff8a969a0ed5543f7e33 \ + --hash=sha256:e0a16d274b588767602b7646fa05af2782576a6cf1022f4ba74cbb4db66f6ca8 \ + --hash=sha256:e4129b528c6baa99a429f97ce733fff478ec955513630e61b49804b6cf9b224a \ + --hash=sha256:e5f805d2d5d0a41633651a73fa4ecdd0b3d7a49de4ec3fadf062fe16501ddbf1 \ + --hash=sha256:ef6c96b2baa2100ec91a4b428f80d8f28a3c9e53568219b6c298c1125572ebc6 \ + --hash=sha256:fdbdd1d630195689f325c9ef1a12900524dceb503b00a987663ff4f58669b93d + # via aws-sam-translator +pygments==2.15.1 \ + --hash=sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c \ + --hash=sha256:db2db3deb4b4179f399a09054b023b6a586b76499d36965813c71aa8ed7b5fd1 + # via rich +pyopenssl==23.2.0 \ + --hash=sha256:24f0dc5227396b3e831f4c7f602b950a5e9833d292c8e4a2e06b709292806ae2 \ + --hash=sha256:276f931f55a452e7dea69c7173e984eb2a4407ce413c918aa34b55f82f9b8bac + # via aws-sam-cli (setup.py) +pyrsistent==0.19.3 \ + --hash=sha256:016ad1afadf318eb7911baa24b049909f7f3bb2c5b1ed7b6a8f21db21ea3faa8 \ + --hash=sha256:1a2994773706bbb4995c31a97bc94f1418314923bd1048c6d964837040376440 \ + --hash=sha256:20460ac0ea439a3e79caa1dbd560344b64ed75e85d8703943e0b66c2a6150e4a \ + --hash=sha256:3311cb4237a341aa52ab8448c27e3a9931e2ee09561ad150ba94e4cfd3fc888c \ + --hash=sha256:3a8cb235fa6d3fd7aae6a4f1429bbb1fec1577d978098da1252f0489937786f3 \ + --hash=sha256:3ab2204234c0ecd8b9368dbd6a53e83c3d4f3cab10ecaf6d0e772f456c442393 \ + --hash=sha256:42ac0b2f44607eb92ae88609eda931a4f0dfa03038c44c772e07f43e738bcac9 \ + --hash=sha256:49c32f216c17148695ca0e02a5c521e28a4ee6c5089f97e34fe24163113722da \ + --hash=sha256:4b774f9288dda8d425adb6544e5903f1fb6c273ab3128a355c6b972b7df39dcf \ + --hash=sha256:4c18264cb84b5e68e7085a43723f9e4c1fd1d935ab240ce02c0324a8e01ccb64 \ + --hash=sha256:5a474fb80f5e0d6c9394d8db0fc19e90fa540b82ee52dba7d246a7791712f74a \ + --hash=sha256:64220c429e42a7150f4bfd280f6f4bb2850f95956bde93c6fda1b70507af6ef3 \ + --hash=sha256:878433581fc23e906d947a6814336eee031a00e6defba224234169ae3d3d6a98 \ + --hash=sha256:99abb85579e2165bd8522f0c0138864da97847875ecbd45f3e7e2af569bfc6f2 \ + --hash=sha256:a2471f3f8693101975b1ff85ffd19bb7ca7dd7c38f8a81701f67d6b4f97b87d8 \ + --hash=sha256:aeda827381f5e5d65cced3024126529ddc4289d944f75e090572c77ceb19adbf \ + --hash=sha256:b735e538f74ec31378f5a1e3886a26d2ca6351106b4dfde376a26fc32a044edc \ + --hash=sha256:c147257a92374fde8498491f53ffa8f4822cd70c0d85037e09028e478cababb7 \ + --hash=sha256:c4db1bd596fefd66b296a3d5d943c94f4fac5bcd13e99bffe2ba6a759d959a28 \ + --hash=sha256:c74bed51f9b41c48366a286395c67f4e894374306b197e62810e0fdaf2364da2 \ + --hash=sha256:c9bb60a40a0ab9aba40a59f68214eed5a29c6274c83b2cc206a359c4a89fa41b \ + --hash=sha256:cc5d149f31706762c1f8bda2e8c4f8fead6e80312e3692619a75301d3dbb819a \ + --hash=sha256:ccf0d6bd208f8111179f0c26fdf84ed7c3891982f2edaeae7422575f47e66b64 \ + --hash=sha256:e42296a09e83028b3476f7073fcb69ffebac0e66dbbfd1bd847d61f74db30f19 \ + --hash=sha256:e8f2b814a3dc6225964fa03d8582c6e0b6650d68a232df41e3cc1b66a5d2f8d1 \ + --hash=sha256:f0774bf48631f3a20471dd7c5989657b639fd2d285b861237ea9e82c36a415a9 \ + --hash=sha256:f0e7c4b2f77593871e918be000b96c8107da48444d57005b6a6bc61fb4331b2c + # via jsonschema +python-dateutil==2.8.2 \ + --hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \ + --hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9 + # via + # arrow + # botocore + # dateparser +python-slugify==8.0.1 \ + --hash=sha256:70ca6ea68fe63ecc8fa4fcf00ae651fc8a5d02d93dcd12ae6d4fc7ca46c4d395 \ + --hash=sha256:ce0d46ddb668b3be82f4ed5e503dbc33dd815d83e2eb6824211310d3fb172a27 + # via cookiecutter +pytz==2023.3 \ + --hash=sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588 \ + --hash=sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb + # via dateparser +pywin32==306 \ + --hash=sha256:06d3420a5155ba65f0b72f2699b5bacf3109f36acbe8923765c22938a69dfc8d \ + --hash=sha256:1c73ea9a0d2283d889001998059f5eaaba3b6238f767c9cf2833b13e6a685f65 \ + --hash=sha256:37257794c1ad39ee9be652da0462dc2e394c8159dfd913a8a4e8eb6fd346da0e \ + --hash=sha256:383229d515657f4e3ed1343da8be101000562bf514591ff383ae940cad65458b \ + --hash=sha256:39b61c15272833b5c329a2989999dcae836b1eed650252ab1b7bfbe1d59f30f4 \ + --hash=sha256:5821ec52f6d321aa59e2db7e0a35b997de60c201943557d108af9d4ae1ec7040 \ + --hash=sha256:70dba0c913d19f942a2db25217d9a1b726c278f483a919f1abfed79c9cf64d3a \ + --hash=sha256:72c5f621542d7bdd4fdb716227be0dd3f8565c11b280be6315b06ace35487d36 \ + --hash=sha256:84f4471dbca1887ea3803d8848a1616429ac94a4a8d05f4bc9c5dcfd42ca99c8 \ + --hash=sha256:a7639f51c184c0272e93f244eb24dafca9b1855707d94c192d4a0b4c01e1100e \ + --hash=sha256:e25fd5b485b55ac9c057f67d94bc203f3f6595078d1fb3b458c9c28b7153a802 \ + --hash=sha256:e4c092e2589b5cf0d365849e73e02c391c1349958c5ac3e9d5ccb9a28e017b3a \ + --hash=sha256:e65028133d15b64d2ed8f06dd9fbc268352478d4f9289e69c190ecd6818b6407 \ + --hash=sha256:e8ac1ae3601bee6ca9f7cb4b5363bf1c0badb935ef243c4733ff9a393b1690c0 + # via docker +pyyaml==6.0.1 \ + --hash=sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc \ + --hash=sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741 \ + --hash=sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206 \ + --hash=sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27 \ + --hash=sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595 \ + --hash=sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62 \ + --hash=sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98 \ + --hash=sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696 \ + --hash=sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d \ + --hash=sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867 \ + --hash=sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47 \ + --hash=sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486 \ + --hash=sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6 \ + --hash=sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3 \ + --hash=sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 \ + --hash=sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938 \ + --hash=sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c \ + --hash=sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735 \ + --hash=sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d \ + --hash=sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba \ + --hash=sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8 \ + --hash=sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5 \ + --hash=sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd \ + --hash=sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3 \ + --hash=sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0 \ + --hash=sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515 \ + --hash=sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c \ + --hash=sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c \ + --hash=sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924 \ + --hash=sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34 \ + --hash=sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43 \ + --hash=sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859 \ + --hash=sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673 \ + --hash=sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a \ + --hash=sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab \ + --hash=sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa \ + --hash=sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c \ + --hash=sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585 \ + --hash=sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d \ + --hash=sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f + # via + # aws-sam-cli (setup.py) + # cfn-lint + # cookiecutter +regex==2023.6.3 \ + --hash=sha256:0385e73da22363778ef2324950e08b689abdf0b108a7d8decb403ad7f5191938 \ + --hash=sha256:051da80e6eeb6e239e394ae60704d2b566aa6a7aed6f2890a7967307267a5dc6 \ + --hash=sha256:05ed27acdf4465c95826962528f9e8d41dbf9b1aa8531a387dee6ed215a3e9ef \ + --hash=sha256:0654bca0cdf28a5956c83839162692725159f4cda8d63e0911a2c0dc76166525 \ + --hash=sha256:09e4a1a6acc39294a36b7338819b10baceb227f7f7dbbea0506d419b5a1dd8af \ + --hash=sha256:0b49c764f88a79160fa64f9a7b425620e87c9f46095ef9c9920542ab2495c8bc \ + --hash=sha256:0b71e63226e393b534105fcbdd8740410dc6b0854c2bfa39bbda6b0d40e59a54 \ + --hash=sha256:0c29ca1bd61b16b67be247be87390ef1d1ef702800f91fbd1991f5c4421ebae8 \ + --hash=sha256:10590510780b7541969287512d1b43f19f965c2ece6c9b1c00fc367b29d8dce7 \ + --hash=sha256:10cb847aeb1728412c666ab2e2000ba6f174f25b2bdc7292e7dd71b16db07568 \ + --hash=sha256:12b74fbbf6cbbf9dbce20eb9b5879469e97aeeaa874145517563cca4029db65c \ + --hash=sha256:20326216cc2afe69b6e98528160b225d72f85ab080cbdf0b11528cbbaba2248f \ + --hash=sha256:2239d95d8e243658b8dbb36b12bd10c33ad6e6933a54d36ff053713f129aa536 \ + --hash=sha256:25be746a8ec7bc7b082783216de8e9473803706723b3f6bef34b3d0ed03d57e2 \ + --hash=sha256:271f0bdba3c70b58e6f500b205d10a36fb4b58bd06ac61381b68de66442efddb \ + --hash=sha256:29cdd471ebf9e0f2fb3cac165efedc3c58db841d83a518b082077e612d3ee5df \ + --hash=sha256:2d44dc13229905ae96dd2ae2dd7cebf824ee92bc52e8cf03dcead37d926da019 \ + --hash=sha256:3676f1dd082be28b1266c93f618ee07741b704ab7b68501a173ce7d8d0d0ca18 \ + --hash=sha256:36efeba71c6539d23c4643be88295ce8c82c88bbd7c65e8a24081d2ca123da3f \ + --hash=sha256:3e5219bf9e75993d73ab3d25985c857c77e614525fac9ae02b1bebd92f7cecac \ + --hash=sha256:43e1dd9d12df9004246bacb79a0e5886b3b6071b32e41f83b0acbf293f820ee8 \ + --hash=sha256:457b6cce21bee41ac292d6753d5e94dcbc5c9e3e3a834da285b0bde7aa4a11e9 \ + --hash=sha256:463b6a3ceb5ca952e66550a4532cef94c9a0c80dc156c4cc343041951aec1697 \ + --hash=sha256:4959e8bcbfda5146477d21c3a8ad81b185cd252f3d0d6e4724a5ef11c012fb06 \ + --hash=sha256:4d3850beab9f527f06ccc94b446c864059c57651b3f911fddb8d9d3ec1d1b25d \ + --hash=sha256:5708089ed5b40a7b2dc561e0c8baa9535b77771b64a8330b684823cfd5116036 \ + --hash=sha256:5c6b48d0fa50d8f4df3daf451be7f9689c2bde1a52b1225c5926e3f54b6a9ed1 \ + --hash=sha256:61474f0b41fe1a80e8dfa70f70ea1e047387b7cd01c85ec88fa44f5d7561d787 \ + --hash=sha256:6343c6928282c1f6a9db41f5fd551662310e8774c0e5ebccb767002fcf663ca9 \ + --hash=sha256:65ba8603753cec91c71de423a943ba506363b0e5c3fdb913ef8f9caa14b2c7e0 \ + --hash=sha256:687ea9d78a4b1cf82f8479cab23678aff723108df3edeac098e5b2498879f4a7 \ + --hash=sha256:6b2675068c8b56f6bfd5a2bda55b8accbb96c02fd563704732fd1c95e2083461 \ + --hash=sha256:7117d10690c38a622e54c432dfbbd3cbd92f09401d622902c32f6d377e2300ee \ + --hash=sha256:7178bbc1b2ec40eaca599d13c092079bf529679bf0371c602edaa555e10b41c3 \ + --hash=sha256:72d1a25bf36d2050ceb35b517afe13864865268dfb45910e2e17a84be6cbfeb0 \ + --hash=sha256:742e19a90d9bb2f4a6cf2862b8b06dea5e09b96c9f2df1779e53432d7275331f \ + --hash=sha256:74390d18c75054947e4194019077e243c06fbb62e541d8817a0fa822ea310c14 \ + --hash=sha256:74419d2b50ecb98360cfaa2974da8689cb3b45b9deff0dcf489c0d333bcc1477 \ + --hash=sha256:824bf3ac11001849aec3fa1d69abcb67aac3e150a933963fb12bda5151fe1bfd \ + --hash=sha256:83320a09188e0e6c39088355d423aa9d056ad57a0b6c6381b300ec1a04ec3d16 \ + --hash=sha256:837328d14cde912af625d5f303ec29f7e28cdab588674897baafaf505341f2fc \ + --hash=sha256:841d6e0e5663d4c7b4c8099c9997be748677d46cbf43f9f471150e560791f7ff \ + --hash=sha256:87b2a5bb5e78ee0ad1de71c664d6eb536dc3947a46a69182a90f4410f5e3f7dd \ + --hash=sha256:890e5a11c97cf0d0c550eb661b937a1e45431ffa79803b942a057c4fb12a2da2 \ + --hash=sha256:8abbc5d54ea0ee80e37fef009e3cec5dafd722ed3c829126253d3e22f3846f1e \ + --hash=sha256:8e3f1316c2293e5469f8f09dc2d76efb6c3982d3da91ba95061a7e69489a14ef \ + --hash=sha256:8f56fcb7ff7bf7404becdfc60b1e81a6d0561807051fd2f1860b0d0348156a07 \ + --hash=sha256:9427a399501818a7564f8c90eced1e9e20709ece36be701f394ada99890ea4b3 \ + --hash=sha256:976d7a304b59ede34ca2921305b57356694f9e6879db323fd90a80f865d355a3 \ + --hash=sha256:9a5bfb3004f2144a084a16ce19ca56b8ac46e6fd0651f54269fc9e230edb5e4a \ + --hash=sha256:9beb322958aaca059f34975b0df135181f2e5d7a13b84d3e0e45434749cb20f7 \ + --hash=sha256:9edcbad1f8a407e450fbac88d89e04e0b99a08473f666a3f3de0fd292badb6aa \ + --hash=sha256:9edce5281f965cf135e19840f4d93d55b3835122aa76ccacfd389e880ba4cf82 \ + --hash=sha256:a4c3b7fa4cdaa69268748665a1a6ff70c014d39bb69c50fda64b396c9116cf77 \ + --hash=sha256:a8105e9af3b029f243ab11ad47c19b566482c150c754e4c717900a798806b222 \ + --hash=sha256:a99b50300df5add73d307cf66abea093304a07eb017bce94f01e795090dea87c \ + --hash=sha256:aad51907d74fc183033ad796dd4c2e080d1adcc4fd3c0fd4fd499f30c03011cd \ + --hash=sha256:af4dd387354dc83a3bff67127a124c21116feb0d2ef536805c454721c5d7993d \ + --hash=sha256:b28f5024a3a041009eb4c333863d7894d191215b39576535c6734cd88b0fcb68 \ + --hash=sha256:b4598b1897837067a57b08147a68ac026c1e73b31ef6e36deeeb1fa60b2933c9 \ + --hash=sha256:b6192d5af2ccd2a38877bfef086d35e6659566a335b1492786ff254c168b1693 \ + --hash=sha256:b862c2b9d5ae38a68b92e215b93f98d4c5e9454fa36aae4450f61dd33ff48487 \ + --hash=sha256:b956231ebdc45f5b7a2e1f90f66a12be9610ce775fe1b1d50414aac1e9206c06 \ + --hash=sha256:bb60b503ec8a6e4e3e03a681072fa3a5adcbfa5479fa2d898ae2b4a8e24c4591 \ + --hash=sha256:bbb02fd4462f37060122e5acacec78e49c0fbb303c30dd49c7f493cf21fc5b27 \ + --hash=sha256:bdff5eab10e59cf26bc479f565e25ed71a7d041d1ded04ccf9aee1d9f208487a \ + --hash=sha256:c123f662be8ec5ab4ea72ea300359023a5d1df095b7ead76fedcd8babbedf969 \ + --hash=sha256:c2b867c17a7a7ae44c43ebbeb1b5ff406b3e8d5b3e14662683e5e66e6cc868d3 \ + --hash=sha256:c5f8037000eb21e4823aa485149f2299eb589f8d1fe4b448036d230c3f4e68e0 \ + --hash=sha256:c6a57b742133830eec44d9b2290daf5cbe0a2f1d6acee1b3c7b1c7b2f3606df7 \ + --hash=sha256:ccf91346b7bd20c790310c4147eee6ed495a54ddb6737162a36ce9dbef3e4751 \ + --hash=sha256:cf67ca618b4fd34aee78740bea954d7c69fdda419eb208c2c0c7060bb822d747 \ + --hash=sha256:d2da3abc88711bce7557412310dfa50327d5769a31d1c894b58eb256459dc289 \ + --hash=sha256:d4f03bb71d482f979bda92e1427f3ec9b220e62a7dd337af0aa6b47bf4498f72 \ + --hash=sha256:d54af539295392611e7efbe94e827311eb8b29668e2b3f4cadcfe6f46df9c777 \ + --hash=sha256:d77f09bc4b55d4bf7cc5eba785d87001d6757b7c9eec237fe2af57aba1a071d9 \ + --hash=sha256:d831c2f8ff278179705ca59f7e8524069c1a989e716a1874d6d1aab6119d91d1 \ + --hash=sha256:dbbbfce33cd98f97f6bffb17801b0576e653f4fdb1d399b2ea89638bc8d08ae1 \ + --hash=sha256:dcba6dae7de533c876255317c11f3abe4907ba7d9aa15d13e3d9710d4315ec0e \ + --hash=sha256:e0bb18053dfcfed432cc3ac632b5e5e5c5b7e55fb3f8090e867bfd9b054dbcbf \ + --hash=sha256:e2fbd6236aae3b7f9d514312cdb58e6494ee1c76a9948adde6eba33eb1c4264f \ + --hash=sha256:e5087a3c59eef624a4591ef9eaa6e9a8d8a94c779dade95d27c0bc24650261cd \ + --hash=sha256:e8915cc96abeb8983cea1df3c939e3c6e1ac778340c17732eb63bb96247b91d2 \ + --hash=sha256:ea353ecb6ab5f7e7d2f4372b1e779796ebd7b37352d290096978fea83c4dba0c \ + --hash=sha256:ee2d1a9a253b1729bb2de27d41f696ae893507c7db224436abe83ee25356f5c1 \ + --hash=sha256:f415f802fbcafed5dcc694c13b1292f07fe0befdb94aa8a52905bd115ff41e88 \ + --hash=sha256:fb5ec16523dc573a4b277663a2b5a364e2099902d3944c9419a40ebd56a118f9 \ + --hash=sha256:fea75c3710d4f31389eed3c02f62d0b66a9da282521075061ce875eb5300cf23 + # via + # aws-sam-cli (setup.py) + # cfn-lint + # dateparser +requests==2.31.0 \ + --hash=sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f \ + --hash=sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1 + # via + # aws-sam-cli (setup.py) + # cookiecutter + # docker +rich==13.4.2 \ + --hash=sha256:8f87bc7ee54675732fa66a05ebfe489e27264caeeff3728c945d25971b6485ec \ + --hash=sha256:d653d6bccede5844304c605d5aac802c7cf9621efd700b46c7ec2b51ea914898 + # via aws-sam-cli (setup.py) +ruamel-yaml==0.17.32 \ + --hash=sha256:23cd2ed620231677564646b0c6a89d138b6822a0d78656df7abda5879ec4f447 \ + --hash=sha256:ec939063761914e14542972a5cba6d33c23b0859ab6342f61cf070cfc600efc2 + # via aws-sam-cli (setup.py) +ruamel-yaml-clib==0.2.7 \ + --hash=sha256:045e0626baf1c52e5527bd5db361bc83180faaba2ff586e763d3d5982a876a9e \ + --hash=sha256:15910ef4f3e537eea7fe45f8a5d19997479940d9196f357152a09031c5be59f3 \ + --hash=sha256:184faeaec61dbaa3cace407cffc5819f7b977e75360e8d5ca19461cd851a5fc5 \ + --hash=sha256:1a6391a7cabb7641c32517539ca42cf84b87b667bad38b78d4d42dd23e957c81 \ + --hash=sha256:1f08fd5a2bea9c4180db71678e850b995d2a5f4537be0e94557668cf0f5f9497 \ + --hash=sha256:2aa261c29a5545adfef9296b7e33941f46aa5bbd21164228e833412af4c9c75f \ + --hash=sha256:3110a99e0f94a4a3470ff67fc20d3f96c25b13d24c6980ff841e82bafe827cac \ + --hash=sha256:3243f48ecd450eddadc2d11b5feb08aca941b5cd98c9b1db14b2fd128be8c697 \ + --hash=sha256:370445fd795706fd291ab00c9df38a0caed0f17a6fb46b0f607668ecb16ce763 \ + --hash=sha256:40d030e2329ce5286d6b231b8726959ebbe0404c92f0a578c0e2482182e38282 \ + --hash=sha256:41d0f1fa4c6830176eef5b276af04c89320ea616655d01327d5ce65e50575c94 \ + --hash=sha256:4a4d8d417868d68b979076a9be6a38c676eca060785abaa6709c7b31593c35d1 \ + --hash=sha256:4b3a93bb9bc662fc1f99c5c3ea8e623d8b23ad22f861eb6fce9377ac07ad6072 \ + --hash=sha256:5bc0667c1eb8f83a3752b71b9c4ba55ef7c7058ae57022dd9b29065186a113d9 \ + --hash=sha256:763d65baa3b952479c4e972669f679fe490eee058d5aa85da483ebae2009d231 \ + --hash=sha256:7bdb4c06b063f6fd55e472e201317a3bb6cdeeee5d5a38512ea5c01e1acbdd93 \ + --hash=sha256:8831a2cedcd0f0927f788c5bdf6567d9dc9cc235646a434986a852af1cb54b4b \ + --hash=sha256:91a789b4aa0097b78c93e3dc4b40040ba55bef518f84a40d4442f713b4094acb \ + --hash=sha256:92460ce908546ab69770b2e576e4f99fbb4ce6ab4b245345a3869a0a0410488f \ + --hash=sha256:99e77daab5d13a48a4054803d052ff40780278240a902b880dd37a51ba01a307 \ + --hash=sha256:9c7617df90c1365638916b98cdd9be833d31d337dbcd722485597b43c4a215bf \ + --hash=sha256:a234a20ae07e8469da311e182e70ef6b199d0fbeb6c6cc2901204dd87fb867e8 \ + --hash=sha256:a7b301ff08055d73223058b5c46c55638917f04d21577c95e00e0c4d79201a6b \ + --hash=sha256:be2a7ad8fd8f7442b24323d24ba0b56c51219513cfa45b9ada3b87b76c374d4b \ + --hash=sha256:bf9a6bc4a0221538b1a7de3ed7bca4c93c02346853f44e1cd764be0023cd3640 \ + --hash=sha256:c3ca1fbba4ae962521e5eb66d72998b51f0f4d0f608d3c0347a48e1af262efa7 \ + --hash=sha256:d000f258cf42fec2b1bbf2863c61d7b8918d31ffee905da62dede869254d3b8a \ + --hash=sha256:d5859983f26d8cd7bb5c287ef452e8aacc86501487634573d260968f753e1d71 \ + --hash=sha256:d5e51e2901ec2366b79f16c2299a03e74ba4531ddcfacc1416639c557aef0ad8 \ + --hash=sha256:da538167284de58a52109a9b89b8f6a53ff8437dd6dc26d33b57bf6699153122 \ + --hash=sha256:debc87a9516b237d0466a711b18b6ebeb17ba9f391eb7f91c649c5c4ec5006c7 \ + --hash=sha256:df5828871e6648db72d1c19b4bd24819b80a755c4541d3409f0f7acd0f335c80 \ + --hash=sha256:ecdf1a604009bd35c674b9225a8fa609e0282d9b896c03dd441a91e5f53b534e \ + --hash=sha256:efa08d63ef03d079dcae1dfe334f6c8847ba8b645d08df286358b1f5293d24ab \ + --hash=sha256:f01da5790e95815eb5a8a138508c01c758e5f5bc0ce4286c4f7028b8dd7ac3d0 \ + --hash=sha256:f34019dced51047d6f70cb9383b2ae2853b7fc4dce65129a5acd49f4f9256646 \ + --hash=sha256:f6d3d39611ac2e4f62c3128a9eed45f19a6608670c5a2f4f07f24e8de3441d38 + # via ruamel-yaml +s3transfer==0.6.1 \ + --hash=sha256:3c0da2d074bf35d6870ef157158641178a4204a6e689e82546083e31e0311346 \ + --hash=sha256:640bb492711f4c0c0905e1f62b6aaeb771881935ad27884852411f8e9cacbca9 + # via boto3 +sarif-om==1.0.4 \ + --hash=sha256:539ef47a662329b1c8502388ad92457425e95dc0aaaf995fe46f4984c4771911 \ + --hash=sha256:cd5f416b3083e00d402a92e449a7ff67af46f11241073eea0461802a3b5aef98 + # via cfn-lint +six==1.16.0 \ + --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ + --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 + # via + # junit-xml + # python-dateutil +sympy==1.12 \ + --hash=sha256:c3588cd4295d0c0f603d0f2ae780587e64e2efeedb3521e46b9bb1d08d184fa5 \ + --hash=sha256:ebf595c8dac3e0fdc4152c51878b498396ec7f30e7a914d6071e674d49420fb8 + # via cfn-lint +text-unidecode==1.3 \ + --hash=sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8 \ + --hash=sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93 + # via python-slugify +tomlkit==0.11.8 \ + --hash=sha256:8c726c4c202bdb148667835f68d68780b9a003a9ec34167b6c673b38eff2a171 \ + --hash=sha256:9330fc7faa1db67b541b28e62018c17d20be733177d290a13b24c62d1614e0c3 + # via aws-sam-cli (setup.py) +types-awscrt==0.17.0 \ + --hash=sha256:278c1a913098e226769cd28dc37643a2f360907353a7e8918e1bcdf93d4e34f2 \ + --hash=sha256:4214783a747af900a5f98ec020d52ecae5910b470fd636813637a45b82a97516 + # via + # botocore-stubs + # types-s3transfer +types-s3transfer==0.6.1 \ + --hash=sha256:6d1ac1dedac750d570428362acdf60fdd4f277b0788855c3894d3226756b2bfb \ + --hash=sha256:75ac1d7143d58c1e6af467cfd4a96c67ee058a3adf7c249d9309999e1f5f41e4 + # via boto3-stubs +typing-extensions==4.7.1 \ + --hash=sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36 \ + --hash=sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2 + # via + # aws-sam-cli (setup.py) + # aws-sam-translator + # boto3-stubs + # botocore-stubs + # mypy-boto3-apigateway + # mypy-boto3-cloudformation + # mypy-boto3-ecr + # mypy-boto3-iam + # mypy-boto3-lambda + # mypy-boto3-s3 + # mypy-boto3-schemas + # mypy-boto3-secretsmanager + # mypy-boto3-signer + # mypy-boto3-stepfunctions + # mypy-boto3-sts + # mypy-boto3-xray + # pydantic + # rich +tzdata==2023.3 \ + --hash=sha256:11ef1e08e54acb0d4f95bdb1be05da659673de4acbd21bf9c69e94cc5e907a3a \ + --hash=sha256:7e65763eef3120314099b6939b5546db7adce1e7d6f2e179e3df563c70511eda + # via tzlocal +tzlocal==3.0 \ + --hash=sha256:c736f2540713deb5938d789ca7c3fc25391e9a20803f05b60ec64987cf086559 \ + --hash=sha256:f4e6e36db50499e0d92f79b67361041f048e2609d166e93456b50746dc4aef12 + # via + # aws-sam-cli (setup.py) + # dateparser +urllib3==1.26.16 \ + --hash=sha256:8d36afa7616d8ab714608411b4a3b13e58f463aee519024578e062e141dce20f \ + --hash=sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14 + # via + # botocore + # docker + # requests +watchdog==2.1.2 \ + --hash=sha256:0237db4d9024859bea27d0efb59fe75eef290833fd988b8ead7a879b0308c2db \ + --hash=sha256:104266a778906ae0e971368d368a65c4cd032a490a9fca5ba0b78c6c7ae11720 \ + --hash=sha256:188145185c08c73c56f1478ccf1f0f0f85101191439679b35b6b100886ce0b39 \ + --hash=sha256:1a62a4671796dc93d1a7262286217d9e75823c63d4c42782912d39a506d30046 \ + --hash=sha256:255a32d44bbbe62e52874ff755e2eefe271b150e0ec240ad7718a62a7a7a73c4 \ + --hash=sha256:3d6405681471ebe0beb3aa083998c4870e48b57f8afdb45ea1b5957cc5cf1014 \ + --hash=sha256:4b219d46d89cfa49af1d73175487c14a318a74cb8c5442603fd13c6a5b418c86 \ + --hash=sha256:581e3548159fe7d2a9f377a1fbcb41bdcee46849cca8ab803c7ac2e5e04ec77c \ + --hash=sha256:58ebb1095ee493008a7789d47dd62e4999505d82be89fc884d473086fccc6ebd \ + --hash=sha256:598d772beeaf9c98d0df946fbabf0c8365dd95ea46a250c224c725fe0c4730bc \ + --hash=sha256:668391e6c32742d76e5be5db6bf95c455fa4b3d11e76a77c13b39bccb3a47a72 \ + --hash=sha256:6ef9fe57162c4c361692620e1d9167574ba1975ee468b24051ca11c9bba6438e \ + --hash=sha256:91387ee2421f30b75f7ff632c9d48f76648e56bf346a7c805c0a34187a93aab4 \ + --hash=sha256:a42e6d652f820b2b94cd03156c62559a2ea68d476476dfcd77d931e7f1012d4a \ + --hash=sha256:a6471517315a8541a943c00b45f1d252e36898a3ae963d2d52509b89a50cb2b9 \ + --hash=sha256:d34ce2261f118ecd57eedeef95fc2a495fc4a40b3ed7b3bf0bd7a8ccc1ab4f8f \ + --hash=sha256:edcd9ef3fd460bb8a98eb1fcf99941e9fd9f275f45f1a82cb1359ec92975d647 + # via aws-sam-cli (setup.py) +websocket-client==1.6.1 \ + --hash=sha256:c951af98631d24f8df89ab1019fc365f2227c0892f12fd150e935607c79dd0dd \ + --hash=sha256:f1f9f2ad5291f0225a49efad77abf9e700b6fef553900623060dad6e26503b9d + # via docker +werkzeug==2.3.6 \ + --hash=sha256:935539fa1413afbb9195b24880778422ed620c0fc09670945185cce4d91a8890 \ + --hash=sha256:98c774df2f91b05550078891dee5f0eb0cb797a522c757a2452b9cee5b202330 + # via flask +wheel==0.41.0 \ + --hash=sha256:55a0f0a5a84869bce5ba775abfd9c462e3a6b1b7b7ec69d72c0b83d673a5114d \ + --hash=sha256:7e9be3bbd0078f6147d82ed9ed957e323e7708f57e134743d2edef3a7b7972a9 + # via aws-lambda-builders +zipp==3.16.2 \ + --hash=sha256:679e51dd4403591b2d6838a48de3d283f3d188412a9782faadf845f298736ba0 \ + --hash=sha256:ebc15946aa78bd63458992fc81ec3b6f7b1e92d51c35e6de1c3804e73b799147 + # via + # importlib-metadata + # importlib-resources + +# The following packages are considered to be unsafe in a requirements file: +setuptools==68.0.0 \ + --hash=sha256:11e52c67415a381d10d6b462ced9cfb97066179f0e871399e006c4ab101fc85f \ + --hash=sha256:baf1fdb41c6da4cd2eae722e135500da913332ab3f2f5c7d33af9b492acb5235 + # via aws-lambda-builders From 1af6375c30994a5ae48faeffff06d0641aedc527 Mon Sep 17 00:00:00 2001 From: Leonardo Gama <51037424+Leo10Gama@users.noreply.github.com> Date: Thu, 3 Aug 2023 10:39:32 -0700 Subject: [PATCH 09/13] fix: Repair failing integration test (#5698) * Fix failing integration test * Be more specific with error message --------- Co-authored-by: Leonardo Gama --- tests/integration/deploy/test_deploy_command.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/integration/deploy/test_deploy_command.py b/tests/integration/deploy/test_deploy_command.py index 7221c40264..0b4327370e 100644 --- a/tests/integration/deploy/test_deploy_command.py +++ b/tests/integration/deploy/test_deploy_command.py @@ -826,7 +826,11 @@ def test_deploy_with_invalid_config(self, template_file, config_file): deploy_process_execute = self.run_command(deploy_command_list) self.assertEqual(deploy_process_execute.process.returncode, 1) - self.assertIn("Error reading configuration: Unexpected character", str(deploy_process_execute.stderr)) + self.assertIn( + "Unexpected character: 'm' at line 2 col 11", + str(deploy_process_execute.stderr), + "Should notify user of the parsing error.", + ) @parameterized.expand([("aws-serverless-function.yaml", "samconfig-tags-list.toml")]) def test_deploy_with_valid_config_tags_list(self, template_file, config_file): From e8584897a90fe7265726a7ef6b5541f0a1adcede Mon Sep 17 00:00:00 2001 From: Mohamed Elasmar <71043312+moelasmar@users.noreply.github.com> Date: Thu, 3 Aug 2023 10:46:36 -0700 Subject: [PATCH 10/13] fix: link the API gateway resource parent to either rest api or another gateway resource (#5697) --- .../terraform/hooks/prepare/constants.py | 10 + .../terraform/hooks/prepare/exceptions.py | 21 + .../hooks/prepare/property_builder.py | 24 +- .../hooks/prepare/resource_linking.py | 382 ++++++++++++------ .../hooks/prepare/resources/resource_links.py | 16 +- .../prepare/resources/resource_properties.py | 2 +- .../terraform/hooks/prepare/translate.py | 39 +- .../terraform/hooks/prepare/types.py | 6 + ...st_start_api_with_terraform_application.py | 38 +- .../terraform/terraform-v1-api-simple/main.tf | 40 +- .../HelloWorldFunction.zip | Bin 0 -> 1079 bytes .../terraform-v1-nested-apis/main.tf | 143 +++++++ .../resources/test_resource_properties.py | 5 +- .../hooks/prepare/test_property_builder.py | 2 +- .../hooks/prepare/test_resource_linking.py | 298 +++++++++----- .../terraform/hooks/prepare/test_translate.py | 49 ++- 16 files changed, 786 insertions(+), 289 deletions(-) create mode 100644 tests/integration/testdata/start_api/terraform/terraform-v1-nested-apis/HelloWorldFunction.zip create mode 100644 tests/integration/testdata/start_api/terraform/terraform-v1-nested-apis/main.tf diff --git a/samcli/hook_packages/terraform/hooks/prepare/constants.py b/samcli/hook_packages/terraform/hooks/prepare/constants.py index 6cbe591e57..ffde46e57c 100644 --- a/samcli/hook_packages/terraform/hooks/prepare/constants.py +++ b/samcli/hook_packages/terraform/hooks/prepare/constants.py @@ -13,3 +13,13 @@ CFN_AWS_LAMBDA_LAYER_VERSION: "Content", } COMPILED_REGULAR_EXPRESSION = re.compile(r"\[[^\[\]]*\]") +REMOTE_DUMMY_VALUE = "<>" +TF_AWS_LAMBDA_FUNCTION = "aws_lambda_function" +TF_AWS_LAMBDA_LAYER_VERSION = "aws_lambda_layer_version" +TF_AWS_API_GATEWAY_RESOURCE = "aws_api_gateway_resource" +TF_AWS_API_GATEWAY_REST_API = "aws_api_gateway_rest_api" +TF_AWS_API_GATEWAY_STAGE = "aws_api_gateway_stage" +TF_AWS_API_GATEWAY_METHOD = "aws_api_gateway_method" +TF_AWS_API_GATEWAY_INTEGRATION = "aws_api_gateway_integration" +TF_AWS_API_GATEWAY_AUTHORIZER = "aws_api_gateway_authorizer" +TF_AWS_API_GATEWAY_INTEGRATION_RESPONSE = "aws_api_gateway_method_response" diff --git a/samcli/hook_packages/terraform/hooks/prepare/exceptions.py b/samcli/hook_packages/terraform/hooks/prepare/exceptions.py index ca8cdf55f6..f0ea430478 100644 --- a/samcli/hook_packages/terraform/hooks/prepare/exceptions.py +++ b/samcli/hook_packages/terraform/hooks/prepare/exceptions.py @@ -19,6 +19,13 @@ def __init__(self, message): UserException.__init__(self, msg) +class UnexpectedDestinationResource(InvalidResourceLinkingException): + """ + Exception that will be thrown while doing terraform linking logic in case if the found destination resource is not + of the expected type, or the field used for linking is not the expected field. + """ + + class ApplyLimitationException(UserException): def __init__(self, message): fmt = "{message}{line_sep}{line_sep}{apply_work_around}" @@ -85,6 +92,20 @@ class GatewayResourceToGatewayRestApiLocalVariablesLinkingLimitationException(Lo """ +class OneGatewayResourceToParentResourceLinkingLimitationException(OneResourceLinkingLimitationException): + """ + Exception specific for Gateway Resource linking to more than one Parent Resources which is either Rest API or + Gateway Resource + """ + + +class GatewayResourceToParentResourceLocalVariablesLinkingLimitationException(LocalVariablesLinkingLimitationException): + """ + Exception specific for Gateway Resource linking to Parent Resources which is either Rest API or Gateway Resource + using locals. + """ + + class OneRestApiToApiGatewayMethodLinkingLimitationException(OneResourceLinkingLimitationException): """ Exception specific for Gateway Method linking to more than Rest API diff --git a/samcli/hook_packages/terraform/hooks/prepare/property_builder.py b/samcli/hook_packages/terraform/hooks/prepare/property_builder.py index a8910f112a..4fe50e935a 100644 --- a/samcli/hook_packages/terraform/hooks/prepare/property_builder.py +++ b/samcli/hook_packages/terraform/hooks/prepare/property_builder.py @@ -6,6 +6,18 @@ from json.decoder import JSONDecodeError from typing import Any, Dict, Optional +from samcli.hook_packages.terraform.hooks.prepare.constants import ( + REMOTE_DUMMY_VALUE, + TF_AWS_API_GATEWAY_AUTHORIZER, + TF_AWS_API_GATEWAY_INTEGRATION, + TF_AWS_API_GATEWAY_INTEGRATION_RESPONSE, + TF_AWS_API_GATEWAY_METHOD, + TF_AWS_API_GATEWAY_RESOURCE, + TF_AWS_API_GATEWAY_REST_API, + TF_AWS_API_GATEWAY_STAGE, + TF_AWS_LAMBDA_FUNCTION, + TF_AWS_LAMBDA_LAYER_VERSION, +) from samcli.hook_packages.terraform.hooks.prepare.resource_linking import _resolve_resource_attribute from samcli.hook_packages.terraform.hooks.prepare.resources.internal import ( INTERNAL_API_GATEWAY_INTEGRATION, @@ -29,18 +41,6 @@ LOG = logging.getLogger(__name__) -REMOTE_DUMMY_VALUE = "<>" -TF_AWS_LAMBDA_FUNCTION = "aws_lambda_function" -TF_AWS_LAMBDA_LAYER_VERSION = "aws_lambda_layer_version" - -TF_AWS_API_GATEWAY_RESOURCE = "aws_api_gateway_resource" -TF_AWS_API_GATEWAY_REST_API = "aws_api_gateway_rest_api" -TF_AWS_API_GATEWAY_STAGE = "aws_api_gateway_stage" -TF_AWS_API_GATEWAY_METHOD = "aws_api_gateway_method" -TF_AWS_API_GATEWAY_INTEGRATION = "aws_api_gateway_integration" -TF_AWS_API_GATEWAY_AUTHORIZER = "aws_api_gateway_authorizer" -TF_AWS_API_GATEWAY_INTEGRATION_RESPONSE = "aws_api_gateway_method_response" - def _build_code_property(tf_properties: dict, resource: TFResource) -> Any: """ diff --git a/samcli/hook_packages/terraform/hooks/prepare/resource_linking.py b/samcli/hook_packages/terraform/hooks/prepare/resource_linking.py index 80dd302d41..08ae51cff7 100644 --- a/samcli/hook_packages/terraform/hooks/prepare/resource_linking.py +++ b/samcli/hook_packages/terraform/hooks/prepare/resource_linking.py @@ -7,6 +7,7 @@ from dataclasses import dataclass from typing import Callable, Dict, List, Optional, Type, Union +from samcli.hook_packages.terraform.hooks.prepare.constants import TF_AWS_API_GATEWAY_REST_API from samcli.hook_packages.terraform.hooks.prepare.exceptions import ( FunctionLayerLocalVariablesLinkingLimitationException, GatewayAuthorizerToLambdaFunctionLocalVariablesLinkingLimitationException, @@ -16,6 +17,7 @@ GatewayResourceToApiGatewayIntegrationResponseLocalVariablesLinkingLimitationException, GatewayResourceToApiGatewayMethodLocalVariablesLinkingLimitationException, GatewayResourceToGatewayRestApiLocalVariablesLinkingLimitationException, + GatewayResourceToParentResourceLocalVariablesLinkingLimitationException, InvalidResourceLinkingException, LambdaFunctionToApiGatewayIntegrationLocalVariablesLinkingLimitationException, LocalVariablesLinkingLimitationException, @@ -25,6 +27,7 @@ OneGatewayResourceToApiGatewayIntegrationLinkingLimitationException, OneGatewayResourceToApiGatewayIntegrationResponseLinkingLimitationException, OneGatewayResourceToApiGatewayMethodLinkingLimitationException, + OneGatewayResourceToParentResourceLinkingLimitationException, OneGatewayResourceToRestApiLinkingLimitationException, OneLambdaFunctionResourceToApiGatewayIntegrationLinkingLimitationException, OneLambdaLayerLinkingLimitationException, @@ -37,6 +40,7 @@ RestApiToApiGatewayIntegrationResponseLocalVariablesLinkingLimitationException, RestApiToApiGatewayMethodLocalVariablesLinkingLimitationException, RestApiToApiGatewayStageLocalVariablesLinkingLimitationException, + UnexpectedDestinationResource, ) from samcli.hook_packages.terraform.hooks.prepare.resources.apigw import INVOKE_ARN_FORMAT from samcli.hook_packages.terraform.hooks.prepare.types import ( @@ -87,6 +91,7 @@ class LogicalIdReference(ReferenceType): for the destination resources defined in the customer TF project. """ + resource_type: str value: str @@ -96,15 +101,20 @@ class ResourcePairExceptions: local_variable_linking_exception: Type[LocalVariablesLinkingLimitationException] +@dataclass +class ResourcePairExceptedDestination: + terraform_resource_type_prefix: str + terraform_attribute_name: str + + @dataclass class ResourceLinkingPair: source_resource_cfn_resource: Dict[str, List] source_resource_tf_config: Dict[str, TFResource] destination_resource_tf: Dict[str, Dict] - tf_destination_attribute_name: str # arn or id + expected_destinations: List[ResourcePairExceptedDestination] terraform_link_field_name: str cfn_link_field_name: str - terraform_resource_type_prefix: str cfn_resource_update_call_back_function: Callable[[Dict, List[ReferenceType]], None] linking_exceptions: ResourcePairExceptions @@ -272,22 +282,36 @@ def _link_using_linking_fields(self, cfn_resource: Dict) -> None: values = [values] # build map between the destination linking field property values, and resources' logical ids + expected_destinations_map = { + expected_destination.terraform_resource_type_prefix: expected_destination.terraform_attribute_name + for expected_destination in self._resource_pair.expected_destinations + } child_resources_linking_attributes_logical_id_mapping = {} for logical_id, destination_resource in self._resource_pair.destination_resource_tf.items(): - linking_attribute_value = destination_resource.get("values", {}).get( - self._resource_pair.tf_destination_attribute_name - ) + destination_attribute = expected_destinations_map.get(f"{destination_resource.get('type', '')}.", "") + linking_attribute_value = destination_resource.get("values", {}).get(destination_attribute) if linking_attribute_value: - child_resources_linking_attributes_logical_id_mapping[linking_attribute_value] = logical_id + child_resources_linking_attributes_logical_id_mapping[linking_attribute_value] = ( + logical_id, + destination_resource.get("type", {}), + ) LOG.debug( - "The map between destination resources linking field %s, and resources logical ids is %s", - self._resource_pair.tf_destination_attribute_name, + "The map between destination resources linking fields %s, and resources logical ids is %s", + ", ".join( + [ + expected_destination.terraform_attribute_name + for expected_destination in self._resource_pair.expected_destinations + ] + ), child_resources_linking_attributes_logical_id_mapping, ) dest_resources = [ - LogicalIdReference(child_resources_linking_attributes_logical_id_mapping[value]) + LogicalIdReference( + value=child_resources_linking_attributes_logical_id_mapping[value][0], + resource_type=child_resources_linking_attributes_logical_id_mapping[value][1], + ) if value in child_resources_linking_attributes_logical_id_mapping else ExistingResourceReference(value) for value in values @@ -389,64 +413,74 @@ def _process_reference_resource_value( ) # Valid destination resource - if resolved_destination_resource.value.startswith(self._resource_pair.terraform_resource_type_prefix): - LOG.debug("Process the destination resource %s", resolved_destination_resource.value) - if not resolved_destination_resource.value.endswith(self._resource_pair.tf_destination_attribute_name): - LOG.debug( - "The used property in reference %s is not an ARN property", resolved_destination_resource.value - ) - raise InvalidResourceLinkingException( - f"Could not use the value {resolved_destination_resource.value} as a " - f"destination resource for the source resource " - f"{source_tf_resource.full_address}. The source resource " - f"value should refer to valid destination resource ARN property." - ) - - # we need to the resource name by removing the attribute part from the reference value - # as an example the reference will be look like aws_layer_version.layer1.arn - # and the attribute name is `arn`, we need to remove the last 4 characters `.arn` - # which is the length of the linking attribute `arn` in our example adding one for the `.` character - tf_dest_res_name = resolved_destination_resource.value[ - len(self._resource_pair.terraform_resource_type_prefix) : -len( - self._resource_pair.tf_destination_attribute_name - ) - - 1 - ] - if resolved_destination_resource.module_address: - tf_dest_resource_full_address = ( - f"{resolved_destination_resource.module_address}." - f"{self._resource_pair.terraform_resource_type_prefix}" - f"{tf_dest_res_name}" - ) - else: - tf_dest_resource_full_address = ( - f"{self._resource_pair.terraform_resource_type_prefix}{tf_dest_res_name}" - ) - cfn_dest_resource_logical_id = build_cfn_logical_id(tf_dest_resource_full_address) - LOG.debug( - "The logical id of the resource referred by %s is %s", - resolved_destination_resource.value, - cfn_dest_resource_logical_id, - ) - - # validate that the found dest resource is in mapped dest resources, which means that it is created. - # The resource can be defined in the TF plan configuration, but will not be created. - dest_resources: List[ReferenceType] = [] - if cfn_dest_resource_logical_id in self._resource_pair.destination_resource_tf: + for expected_destination in self._resource_pair.expected_destinations: + if resolved_destination_resource.value.startswith(expected_destination.terraform_resource_type_prefix): + LOG.debug("Process the destination resource %s", resolved_destination_resource.value) + if not resolved_destination_resource.value.endswith(expected_destination.terraform_attribute_name): + LOG.debug( + "The used property in reference %s is not an %s property", + resolved_destination_resource.value, + expected_destination.terraform_attribute_name, + ) + continue + + # we need to the resource name by removing the attribute part from the reference value + # as an example the reference will be look like aws_layer_version.layer1.arn + # and the attribute name is `arn`, we need to remove the last 4 characters `.arn` + # which is the length of the linking attribute `arn` in our example adding one for the `.` character + tf_dest_res_name = resolved_destination_resource.value[ + len(expected_destination.terraform_resource_type_prefix) : -len( + expected_destination.terraform_attribute_name + ) + - 1 + ] + if resolved_destination_resource.module_address: + tf_dest_resource_full_address = ( + f"{resolved_destination_resource.module_address}." + f"{expected_destination.terraform_resource_type_prefix}" + f"{tf_dest_res_name}" + ) + else: + tf_dest_resource_full_address = ( + f"{expected_destination.terraform_resource_type_prefix}{tf_dest_res_name}" + ) + cfn_dest_resource_logical_id = build_cfn_logical_id(tf_dest_resource_full_address) LOG.debug( - "The resource referred by %s can be found in the mapped destination resources", + "The logical id of the resource referred by %s is %s", resolved_destination_resource.value, + cfn_dest_resource_logical_id, ) - dest_resources.append(LogicalIdReference(cfn_dest_resource_logical_id)) - return dest_resources + + # validate that the found dest resource is in mapped dest resources, which means that it is created. + # The resource can be defined in the TF plan configuration, but will not be created. + dest_resources: List[ReferenceType] = [] + if cfn_dest_resource_logical_id in self._resource_pair.destination_resource_tf: + LOG.debug( + "The resource referred by %s can be found in the mapped destination resources", + resolved_destination_resource.value, + ) + dest_resources.append( + LogicalIdReference( + value=cfn_dest_resource_logical_id, + resource_type=self._resource_pair.destination_resource_tf[cfn_dest_resource_logical_id].get( + "type", "" + ), + ) + ) + return dest_resources # it means the source resource is referring to a wrong destination resource type LOG.debug( "The used reference %s is not the correct destination resource type.", resolved_destination_resource.value ) - raise InvalidResourceLinkingException( + expected_destinations_strings = [ + f"destination resource type {expected_destination.terraform_resource_type_prefix} using " + f"{expected_destination.terraform_attribute_name} property" + for expected_destination in self._resource_pair.expected_destinations + ] + raise UnexpectedDestinationResource( f"Could not use the value {resolved_destination_resource.value} as a destination for the source resource " - f"{source_tf_resource.full_address}. The source resource value should refer to valid destination ARN " - f"property." + f"{source_tf_resource.full_address}. The expected destination resources should be of " + f"{', '.join(expected_destinations_strings)}." ) @@ -1011,38 +1045,70 @@ def _link_gateway_resources_to_gateway_rest_apis( Dictionary of all actual terraform Rest API resources (not configuration resources). The dictionary's key is the calculated logical id for each resource. """ - resource_linking_pairs = [ - ResourceLinkingPair( - source_resource_cfn_resource=gateway_resources_cfn_resources, - source_resource_tf_config=gateway_resources_tf_configs, - destination_resource_tf=rest_apis_terraform_resources, - tf_destination_attribute_name="id", - terraform_link_field_name="rest_api_id", - cfn_link_field_name="RestApiId", - terraform_resource_type_prefix=API_GATEWAY_REST_API_RESOURCE_ADDRESS_PREFIX, - cfn_resource_update_call_back_function=_link_gateway_resource_to_gateway_rest_apis_rest_api_id_call_back, - linking_exceptions=ResourcePairExceptions( - multiple_resource_linking_exception=OneGatewayResourceToRestApiLinkingLimitationException, - local_variable_linking_exception=GatewayResourceToGatewayRestApiLocalVariablesLinkingLimitationException, + resource_linking_pair = ResourceLinkingPair( + source_resource_cfn_resource=gateway_resources_cfn_resources, + source_resource_tf_config=gateway_resources_tf_configs, + destination_resource_tf=rest_apis_terraform_resources, + expected_destinations=[ + ResourcePairExceptedDestination( + terraform_resource_type_prefix=API_GATEWAY_REST_API_RESOURCE_ADDRESS_PREFIX, + terraform_attribute_name="id", ), + ], + terraform_link_field_name="rest_api_id", + cfn_link_field_name="RestApiId", + cfn_resource_update_call_back_function=_link_gateway_resource_to_gateway_rest_apis_rest_api_id_call_back, + linking_exceptions=ResourcePairExceptions( + multiple_resource_linking_exception=OneGatewayResourceToRestApiLinkingLimitationException, + local_variable_linking_exception=GatewayResourceToGatewayRestApiLocalVariablesLinkingLimitationException, ), - ResourceLinkingPair( - source_resource_cfn_resource=gateway_resources_cfn_resources, - source_resource_tf_config=gateway_resources_tf_configs, - destination_resource_tf=rest_apis_terraform_resources, - tf_destination_attribute_name="root_resource_id", - terraform_link_field_name="parent_id", - cfn_link_field_name="ResourceId", - terraform_resource_type_prefix=API_GATEWAY_REST_API_RESOURCE_ADDRESS_PREFIX, - cfn_resource_update_call_back_function=_link_gateway_resource_to_gateway_rest_apis_parent_id_call_back, - linking_exceptions=ResourcePairExceptions( - multiple_resource_linking_exception=OneGatewayResourceToRestApiLinkingLimitationException, - local_variable_linking_exception=GatewayResourceToGatewayRestApiLocalVariablesLinkingLimitationException, + ) + ResourceLinker(resource_linking_pair).link_resources() + + +def _link_gateway_resources_to_parents( + gateway_resources_tf_configs: Dict[str, TFResource], + gateway_resources_cfn_resources: Dict[str, List], + multiple_destination_options_terraform_resources: Dict[str, Dict], +): + """ + Iterate through all the resources and link them to the corresponding parent resource. Parent resource can either be + a Rest API resource or another API Resource resource. + + Parameters + ---------- + gateway_resources_tf_configs: Dict[str, TFResource] + Dictionary of configuration Gateway Resource resources + gateway_resources_cfn_resources: Dict[str, List] + Dictionary containing resolved configuration addresses matched up to the cfn Gateway Resource + multiple_destination_options_terraform_resources: Dict[str, Dict] + Dictionary of all actual terraform Rest API resources or Gateway Resources. The dictionary's key is the + calculated logical id for each resource. + """ + + resource_linking_pair = ResourceLinkingPair( + source_resource_cfn_resource=gateway_resources_cfn_resources, + source_resource_tf_config=gateway_resources_tf_configs, + destination_resource_tf=multiple_destination_options_terraform_resources, + expected_destinations=[ + ResourcePairExceptedDestination( + terraform_resource_type_prefix=API_GATEWAY_REST_API_RESOURCE_ADDRESS_PREFIX, + terraform_attribute_name="root_resource_id", + ), + ResourcePairExceptedDestination( + terraform_resource_type_prefix=API_GATEWAY_RESOURCE_RESOURCE_ADDRESS_PREFIX, + terraform_attribute_name="id", ), + ], + terraform_link_field_name="parent_id", + cfn_link_field_name="ParentId", + cfn_resource_update_call_back_function=_link_gateway_resource_to_parent_resource_call_back, + linking_exceptions=ResourcePairExceptions( + multiple_resource_linking_exception=OneGatewayResourceToParentResourceLinkingLimitationException, + local_variable_linking_exception=GatewayResourceToParentResourceLocalVariablesLinkingLimitationException, ), - ] - for resource_linking_pair in resource_linking_pairs: - ResourceLinker(resource_linking_pair).link_resources() + ) + ResourceLinker(resource_linking_pair).link_resources() def _link_lambda_functions_to_layers( @@ -1071,10 +1137,14 @@ def _link_lambda_functions_to_layers( source_resource_cfn_resource=lambda_funcs_conf_cfn_resources, source_resource_tf_config=lambda_config_funcs_conf_cfn_resources, destination_resource_tf=lambda_layers_terraform_resources, - tf_destination_attribute_name="arn", + expected_destinations=[ + ResourcePairExceptedDestination( + terraform_resource_type_prefix=LAMBDA_LAYER_RESOURCE_ADDRESS_PREFIX, + terraform_attribute_name="arn", + ), + ], terraform_link_field_name="layers", cfn_link_field_name="Layers", - terraform_resource_type_prefix=LAMBDA_LAYER_RESOURCE_ADDRESS_PREFIX, cfn_resource_update_call_back_function=_link_lambda_functions_to_layers_call_back, linking_exceptions=exceptions, ) @@ -1140,36 +1210,40 @@ def _link_gateway_resource_to_gateway_resource_call_back( ) -def _link_gateway_resource_to_gateway_rest_apis_parent_id_call_back( - gateway_cfn_resource: Dict, referenced_rest_apis_values: List[ReferenceType] +def _link_gateway_resource_to_parent_resource_call_back( + gateway_resource_cfn_resource: Dict, referenced_parent_resources_values: List[ReferenceType] ) -> None: """ - Callback function that used by the linking algorithm to update an Api Gateway Resource CFN Resource with - a reference to the Rest Api resource. + Callback function that is used by the linking algorithm to update an Api Gateway resource CFN with a reference to + the parent resource which either rest api or gateway resource. Parameters ---------- - gateway_cfn_resource: Dict - API Gateway Method CFN resource - referenced_rest_apis_values: List[ReferenceType] - List of referenced REST API either as the logical id of REST API resource defined in the customer project, or - ARN values for actual REST API resource defined in customer's account. This list should always contain one - element only. + gateway_resource_cfn_resource: Dict + API Gateway resource CFN resource + referenced_parent_resources_values: List[ReferenceType] + List of referenced parent resources either as the logical id of resource defined in the customer project, + or ARN values for actual parent resource defined in customer's account. This list should always contain + one element only. """ - # if the destination rest api list contains more than one element, so we have an issue in our linking logic - if len(referenced_rest_apis_values) > 1: - raise InvalidResourceLinkingException("Could not link multiple Rest APIs to one Gateway resource") + if len(referenced_parent_resources_values) > 1: + raise InvalidResourceLinkingException("Could not link multiple parent Resources to one Gateway resource") - if not referenced_rest_apis_values: - LOG.info("Unable to find any references to Rest APIs, skip linking Rest API to Gateway resource") + if not referenced_parent_resources_values: + LOG.info("Unable to find any references to the parent resource, skip linking Gateway resources") return - logical_id = referenced_rest_apis_values[0] - gateway_cfn_resource["Properties"]["ParentId"] = ( - {"Fn::GetAtt": [logical_id.value, "RootResourceId"]} - if isinstance(logical_id, LogicalIdReference) - else logical_id.value - ) + logical_id = referenced_parent_resources_values[0] + if isinstance(logical_id, LogicalIdReference): + if logical_id.resource_type == TF_AWS_API_GATEWAY_REST_API: + gateway_resource_cfn_resource["Properties"]["ParentId"] = { + "Fn::GetAtt": [logical_id.value, "RootResourceId"] + } + else: + gateway_resource_cfn_resource["Properties"]["ParentId"] = {"Ref": logical_id.value} + + else: + gateway_resource_cfn_resource["Properties"]["ParentId"] = logical_id.value def _link_gateway_methods_to_gateway_rest_apis( @@ -1199,10 +1273,14 @@ def _link_gateway_methods_to_gateway_rest_apis( source_resource_cfn_resource=gateway_methods_config_address_cfn_resources_map, source_resource_tf_config=gateway_methods_config_resources, destination_resource_tf=rest_apis_terraform_resources, - tf_destination_attribute_name="id", + expected_destinations=[ + ResourcePairExceptedDestination( + terraform_resource_type_prefix=API_GATEWAY_REST_API_RESOURCE_ADDRESS_PREFIX, + terraform_attribute_name="id", + ), + ], terraform_link_field_name="rest_api_id", cfn_link_field_name="RestApiId", - terraform_resource_type_prefix=API_GATEWAY_REST_API_RESOURCE_ADDRESS_PREFIX, cfn_resource_update_call_back_function=_link_gateway_resource_to_gateway_rest_apis_rest_api_id_call_back, linking_exceptions=exceptions, ) @@ -1235,10 +1313,14 @@ def _link_gateway_stage_to_rest_api( source_resource_cfn_resource=gateway_stages_config_address_cfn_resources_map, source_resource_tf_config=gateway_stages_config_resources, destination_resource_tf=rest_apis_terraform_resources, - tf_destination_attribute_name="id", + expected_destinations=[ + ResourcePairExceptedDestination( + terraform_resource_type_prefix=API_GATEWAY_REST_API_RESOURCE_ADDRESS_PREFIX, + terraform_attribute_name="id", + ), + ], terraform_link_field_name="rest_api_id", cfn_link_field_name="RestApiId", - terraform_resource_type_prefix=API_GATEWAY_REST_API_RESOURCE_ADDRESS_PREFIX, cfn_resource_update_call_back_function=_link_gateway_resource_to_gateway_rest_apis_rest_api_id_call_back, linking_exceptions=exceptions, ) @@ -1272,10 +1354,14 @@ def _link_gateway_method_to_gateway_resource( source_resource_cfn_resource=gateway_method_config_address_cfn_resources_map, source_resource_tf_config=gateway_method_config_resources, destination_resource_tf=gateway_resources_terraform_resources, - tf_destination_attribute_name="id", + expected_destinations=[ + ResourcePairExceptedDestination( + terraform_resource_type_prefix=API_GATEWAY_RESOURCE_RESOURCE_ADDRESS_PREFIX, + terraform_attribute_name="id", + ), + ], terraform_link_field_name="resource_id", cfn_link_field_name="ResourceId", - terraform_resource_type_prefix=API_GATEWAY_RESOURCE_RESOURCE_ADDRESS_PREFIX, cfn_resource_update_call_back_function=_link_gateway_resource_to_gateway_resource_call_back, linking_exceptions=exceptions, ) @@ -1309,10 +1395,14 @@ def _link_gateway_integrations_to_gateway_rest_apis( source_resource_cfn_resource=gateway_integrations_config_address_cfn_resources_map, source_resource_tf_config=gateway_integrations_config_resources, destination_resource_tf=rest_apis_terraform_resources, - tf_destination_attribute_name="id", + expected_destinations=[ + ResourcePairExceptedDestination( + terraform_resource_type_prefix=API_GATEWAY_REST_API_RESOURCE_ADDRESS_PREFIX, + terraform_attribute_name="id", + ), + ], terraform_link_field_name="rest_api_id", cfn_link_field_name="RestApiId", - terraform_resource_type_prefix=API_GATEWAY_REST_API_RESOURCE_ADDRESS_PREFIX, cfn_resource_update_call_back_function=_link_gateway_resource_to_gateway_rest_apis_rest_api_id_call_back, linking_exceptions=exceptions, ) @@ -1347,10 +1437,14 @@ def _link_gateway_integrations_to_gateway_resource( source_resource_cfn_resource=gateway_integrations_config_address_cfn_resources_map, source_resource_tf_config=gateway_integrations_config_resources, destination_resource_tf=gateway_resources_terraform_resources, - tf_destination_attribute_name="id", + expected_destinations=[ + ResourcePairExceptedDestination( + terraform_resource_type_prefix=API_GATEWAY_RESOURCE_RESOURCE_ADDRESS_PREFIX, + terraform_attribute_name="id", + ), + ], terraform_link_field_name="resource_id", cfn_link_field_name="ResourceId", - terraform_resource_type_prefix=API_GATEWAY_RESOURCE_RESOURCE_ADDRESS_PREFIX, cfn_resource_update_call_back_function=_link_gateway_resource_to_gateway_resource_call_back, linking_exceptions=exceptions, ) @@ -1425,10 +1519,14 @@ def _link_gateway_integrations_to_function_resource( source_resource_cfn_resource=gateway_integrations_config_address_cfn_resources_map, source_resource_tf_config=aws_proxy_integrations_config_resources, destination_resource_tf=lambda_function_terraform_resources, - tf_destination_attribute_name="invoke_arn", + expected_destinations=[ + ResourcePairExceptedDestination( + terraform_resource_type_prefix=LAMBDA_FUNCTION_RESOURCE_ADDRESS_PREFIX, + terraform_attribute_name="invoke_arn", + ), + ], terraform_link_field_name="uri", cfn_link_field_name="Uri", - terraform_resource_type_prefix=LAMBDA_FUNCTION_RESOURCE_ADDRESS_PREFIX, cfn_resource_update_call_back_function=_link_gateway_integration_to_function_call_back, linking_exceptions=exceptions, ) @@ -1464,10 +1562,14 @@ def _link_gateway_integration_responses_to_gateway_rest_apis( source_resource_cfn_resource=gateway_integration_responses_config_address_cfn_resources_map, source_resource_tf_config=gateway_integration_responses_config_resources, destination_resource_tf=rest_apis_terraform_resources, - tf_destination_attribute_name="id", + expected_destinations=[ + ResourcePairExceptedDestination( + terraform_resource_type_prefix=API_GATEWAY_REST_API_RESOURCE_ADDRESS_PREFIX, + terraform_attribute_name="id", + ), + ], terraform_link_field_name="rest_api_id", cfn_link_field_name="RestApiId", - terraform_resource_type_prefix=API_GATEWAY_REST_API_RESOURCE_ADDRESS_PREFIX, cfn_resource_update_call_back_function=_link_gateway_resource_to_gateway_rest_apis_rest_api_id_call_back, linking_exceptions=exceptions, ) @@ -1502,10 +1604,14 @@ def _link_gateway_integration_responses_to_gateway_resource( source_resource_cfn_resource=gateway_integration_responses_config_address_cfn_resources_map, source_resource_tf_config=gateway_integration_responses_config_resources, destination_resource_tf=gateway_resources_terraform_resources, - tf_destination_attribute_name="id", + expected_destinations=[ + ResourcePairExceptedDestination( + terraform_resource_type_prefix=API_GATEWAY_RESOURCE_RESOURCE_ADDRESS_PREFIX, + terraform_attribute_name="id", + ), + ], terraform_link_field_name="resource_id", cfn_link_field_name="ResourceId", - terraform_resource_type_prefix=API_GATEWAY_RESOURCE_RESOURCE_ADDRESS_PREFIX, cfn_resource_update_call_back_function=_link_gateway_resource_to_gateway_resource_call_back, linking_exceptions=exceptions, ) @@ -1571,10 +1677,14 @@ def _link_gateway_authorizer_to_lambda_function( source_resource_cfn_resource=authorizer_cfn_resources, source_resource_tf_config=authorizer_config_resources, destination_resource_tf=lamda_function_resources, - tf_destination_attribute_name="invoke_arn", + expected_destinations=[ + ResourcePairExceptedDestination( + terraform_resource_type_prefix=LAMBDA_FUNCTION_RESOURCE_ADDRESS_PREFIX, + terraform_attribute_name="invoke_arn", + ), + ], terraform_link_field_name="authorizer_uri", cfn_link_field_name="AuthorizerUri", - terraform_resource_type_prefix=LAMBDA_FUNCTION_RESOURCE_ADDRESS_PREFIX, cfn_resource_update_call_back_function=_link_gateway_authorizer_to_lambda_function_call_back, linking_exceptions=exceptions, ) @@ -1607,10 +1717,14 @@ def _link_gateway_authorizer_to_rest_api( source_resource_cfn_resource=authorizer_cfn_resources, source_resource_tf_config=authorizer_config_resources, destination_resource_tf=rest_api_resource, - tf_destination_attribute_name="id", + expected_destinations=[ + ResourcePairExceptedDestination( + terraform_resource_type_prefix=API_GATEWAY_REST_API_RESOURCE_ADDRESS_PREFIX, + terraform_attribute_name="id", + ), + ], terraform_link_field_name="rest_api_id", cfn_link_field_name="RestApiId", - terraform_resource_type_prefix=API_GATEWAY_REST_API_RESOURCE_ADDRESS_PREFIX, cfn_resource_update_call_back_function=_link_gateway_resource_to_gateway_rest_apis_rest_api_id_call_back, linking_exceptions=exceptions, ) @@ -1673,10 +1787,14 @@ def _link_gateway_method_to_gateway_authorizer( source_resource_cfn_resource=gateway_method_config_address_cfn_resources_map, source_resource_tf_config=gateway_method_config_resources, destination_resource_tf=authorizer_resources, - tf_destination_attribute_name="id", + expected_destinations=[ + ResourcePairExceptedDestination( + terraform_resource_type_prefix=API_GATEWAY_AUTHORIZER_RESOURCE_ADDRESS_PREFIX, + terraform_attribute_name="id", + ), + ], terraform_link_field_name="authorizer_id", cfn_link_field_name="AuthorizerId", - terraform_resource_type_prefix=API_GATEWAY_AUTHORIZER_RESOURCE_ADDRESS_PREFIX, cfn_resource_update_call_back_function=_link_gateway_method_to_gateway_authorizer_call_back, linking_exceptions=exceptions, ) diff --git a/samcli/hook_packages/terraform/hooks/prepare/resources/resource_links.py b/samcli/hook_packages/terraform/hooks/prepare/resources/resource_links.py index b91478580a..dc5f3080f5 100644 --- a/samcli/hook_packages/terraform/hooks/prepare/resources/resource_links.py +++ b/samcli/hook_packages/terraform/hooks/prepare/resources/resource_links.py @@ -1,6 +1,6 @@ from typing import List -from samcli.hook_packages.terraform.hooks.prepare.property_builder import ( +from samcli.hook_packages.terraform.hooks.prepare.constants import ( TF_AWS_API_GATEWAY_AUTHORIZER, TF_AWS_API_GATEWAY_INTEGRATION, TF_AWS_API_GATEWAY_INTEGRATION_RESPONSE, @@ -23,10 +23,14 @@ _link_gateway_method_to_gateway_resource, _link_gateway_methods_to_gateway_rest_apis, _link_gateway_resources_to_gateway_rest_apis, + _link_gateway_resources_to_parents, _link_gateway_stage_to_rest_api, _link_lambda_functions_to_layers, ) -from samcli.hook_packages.terraform.hooks.prepare.types import LinkingPairCaller +from samcli.hook_packages.terraform.hooks.prepare.types import ( + LinkingMultipleDestinationsOptionsCaller, + LinkingPairCaller, +) RESOURCE_LINKS: List[LinkingPairCaller] = [ LinkingPairCaller( @@ -91,3 +95,11 @@ linking_func=_link_gateway_method_to_gateway_authorizer, ), ] + +MULTIPLE_DESTINATIONS_RESOURCE_LINKS: List[LinkingMultipleDestinationsOptionsCaller] = [ + LinkingMultipleDestinationsOptionsCaller( + source=TF_AWS_API_GATEWAY_RESOURCE, + destinations=[TF_AWS_API_GATEWAY_REST_API, TF_AWS_API_GATEWAY_RESOURCE], + linking_func=_link_gateway_resources_to_parents, + ), +] diff --git a/samcli/hook_packages/terraform/hooks/prepare/resources/resource_properties.py b/samcli/hook_packages/terraform/hooks/prepare/resources/resource_properties.py index 30c31aabd0..f190eb43d2 100644 --- a/samcli/hook_packages/terraform/hooks/prepare/resources/resource_properties.py +++ b/samcli/hook_packages/terraform/hooks/prepare/resources/resource_properties.py @@ -1,7 +1,7 @@ """Module for getting the resource property mappings for various resource types""" from typing import Dict -from samcli.hook_packages.terraform.hooks.prepare.property_builder import ( +from samcli.hook_packages.terraform.hooks.prepare.constants import ( TF_AWS_API_GATEWAY_AUTHORIZER, TF_AWS_API_GATEWAY_INTEGRATION, TF_AWS_API_GATEWAY_INTEGRATION_RESPONSE, diff --git a/samcli/hook_packages/terraform/hooks/prepare/translate.py b/samcli/hook_packages/terraform/hooks/prepare/translate.py index 14f9e73733..46dcb15c97 100644 --- a/samcli/hook_packages/terraform/hooks/prepare/translate.py +++ b/samcli/hook_packages/terraform/hooks/prepare/translate.py @@ -9,16 +9,16 @@ from samcli.hook_packages.terraform.hooks.prepare.constants import ( CFN_CODE_PROPERTIES, - SAM_METADATA_RESOURCE_NAME_ATTRIBUTE, -) -from samcli.hook_packages.terraform.hooks.prepare.enrich import enrich_resources_and_generate_makefile -from samcli.hook_packages.terraform.hooks.prepare.property_builder import ( REMOTE_DUMMY_VALUE, - RESOURCE_TRANSLATOR_MAPPING, + SAM_METADATA_RESOURCE_NAME_ATTRIBUTE, TF_AWS_API_GATEWAY_INTEGRATION, TF_AWS_API_GATEWAY_INTEGRATION_RESPONSE, TF_AWS_API_GATEWAY_METHOD, TF_AWS_API_GATEWAY_REST_API, +) +from samcli.hook_packages.terraform.hooks.prepare.enrich import enrich_resources_and_generate_makefile +from samcli.hook_packages.terraform.hooks.prepare.property_builder import ( + RESOURCE_TRANSLATOR_MAPPING, PropertyBuilderMapping, ) from samcli.hook_packages.terraform.hooks.prepare.resource_linking import ( @@ -31,7 +31,10 @@ add_integrations_to_methods, ) from samcli.hook_packages.terraform.hooks.prepare.resources.internal import INTERNAL_PREFIX -from samcli.hook_packages.terraform.hooks.prepare.resources.resource_links import RESOURCE_LINKS +from samcli.hook_packages.terraform.hooks.prepare.resources.resource_links import ( + MULTIPLE_DESTINATIONS_RESOURCE_LINKS, + RESOURCE_LINKS, +) from samcli.hook_packages.terraform.hooks.prepare.resources.resource_properties import get_resource_property_mapping from samcli.hook_packages.terraform.hooks.prepare.types import ( CodeResourceProperties, @@ -339,11 +342,25 @@ def translate_to_cfn(tf_json: dict, output_directory_path: str, terraform_applic def _handle_linking(resource_property_mapping: Dict[str, ResourceProperties]) -> None: - for links in RESOURCE_LINKS: - links.linking_func( - resource_property_mapping[links.source].terraform_config, - resource_property_mapping[links.source].cfn_resources, - resource_property_mapping[links.dest].terraform_resources, + for link in RESOURCE_LINKS: + link.linking_func( + resource_property_mapping[link.source].terraform_config, + resource_property_mapping[link.source].cfn_resources, + resource_property_mapping[link.dest].terraform_resources, + ) + + for multiple_destinations_link in MULTIPLE_DESTINATIONS_RESOURCE_LINKS: + destinations: Dict[str, Dict] = {} + for dest_resource_type in multiple_destinations_link.destinations: + destinations = { + **destinations, + **resource_property_mapping[dest_resource_type].terraform_resources, + } + + multiple_destinations_link.linking_func( + resource_property_mapping[multiple_destinations_link.source].terraform_config, + resource_property_mapping[multiple_destinations_link.source].cfn_resources, + destinations, ) diff --git a/samcli/hook_packages/terraform/hooks/prepare/types.py b/samcli/hook_packages/terraform/hooks/prepare/types.py index d88c8b9103..361ddc95fd 100644 --- a/samcli/hook_packages/terraform/hooks/prepare/types.py +++ b/samcli/hook_packages/terraform/hooks/prepare/types.py @@ -88,6 +88,12 @@ class LinkingPairCaller(NamedTuple): linking_func: Callable[[Dict[str, TFResource], Dict[str, List], Dict[str, Dict]], None] +class LinkingMultipleDestinationsOptionsCaller(NamedTuple): + source: str + destinations: List[str] + linking_func: Callable[[Dict[str, TFResource], Dict[str, List], Dict[str, Dict[str, Dict]]], None] + + class ResourceTranslationValidator: """ Base class for a validation class to be used when translating Terraform resources to a metadata file diff --git a/tests/integration/local/start_api/test_start_api_with_terraform_application.py b/tests/integration/local/start_api/test_start_api_with_terraform_application.py index e8ab21d01d..8953ec780f 100644 --- a/tests/integration/local/start_api/test_start_api_with_terraform_application.py +++ b/tests/integration/local/start_api/test_start_api_with_terraform_application.py @@ -94,18 +94,29 @@ def tearDownClass(cls) -> None: not CI_OVERRIDE, "Skip Terraform test cases unless running in CI", ) +@parameterized_class( + [ + { + "terraform_application": "terraform-v1-nested-apis", + "testing_urls": ["parent/hello", "parent"], + }, + { + "terraform_application": "terraform-v1-api-simple", + "testing_urls": ["hello"], + }, + ] +) @pytest.mark.flaky(reruns=3) class TestStartApiTerraformApplication(TerraformStartApiIntegrationBase): - terraform_application = "terraform-v1-api-simple" - def setUp(self): self.url = "http://127.0.0.1:{}".format(self.port) def test_successful_request(self): - response = requests.get(self.url + "/hello", timeout=300) + for url in self.testing_urls: + response = requests.get(f"{self.url}/{url}", timeout=300) - self.assertEqual(response.status_code, 200) - self.assertEqual(response.json(), {"message": "hello world"}) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json(), {"message": "hello world"}) @skipIf( @@ -172,11 +183,21 @@ def test_unsupported_limitations(self): @pytest.mark.flaky(reruns=3) @parameterized_class( [ + { + "terraform_application": "terraform-v1-nested-apis", + "testing_urls": ["parent/hello", "parent"], + }, + { + "terraform_application": "terraform-v1-api-simple", + "testing_urls": ["hello"], + }, { "terraform_application": "terraform-api-simple-multiple-resources-limitation", + "testing_urls": ["hello"], }, { "terraform_application": "terraform-api-simple-local-variables-limitation", + "testing_urls": ["hello"], }, ] ) @@ -185,10 +206,11 @@ def setUp(self): self.url = "http://127.0.0.1:{}".format(self.port) def test_successful_request(self): - response = requests.get(self.url + "/hello", timeout=300) + for url in self.testing_urls: + response = requests.get(f"{self.url}/{url}", timeout=300) - self.assertEqual(response.status_code, 200) - self.assertEqual(response.json(), {"message": "hello world"}) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.json(), {"message": "hello world"}) @skipIf( diff --git a/tests/integration/testdata/start_api/terraform/terraform-v1-api-simple/main.tf b/tests/integration/testdata/start_api/terraform/terraform-v1-api-simple/main.tf index 7f64aca6ad..43012c539e 100644 --- a/tests/integration/testdata/start_api/terraform/terraform-v1-api-simple/main.tf +++ b/tests/integration/testdata/start_api/terraform/terraform-v1-api-simple/main.tf @@ -1,8 +1,14 @@ provider "aws" { } +resource "random_uuid" "unique_id" { + keepers = { + my_key = "my_key" + } +} + resource "aws_iam_role" "iam_for_lambda" { - name = "iam_for_lambda" + name = "iam_for_lambda_${random_uuid.unique_id.result}" assume_role_policy = <d% zj=rr_mB#73$cT&^d&Rnvd~@F3nr0UsKKwd(1On*(k|vmU$lC-Lv;C$Aq$o-7pq&E{M-q~^XxoMvJEv_l+m@7jTa9;hPw$6Vy`wtz-{!cZE_a|D; zeVDjm-otwV`j)dFmQUoFvQj%^=GxV#jB;WW`yak~>TfKv^`&=a>12=7dUs@}Yn^z} zFu?8)zcdJTqJ=t z?SE6fiLK;bUk3&I4etb<+SUg09kOvSntbo~f?C7+ga0qrO)`tl_p0VQ<7}sSdh&*g z$w~E2-%Miq^?$!E*jEv^Y;xM}6Fw>bvpuG-H<`PiX<4zU?Xji0HFNg=UgQ|py+YGt zRrH$pt#d_Oa|5T`@Htzt>Z0C$pN~`I-W@BlkX^#O$1aogyad~GpBYa?Oit|OG%Q@r zJne+QhMg=wGo;F|=4x6*KUUklYT^|>#^BDNRr{aKXiYwO@2*tqq9%TG^V?6a-djyoq`xwJ&A=1r>d(6HZAx$U$5MgY z6aJ*VtGvDB-}X1=;G`9O{2n_nZGjRH_M`<$cLKnqRg_v-npu>Zo0?ZrtXEP|LQc|U zWD;RU%@?p_4ayfVu%r>hA|aOqc%vDN None: source_resource_cfn_resource=Mock(), source_resource_tf_config=Mock(), destination_resource_tf={ - "applied_layer1_logical_id": {"values": {"arn": "applied_layer1.arn", "filename": "/some/path"}}, - "applied_layer2_logical_id": {"values": {"arn": "applied_layer2.arn", "filename": "/some/path"}}, - "noo_applied_layer3_logical_id": {"values": {"filename": "/some/path"}}, + "applied_layer1_logical_id": { + "values": {"arn": "applied_layer1.arn", "filename": "/some/path"}, + "type": TF_AWS_LAMBDA_LAYER_VERSION, + }, + "applied_layer2_logical_id": { + "values": {"arn": "applied_layer2.arn", "filename": "/some/path"}, + "type": TF_AWS_LAMBDA_LAYER_VERSION, + }, + "noo_applied_layer3_logical_id": { + "values": {"filename": "/some/path"}, + "type": TF_AWS_LAMBDA_LAYER_VERSION, + }, }, - tf_destination_attribute_name="arn", + expected_destinations=[ + ResourcePairExceptedDestination( + terraform_resource_type_prefix=LAMBDA_LAYER_RESOURCE_ADDRESS_PREFIX, terraform_attribute_name="arn" + ) + ], terraform_link_field_name="layers", cfn_link_field_name="Layers", - terraform_resource_type_prefix=LAMBDA_LAYER_RESOURCE_ADDRESS_PREFIX, cfn_resource_update_call_back_function=Mock(), linking_exceptions=self.linker_exceptions, ) @@ -1295,7 +1319,7 @@ def test_link_using_linking_fields_mix_existing_and_applied_resources(self): resource_linker = ResourceLinker(self.sample_resource_linking_pair) resource_linker._link_using_linking_fields(cfn_resource) dest_resources = [ - LogicalIdReference("applied_layer1_logical_id"), + LogicalIdReference(value="applied_layer1_logical_id", resource_type=TF_AWS_LAMBDA_LAYER_VERSION), ExistingResourceReference("existing_layer1.arn"), ] self.sample_resource_linking_pair.cfn_resource_update_call_back_function.assert_called_with( @@ -1412,11 +1436,16 @@ def test_process_reference_resource_value_reference_to_an_existing_layer_resourc reference_resolved_layer = ResolvedReference("aws_lambda_layer_version.layer.arn", "module.layer1") resource = Mock() resource_linker = ResourceLinker(self.sample_resource_linking_pair) - resource_linker._resource_pair.destination_resource_tf = {"layer1LogicalId": Mock()} + + resource_linker._resource_pair.destination_resource_tf = { + "layer1LogicalId": {"values": Mock(), "type": TF_AWS_LAMBDA_LAYER_VERSION} + } resources = resource_linker._process_reference_resource_value(resource, reference_resolved_layer) self.assertEqual(len(resources), 1) - self.assertEqual(resources[0], LogicalIdReference("layer1LogicalId")) + self.assertEqual( + resources[0], LogicalIdReference(value="layer1LogicalId", resource_type=TF_AWS_LAMBDA_LAYER_VERSION) + ) build_cfn_logical_id_mock.assert_called_with("module.layer1.aws_lambda_layer_version.layer") @patch("samcli.hook_packages.terraform.hooks.prepare.resource_linking.build_cfn_logical_id") @@ -1436,10 +1465,10 @@ def test_process_reference_layer_value_reference_to_not_layer_resource_arn_prope resource = Mock() resource.full_address = "func_full_address" expected_exception = ( - f"An error occurred when attempting to link two resources: Could not use the value " - f"aws_lambda_layer_version.layer.name as a destination resource for the source " - f"resource func_full_address. The source resource value should refer to valid destination " - f"resource ARN property." + "An error occurred when attempting to link two resources: Could not use the value " + "aws_lambda_layer_version.layer.name as a destination for the source resource func_full_address. " + "The expected destination resources should be of destination resource type aws_lambda_layer_version. " + "using arn property." ) resource_linker = ResourceLinker(self.sample_resource_linking_pair) with self.assertRaises(InvalidResourceLinkingException) as exc: @@ -1451,9 +1480,10 @@ def test_process_reference_resource_value_reference_to_invalid_destination_resou resource = Mock() resource.full_address = "func_full_address" expected_exception = ( - f"An error occurred when attempting to link two resources: Could not use the value " - f"aws_lambda_layer_version2.layer.arn as a destination for the source resource func_full_address. " - f"The source resource value should refer to valid destination ARN property." + "An error occurred when attempting to link two resources: Could not use the value " + "aws_lambda_layer_version2.layer.arn as a destination for the source resource func_full_address. " + "The expected destination resources should be of destination resource type aws_lambda_layer_version. " + "using arn property." ) resource_linker = ResourceLinker(self.sample_resource_linking_pair) with self.assertRaises(InvalidResourceLinkingException) as exc: @@ -1596,10 +1626,14 @@ def test_link_lambda_functions_to_layers( source_resource_cfn_resource=lambda_funcs_config_resources, source_resource_tf_config=resources, destination_resource_tf=terraform_layers_resources, - tf_destination_attribute_name="arn", + expected_destinations=[ + ResourcePairExceptedDestination( + terraform_resource_type_prefix=LAMBDA_LAYER_RESOURCE_ADDRESS_PREFIX, + terraform_attribute_name="arn", + ), + ], terraform_link_field_name="layers", cfn_link_field_name="Layers", - terraform_resource_type_prefix=LAMBDA_LAYER_RESOURCE_ADDRESS_PREFIX, cfn_resource_update_call_back_function=mock_link_lambda_functions_to_layers_call_back, linking_exceptions=mock_resource_linking_exceptions(), ) @@ -1613,7 +1647,10 @@ def test_link_lambda_functions_to_layers( "Properties": {"FunctionName": "func", "Layers": ["existing_layer1.arn", "applied_layer1.arn"]}, "Metadata": {"SamResourceId": "aws_lambda_function.remote_lambda_code", "SkipBuild": True}, }, - [ExistingResourceReference("existing_layer1.arn"), LogicalIdReference("Layer1LogicaId")], + [ + ExistingResourceReference("existing_layer1.arn"), + LogicalIdReference(value="Layer1LogicaId", resource_type=TF_AWS_LAMBDA_LAYER_VERSION), + ], ["existing_layer1.arn", {"Ref": "Layer1LogicaId"}], ), ( @@ -1633,7 +1670,7 @@ def test_link_lambda_functions_to_layers( }, "Metadata": {"SamResourceId": "aws_lambda_function.remote_lambda_code", "SkipBuild": True}, }, - [LogicalIdReference("Layer1LogicaId")], + [LogicalIdReference(value="Layer1LogicaId", resource_type=TF_AWS_LAMBDA_LAYER_VERSION)], [{"Ref": "Layer1LogicaId"}], ), ] @@ -1671,20 +1708,65 @@ def test_link_gateway_methods_to_gateway_rest_apis( source_resource_cfn_resource=gateway_method_config_resources, source_resource_tf_config=resources, destination_resource_tf=terraform_rest_apis_resources, - tf_destination_attribute_name="id", + expected_destinations=[ + ResourcePairExceptedDestination( + terraform_resource_type_prefix=API_GATEWAY_REST_API_RESOURCE_ADDRESS_PREFIX, + terraform_attribute_name="id", + ), + ], terraform_link_field_name="rest_api_id", cfn_link_field_name="RestApiId", - terraform_resource_type_prefix=API_GATEWAY_REST_API_RESOURCE_ADDRESS_PREFIX, cfn_resource_update_call_back_function=mock_link_gateway_methods_to_gateway_rest_apis_call_back, linking_exceptions=mock_resource_linking_exceptions(), ) mock_resource_linker.assert_called_once_with(mock_resource_linking_pair()) @patch( - "samcli.hook_packages.terraform.hooks.prepare.resource_linking._link_gateway_resource_to_gateway_rest_apis_rest_api_id_call_back" + "samcli.hook_packages.terraform.hooks.prepare.resource_linking._link_gateway_resource_to_parent_resource_call_back" ) + @patch("samcli.hook_packages.terraform.hooks.prepare.resource_linking.ResourceLinker") + @patch("samcli.hook_packages.terraform.hooks.prepare.resource_linking.ResourceLinkingPair") + @patch("samcli.hook_packages.terraform.hooks.prepare.resource_linking.ResourcePairExceptions") + def test_link_gateway_resources_to_parents( + self, + mock_resource_linking_exceptions, + mock_resource_linking_pair, + mock_resource_linker, + mock_link_gateway_resource_to_parent_resource_call_back, + ): + gateway_resource_config_resources = Mock() + terraform_parent_resources = Mock() + resources = Mock() + _link_gateway_resources_to_parents(resources, gateway_resource_config_resources, terraform_parent_resources) + + mock_resource_linking_exceptions.assert_called_once_with( + multiple_resource_linking_exception=OneGatewayResourceToParentResourceLinkingLimitationException, + local_variable_linking_exception=GatewayResourceToParentResourceLocalVariablesLinkingLimitationException, + ) + + mock_resource_linking_pair.assert_called_once_with( + source_resource_cfn_resource=gateway_resource_config_resources, + source_resource_tf_config=resources, + destination_resource_tf=terraform_parent_resources, + expected_destinations=[ + ResourcePairExceptedDestination( + terraform_resource_type_prefix=API_GATEWAY_REST_API_RESOURCE_ADDRESS_PREFIX, + terraform_attribute_name="root_resource_id", + ), + ResourcePairExceptedDestination( + terraform_resource_type_prefix=API_GATEWAY_RESOURCE_RESOURCE_ADDRESS_PREFIX, + terraform_attribute_name="id", + ), + ], + terraform_link_field_name="parent_id", + cfn_link_field_name="ParentId", + cfn_resource_update_call_back_function=mock_link_gateway_resource_to_parent_resource_call_back, + linking_exceptions=mock_resource_linking_exceptions(), + ) + mock_resource_linker.assert_called_once_with(mock_resource_linking_pair()) + @patch( - "samcli.hook_packages.terraform.hooks.prepare.resource_linking._link_gateway_resource_to_gateway_rest_apis_parent_id_call_back" + "samcli.hook_packages.terraform.hooks.prepare.resource_linking._link_gateway_resource_to_gateway_rest_apis_rest_api_id_call_back" ) @patch("samcli.hook_packages.terraform.hooks.prepare.resource_linking.ResourceLinker") @patch("samcli.hook_packages.terraform.hooks.prepare.resource_linking.ResourceLinkingPair") @@ -1694,7 +1776,6 @@ def test_link_gateway_resources_to_gateway_rest_apis( mock_resource_linking_exceptions, mock_resource_linking_pair, mock_resource_linker, - mock_link_gateway_methods_to_gateway_rest_apis_parent_id_call_back, mock_link_gateway_methods_to_gateway_rest_apis_rest_api_id_call_back, ): gateway_resource_config_resources = Mock() @@ -1703,53 +1784,28 @@ def test_link_gateway_resources_to_gateway_rest_apis( _link_gateway_resources_to_gateway_rest_apis( resources, gateway_resource_config_resources, terraform_rest_apis_resources ) - mock_resource_linking_exceptions.assert_has_calls( - [ - call( - multiple_resource_linking_exception=OneGatewayResourceToRestApiLinkingLimitationException, - local_variable_linking_exception=GatewayResourceToGatewayRestApiLocalVariablesLinkingLimitationException, - ), - call( - multiple_resource_linking_exception=OneGatewayResourceToRestApiLinkingLimitationException, - local_variable_linking_exception=GatewayResourceToGatewayRestApiLocalVariablesLinkingLimitationException, - ), - ] + + mock_resource_linking_exceptions.assert_called_once_with( + multiple_resource_linking_exception=OneGatewayResourceToRestApiLinkingLimitationException, + local_variable_linking_exception=GatewayResourceToGatewayRestApiLocalVariablesLinkingLimitationException, ) - mock_resource_linking_pair.assert_has_calls( - [ - call( - source_resource_cfn_resource=gateway_resource_config_resources, - source_resource_tf_config=resources, - destination_resource_tf=terraform_rest_apis_resources, - tf_destination_attribute_name="id", - terraform_link_field_name="rest_api_id", - cfn_link_field_name="RestApiId", - terraform_resource_type_prefix=API_GATEWAY_REST_API_RESOURCE_ADDRESS_PREFIX, - cfn_resource_update_call_back_function=mock_link_gateway_methods_to_gateway_rest_apis_rest_api_id_call_back, - linking_exceptions=mock_resource_linking_exceptions(), - ), - call( - source_resource_cfn_resource=gateway_resource_config_resources, - source_resource_tf_config=resources, - destination_resource_tf=terraform_rest_apis_resources, - tf_destination_attribute_name="root_resource_id", - terraform_link_field_name="parent_id", - cfn_link_field_name="ResourceId", + mock_resource_linking_pair.assert_called_once_with( + source_resource_cfn_resource=gateway_resource_config_resources, + source_resource_tf_config=resources, + destination_resource_tf=terraform_rest_apis_resources, + expected_destinations=[ + ResourcePairExceptedDestination( terraform_resource_type_prefix=API_GATEWAY_REST_API_RESOURCE_ADDRESS_PREFIX, - cfn_resource_update_call_back_function=mock_link_gateway_methods_to_gateway_rest_apis_parent_id_call_back, - linking_exceptions=mock_resource_linking_exceptions(), + terraform_attribute_name="id", ), - ] - ) - mock_resource_linker.assert_has_calls( - [ - call(mock_resource_linking_pair()), - call().link_resources(), - call(mock_resource_linking_pair()), - call().link_resources(), - ] + ], + terraform_link_field_name="rest_api_id", + cfn_link_field_name="RestApiId", + cfn_resource_update_call_back_function=mock_link_gateway_methods_to_gateway_rest_apis_rest_api_id_call_back, + linking_exceptions=mock_resource_linking_exceptions(), ) + mock_resource_linker.assert_called_once_with(mock_resource_linking_pair()) @patch( "samcli.hook_packages.terraform.hooks.prepare.resource_linking._link_gateway_resource_to_gateway_rest_apis_rest_api_id_call_back" @@ -1776,10 +1832,14 @@ def test_link_gateway_stage_to_gateway_rest_apis( source_resource_cfn_resource=gateway_stage_config_resources, source_resource_tf_config=resources, destination_resource_tf=terraform_rest_apis_resources, - tf_destination_attribute_name="id", + expected_destinations=[ + ResourcePairExceptedDestination( + terraform_resource_type_prefix=API_GATEWAY_REST_API_RESOURCE_ADDRESS_PREFIX, + terraform_attribute_name="id", + ), + ], terraform_link_field_name="rest_api_id", cfn_link_field_name="RestApiId", - terraform_resource_type_prefix=API_GATEWAY_REST_API_RESOURCE_ADDRESS_PREFIX, cfn_resource_update_call_back_function=mock_link_gateway_resource_to_gateway_rest_apis_call_back, linking_exceptions=mock_resource_linking_exceptions(), ) @@ -1812,10 +1872,14 @@ def test_link_gateway_methods_to_gateway_resources( source_resource_cfn_resource=gateway_method_config_resources, source_resource_tf_config=resources, destination_resource_tf=terraform_resources_resources, - tf_destination_attribute_name="id", + expected_destinations=[ + ResourcePairExceptedDestination( + terraform_resource_type_prefix=API_GATEWAY_RESOURCE_RESOURCE_ADDRESS_PREFIX, + terraform_attribute_name="id", + ), + ], terraform_link_field_name="resource_id", cfn_link_field_name="ResourceId", - terraform_resource_type_prefix=API_GATEWAY_RESOURCE_RESOURCE_ADDRESS_PREFIX, cfn_resource_update_call_back_function=mock_link_gateway_method_to_gateway_resource_call_back, linking_exceptions=mock_resource_linking_exceptions(), ) @@ -1848,10 +1912,14 @@ def test_link_gateway_integrations_to_gateway_rest_apis( source_resource_cfn_resource=gateway_integrations_config_resources, source_resource_tf_config=resources, destination_resource_tf=terraform_resources_resources, - tf_destination_attribute_name="id", + expected_destinations=[ + ResourcePairExceptedDestination( + terraform_resource_type_prefix=API_GATEWAY_REST_API_RESOURCE_ADDRESS_PREFIX, + terraform_attribute_name="id", + ), + ], terraform_link_field_name="rest_api_id", cfn_link_field_name="RestApiId", - terraform_resource_type_prefix=API_GATEWAY_REST_API_RESOURCE_ADDRESS_PREFIX, cfn_resource_update_call_back_function=mock_link_gateway_integrations_to_gateway_rest_apis, linking_exceptions=mock_resource_linking_exceptions(), ) @@ -1884,10 +1952,14 @@ def test_link_gateway_integrations_to_gateway_resource( source_resource_cfn_resource=gateway_integrations_config_resources, source_resource_tf_config=resources, destination_resource_tf=terraform_resources_resources, - tf_destination_attribute_name="id", + expected_destinations=[ + ResourcePairExceptedDestination( + terraform_resource_type_prefix=API_GATEWAY_RESOURCE_RESOURCE_ADDRESS_PREFIX, + terraform_attribute_name="id", + ), + ], terraform_link_field_name="resource_id", cfn_link_field_name="ResourceId", - terraform_resource_type_prefix=API_GATEWAY_RESOURCE_RESOURCE_ADDRESS_PREFIX, cfn_resource_update_call_back_function=mock_link_gateway_resource_to_gateway_resource_call_back, linking_exceptions=mock_resource_linking_exceptions(), ) @@ -1925,10 +1997,14 @@ def test_link_gateway_integrations_to_function_resource( source_resource_cfn_resource=gateway_integrations_config_resources, source_resource_tf_config=expected_aws_proxy_integrations, destination_resource_tf=terraform_resources_resources, - tf_destination_attribute_name="invoke_arn", + expected_destinations=[ + ResourcePairExceptedDestination( + terraform_resource_type_prefix=LAMBDA_FUNCTION_RESOURCE_ADDRESS_PREFIX, + terraform_attribute_name="invoke_arn", + ), + ], terraform_link_field_name="uri", cfn_link_field_name="Uri", - terraform_resource_type_prefix=LAMBDA_FUNCTION_RESOURCE_ADDRESS_PREFIX, cfn_resource_update_call_back_function=mock_link_gateway_integration_to_function_call_back, linking_exceptions=mock_resource_linking_exceptions(), ) @@ -1941,7 +2017,7 @@ def test_link_gateway_integrations_to_function_resource( "Type": "AWS::ApiGateway::Method", "Properties": {"HttpMethod": "post", "RestApiId": "restapi.id"}, }, - [LogicalIdReference("RestApi1")], + [LogicalIdReference(value="RestApi1", resource_type=TF_AWS_API_GATEWAY_REST_API)], {"Ref": "RestApi1"}, ), ( @@ -1957,7 +2033,7 @@ def test_link_gateway_integrations_to_function_resource( "Type": "AWS::ApiGateway::Method", "Properties": {"HttpMethod": "post"}, }, - [LogicalIdReference("RestApi1")], + [LogicalIdReference(value="RestApi1", resource_type=TF_AWS_API_GATEWAY_REST_API)], {"Ref": "RestApi1"}, ), ] @@ -1977,7 +2053,7 @@ def test_link_gateway_methods_to_gateway_rest_apis_call_back( "Type": "AWS::ApiGateway::Method", "Properties": {"HttpMethod": "post", "ResourceId": "resource.id"}, }, - [LogicalIdReference("Resource1")], + [LogicalIdReference(value="Resource1", resource_type=TF_AWS_API_GATEWAY_RESOURCE)], {"Ref": "Resource1"}, ), ( @@ -1993,7 +2069,7 @@ def test_link_gateway_methods_to_gateway_rest_apis_call_back( "Type": "AWS::ApiGateway::Method", "Properties": {"HttpMethod": "post"}, }, - [LogicalIdReference("Resource1")], + [LogicalIdReference(value="Resource1", resource_type=TF_AWS_API_GATEWAY_RESOURCE)], {"Ref": "Resource1"}, ), ] @@ -2013,7 +2089,7 @@ def test_link_gateway_method_to_gateway_resource_call_back( "Type": "AWS::ApiGateway::Resource", "Properties": {"ParentId": "restapi.parent_id"}, }, - [LogicalIdReference("RestApi")], + [LogicalIdReference(value="RestApi", resource_type=TF_AWS_API_GATEWAY_REST_API)], {"Fn::GetAtt": ["RestApi", "RootResourceId"]}, ), ( @@ -2029,7 +2105,7 @@ def test_link_gateway_method_to_gateway_resource_call_back( "Type": "AWS::ApiGateway::Resource", "Properties": {}, }, - [LogicalIdReference("RestApi")], + [LogicalIdReference(value="RestApi", resource_type=TF_AWS_API_GATEWAY_REST_API)], {"Fn::GetAtt": ["RestApi", "RootResourceId"]}, ), ] @@ -2038,7 +2114,7 @@ def test_link_gateway_resource_to_gateway_rest_api_parent_id_call_back( self, input_gateway_resource, logical_ids, expected_rest_api ): gateway_resource = deepcopy(input_gateway_resource) - _link_gateway_resource_to_gateway_rest_apis_parent_id_call_back(gateway_resource, logical_ids) + _link_gateway_resource_to_parent_resource_call_back(gateway_resource, logical_ids) input_gateway_resource["Properties"]["ParentId"] = expected_rest_api self.assertEqual(gateway_resource, input_gateway_resource) @@ -2049,7 +2125,7 @@ def test_link_gateway_resource_to_gateway_rest_api_parent_id_call_back( "Type": "Internal::ApiGateway::Method::Integration", "Properties": {"Uri": "invoke_arn"}, }, - [LogicalIdReference("FunctionA")], + [LogicalIdReference(value="FunctionA", resource_type=TF_AWS_LAMBDA_FUNCTION)], { "Fn::Sub": "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${FunctionA.Arn}/invocations" }, @@ -2067,7 +2143,7 @@ def test_link_gateway_resource_to_gateway_rest_api_parent_id_call_back( "Type": "Internal::ApiGateway::Method::Integration", "Properties": {"Uri": "invoke_arn"}, }, - [LogicalIdReference("RestApi")], + [LogicalIdReference(value="RestApi", resource_type=TF_AWS_API_GATEWAY_REST_API)], { "Fn::Sub": "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${RestApi.Arn}/invocations" }, @@ -2093,8 +2169,8 @@ def test_link_gateway_integration_to_function_call_back( "Could not link multiple Lambda functions to one Gateway Authorizer", ), ( - _link_gateway_resource_to_gateway_rest_apis_parent_id_call_back, - "Could not link multiple Rest APIs to one Gateway resource", + _link_gateway_resource_to_parent_resource_call_back, + "Could not link multiple parent Resources to one Gateway resource", ), ( _link_gateway_resource_to_gateway_resource_call_back, @@ -2118,7 +2194,7 @@ def test_linking_callbacks_raises_multiple_reference_exception(self, linking_cal [ (_link_gateway_integration_to_function_call_back,), (_link_gateway_authorizer_to_lambda_function_call_back,), - (_link_gateway_resource_to_gateway_rest_apis_parent_id_call_back,), + (_link_gateway_resource_to_parent_resource_call_back,), (_link_gateway_resource_to_gateway_resource_call_back,), (_link_gateway_resource_to_gateway_rest_apis_rest_api_id_call_back,), (_link_gateway_method_to_gateway_authorizer_call_back,), @@ -2159,10 +2235,14 @@ def test_link_gateway_integration_responses_to_gateway_rest_apis( source_resource_cfn_resource=gateway_integration_responses_config_resources, source_resource_tf_config=resources, destination_resource_tf=terraform_resources_resources, - tf_destination_attribute_name="id", + expected_destinations=[ + ResourcePairExceptedDestination( + terraform_resource_type_prefix=API_GATEWAY_REST_API_RESOURCE_ADDRESS_PREFIX, + terraform_attribute_name="id", + ), + ], terraform_link_field_name="rest_api_id", cfn_link_field_name="RestApiId", - terraform_resource_type_prefix=API_GATEWAY_REST_API_RESOURCE_ADDRESS_PREFIX, cfn_resource_update_call_back_function=mock_link_gateway_integrations_to_gateway_rest_apis, linking_exceptions=mock_resource_linking_exceptions(), ) @@ -2195,10 +2275,14 @@ def test_link_gateway_integration_response_to_gateway_resource( source_resource_cfn_resource=gateway_integration_responses_config_resources, source_resource_tf_config=resources, destination_resource_tf=terraform_resources_resources, - tf_destination_attribute_name="id", + expected_destinations=[ + ResourcePairExceptedDestination( + terraform_resource_type_prefix=API_GATEWAY_RESOURCE_RESOURCE_ADDRESS_PREFIX, + terraform_attribute_name="id", + ), + ], terraform_link_field_name="resource_id", cfn_link_field_name="ResourceId", - terraform_resource_type_prefix=API_GATEWAY_RESOURCE_RESOURCE_ADDRESS_PREFIX, cfn_resource_update_call_back_function=mock_link_gateway_resource_to_gateway_resource_call_back, linking_exceptions=mock_resource_linking_exceptions(), ) @@ -2211,7 +2295,7 @@ def test_link_gateway_integration_response_to_gateway_resource( "Type": "AWS::ApiGateway::Authorizer", "Properties": {"Uri": "invoke_arn"}, }, - [LogicalIdReference("Function")], + [LogicalIdReference(value="Function", resource_type=TF_AWS_LAMBDA_FUNCTION)], { "Fn::Sub": "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${Function.Arn}/invocations" }, @@ -2264,10 +2348,14 @@ def test_link_gateway_authorizer_to_lambda_function( source_resource_cfn_resource=authorizer_cfn_resources, source_resource_tf_config=authorizer_config_resources, destination_resource_tf=authorizer_tf_resources, - tf_destination_attribute_name="invoke_arn", + expected_destinations=[ + ResourcePairExceptedDestination( + terraform_resource_type_prefix=LAMBDA_FUNCTION_RESOURCE_ADDRESS_PREFIX, + terraform_attribute_name="invoke_arn", + ), + ], terraform_link_field_name="authorizer_uri", cfn_link_field_name="AuthorizerUri", - terraform_resource_type_prefix=LAMBDA_FUNCTION_RESOURCE_ADDRESS_PREFIX, cfn_resource_update_call_back_function=mock_link_gateway_authorizer_to_lambda_function_call_back, linking_exceptions=mock_resource_linking_exceptions(), ) @@ -2277,7 +2365,7 @@ def test_link_gateway_authorizer_to_lambda_function( @parameterized.expand( [ ( - [LogicalIdReference("Authorizer")], + [LogicalIdReference(value="Authorizer", resource_type=TF_AWS_API_GATEWAY_AUTHORIZER)], {"Ref": "Authorizer"}, ), ( @@ -2326,10 +2414,14 @@ def test_link_gateway_authorizer_to_rest_api( source_resource_cfn_resource=authorizer_cfn_resources, source_resource_tf_config=authorizer_config_resources, destination_resource_tf=rest_api_resources, - tf_destination_attribute_name="id", + expected_destinations=[ + ResourcePairExceptedDestination( + terraform_resource_type_prefix=API_GATEWAY_REST_API_RESOURCE_ADDRESS_PREFIX, + terraform_attribute_name="id", + ), + ], terraform_link_field_name="rest_api_id", cfn_link_field_name="RestApiId", - terraform_resource_type_prefix=API_GATEWAY_REST_API_RESOURCE_ADDRESS_PREFIX, cfn_resource_update_call_back_function=mock_link_resource_to_rest_api_call_back, linking_exceptions=mock_resource_linking_exceptions(), ) @@ -2366,10 +2458,14 @@ def test_link_gateway_method_to_gateway_authorizer( source_resource_cfn_resource=method_cfn_resources, source_resource_tf_config=method_config_resources, destination_resource_tf=authorizer_tf_resources, - tf_destination_attribute_name="id", + expected_destinations=[ + ResourcePairExceptedDestination( + terraform_resource_type_prefix=API_GATEWAY_AUTHORIZER_RESOURCE_ADDRESS_PREFIX, + terraform_attribute_name="id", + ), + ], terraform_link_field_name="authorizer_id", cfn_link_field_name="AuthorizerId", - terraform_resource_type_prefix=API_GATEWAY_AUTHORIZER_RESOURCE_ADDRESS_PREFIX, cfn_resource_update_call_back_function=mock_link_gateway_method_to_gateway_authorizer_call_back, linking_exceptions=mock_resource_linking_exceptions(), ) diff --git a/tests/unit/hook_packages/terraform/hooks/prepare/test_translate.py b/tests/unit/hook_packages/terraform/hooks/prepare/test_translate.py index 5ccf8bb100..56a6dbbe66 100644 --- a/tests/unit/hook_packages/terraform/hooks/prepare/test_translate.py +++ b/tests/unit/hook_packages/terraform/hooks/prepare/test_translate.py @@ -7,28 +7,31 @@ from tests.unit.hook_packages.terraform.hooks.prepare.prepare_base import PrepareHookUnitBase from samcli.hook_packages.terraform.hooks.prepare.property_builder import ( AWS_LAMBDA_FUNCTION_PROPERTY_BUILDER_MAPPING, - REMOTE_DUMMY_VALUE, AWS_API_GATEWAY_RESOURCE_PROPERTY_BUILDER_MAPPING, AWS_API_GATEWAY_REST_API_PROPERTY_BUILDER_MAPPING, AWS_API_GATEWAY_STAGE_PROPERTY_BUILDER_MAPPING, - TF_AWS_API_GATEWAY_REST_API, AWS_API_GATEWAY_METHOD_PROPERTY_BUILDER_MAPPING, + AWS_API_GATEWAY_INTEGRATION_PROPERTY_BUILDER_MAPPING, + AWS_API_GATEWAY_AUTHORIZER_PROPERTY_BUILDER_MAPPING, + AWS_API_GATEWAY_INTEGRATION_RESPONSE_PROPERTY_BUILDER_MAPPING, +) +from samcli.hook_packages.terraform.hooks.prepare.constants import ( + REMOTE_DUMMY_VALUE, TF_AWS_LAMBDA_FUNCTION, TF_AWS_LAMBDA_LAYER_VERSION, - TF_AWS_API_GATEWAY_METHOD, TF_AWS_API_GATEWAY_RESOURCE, + TF_AWS_API_GATEWAY_REST_API, TF_AWS_API_GATEWAY_STAGE, + TF_AWS_API_GATEWAY_METHOD, TF_AWS_API_GATEWAY_INTEGRATION, - AWS_API_GATEWAY_INTEGRATION_PROPERTY_BUILDER_MAPPING, TF_AWS_API_GATEWAY_AUTHORIZER, - AWS_API_GATEWAY_AUTHORIZER_PROPERTY_BUILDER_MAPPING, TF_AWS_API_GATEWAY_INTEGRATION_RESPONSE, - AWS_API_GATEWAY_INTEGRATION_RESPONSE_PROPERTY_BUILDER_MAPPING, ) from samcli.hook_packages.terraform.hooks.prepare.types import ( SamMetadataResource, LinkingPairCaller, ResourceProperties, + LinkingMultipleDestinationsOptionsCaller, ) from samcli.hook_packages.terraform.hooks.prepare.translate import ( _check_unresolvable_values, @@ -968,11 +971,18 @@ def test_check_dummy_remote_values_for_image_uri(self): def test_handle_linking(self): linking_mock_function_a = Mock() linking_mock_function_b = Mock() + linking_mock_function_c = Mock() mock_resource_links = [ LinkingPairCaller("resource_a", "resource_b", linking_mock_function_a), LinkingPairCaller("resource_b", "resource_a", linking_mock_function_b), ] + mock_multiple_destinations_resource_links = [ + LinkingMultipleDestinationsOptionsCaller( + "resource_c", ["resource_c", "resource_d"], linking_mock_function_c + ), + ] + resource_a = ResourceProperties() resource_a.cfn_resources = Mock() resource_a.terraform_resources = Mock() @@ -983,13 +993,29 @@ def test_handle_linking(self): resource_b.terraform_resources = Mock() resource_b.terraform_config = Mock() + resource_c = ResourceProperties() + resource_c.cfn_resources = Mock() + resource_c.terraform_resources = {"res_c_logical_id": Mock()} + resource_c.terraform_config = Mock() + + resource_d = ResourceProperties() + resource_d.cfn_resources = Mock() + resource_d.terraform_resources = {"res_d_logical_id": Mock()} + resource_d.terraform_config = Mock() + resource_property_mapping = { "resource_a": resource_a, "resource_b": resource_b, + "resource_c": resource_c, + "resource_d": resource_d, } with patch("samcli.hook_packages.terraform.hooks.prepare.translate.RESOURCE_LINKS", mock_resource_links): - _handle_linking(resource_property_mapping) + with patch( + "samcli.hook_packages.terraform.hooks.prepare.translate.MULTIPLE_DESTINATIONS_RESOURCE_LINKS", + mock_multiple_destinations_resource_links, + ): + _handle_linking(resource_property_mapping) linking_mock_function_a.assert_called_once_with( resource_a.terraform_config, resource_a.cfn_resources, resource_b.terraform_resources @@ -998,6 +1024,15 @@ def test_handle_linking(self): resource_b.terraform_config, resource_b.cfn_resources, resource_a.terraform_resources ) + linking_mock_function_c.assert_called_once_with( + resource_c.terraform_config, + resource_c.cfn_resources, + { + **resource_c.terraform_resources, + **resource_d.terraform_resources, + }, + ) + def test_get_s3_object_hash(self): self.assertEqual( _get_s3_object_hash(self.s3_bucket, self.s3_key), _get_s3_object_hash(self.s3_bucket, self.s3_key) From 6733ccdcd026b364cc56bd66616f767bd9635b1f Mon Sep 17 00:00:00 2001 From: Lucas <12496191+lucashuy@users.noreply.github.com> Date: Fri, 4 Aug 2023 09:45:33 -0700 Subject: [PATCH 11/13] fix: Delete stacks in REVIEW_IN_PROGRESS (#5687) * Added functionality to delete stacks in REVIEW_IN_PROGRESS * Removed setting output to variable * Addressed comments * Added disclaimer to clean up lingering resources if there are more than one change set --- samcli/commands/delete/delete_context.py | 26 +-- samcli/commands/delete/exceptions.py | 36 ++++ samcli/lib/delete/cfn_utils.py | 164 +++++++++++++++--- .../integration/delete/test_delete_command.py | 123 ++++++------- .../commands/delete/test_delete_context.py | 43 ++--- tests/unit/lib/delete/test_cfn_utils.py | 116 ++++++++++--- 6 files changed, 365 insertions(+), 143 deletions(-) diff --git a/samcli/commands/delete/delete_context.py b/samcli/commands/delete/delete_context.py index 1424c87f4a..2de317d46e 100644 --- a/samcli/commands/delete/delete_context.py +++ b/samcli/commands/delete/delete_context.py @@ -1,7 +1,6 @@ """ Delete a SAM stack """ -import json import logging from typing import Optional @@ -132,6 +131,11 @@ def init_clients(self): self.uploaders = Uploaders(self.s3_uploader, self.ecr_uploader) self.cf_utils = CfnUtils(cloudformation_client) + # Set region, this is purely for logging purposes + # the cloudformation client is able to read from + # the configuration file to get the region + self.region = self.region or cloudformation_client.meta.config.region_name + def s3_prompts(self): """ Guided prompts asking user to delete s3 artifacts @@ -218,16 +222,16 @@ def delete_ecr_companion_stack(self): """ delete_ecr_companion_stack_prompt = self.ecr_companion_stack_prompts() if delete_ecr_companion_stack_prompt or self.no_prompts: - cf_ecr_companion_stack = self.cf_utils.get_stack_template(self.companion_stack_name, TEMPLATE_STAGE) - ecr_stack_template_str = cf_ecr_companion_stack.get("TemplateBody", None) - ecr_stack_template_str = json.dumps(ecr_stack_template_str, indent=4, ensure_ascii=False) + cf_ecr_companion_stack_template = self.cf_utils.get_stack_template( + self.companion_stack_name, TEMPLATE_STAGE + ) ecr_companion_stack_template = Template( template_path=None, parent_dir=None, uploaders=self.uploaders, code_signer=None, - template_str=ecr_stack_template_str, + template_str=cf_ecr_companion_stack_template, ) retain_repos = self.ecr_repos_prompts(ecr_companion_stack_template) @@ -253,20 +257,16 @@ def delete(self): """ # Fetch the template using the stack-name cf_template = self.cf_utils.get_stack_template(self.stack_name, TEMPLATE_STAGE) - template_str = cf_template.get("TemplateBody", None) - - if isinstance(template_str, dict): - template_str = json.dumps(template_str, indent=4, ensure_ascii=False) # Get the cloudformation template name using template_str - self.cf_template_file_name = get_uploaded_s3_object_name(file_content=template_str, extension="template") + self.cf_template_file_name = get_uploaded_s3_object_name(file_content=cf_template, extension="template") template = Template( template_path=None, parent_dir=None, uploaders=self.uploaders, code_signer=None, - template_str=template_str, + template_str=cf_template, ) # If s3 info is not available, try to obtain it from CF @@ -286,7 +286,7 @@ def delete(self): # ECR companion stack delete prompts, if it exists companion_stack = CompanionStack(self.stack_name) - ecr_companion_stack_exists = self.cf_utils.has_stack(stack_name=companion_stack.stack_name) + ecr_companion_stack_exists = self.cf_utils.can_delete_stack(stack_name=companion_stack.stack_name) if ecr_companion_stack_exists: LOG.debug("ECR Companion stack found for the input stack") self.companion_stack_name = companion_stack.stack_name @@ -340,7 +340,7 @@ def run(self): ) if self.no_prompts or delete_stack: - is_deployed = self.cf_utils.has_stack(stack_name=self.stack_name) + is_deployed = self.cf_utils.can_delete_stack(stack_name=self.stack_name) # Check if the provided stack-name exists if is_deployed: LOG.debug("Input stack is deployed, continue deleting") diff --git a/samcli/commands/delete/exceptions.py b/samcli/commands/delete/exceptions.py index 5486189cf0..1b6a21f8bc 100644 --- a/samcli/commands/delete/exceptions.py +++ b/samcli/commands/delete/exceptions.py @@ -38,3 +38,39 @@ def __init__(self, stack_name, msg): message = f"Failed to fetch the template for the stack: {stack_name}, {msg}" super().__init__(message=message) + + +class FetchChangeSetError(UserException): + def __init__(self, stack_name, msg): + self.stack_name = stack_name + self.msg = msg + + message = f"Failed to fetch change sets for stack: {stack_name}, {msg}" + + super().__init__(message=message) + + +class NoChangeSetFoundError(UserException): + def __init__(self, stack_name): + self.stack_name = stack_name + + message = f"Stack {stack_name} does not contain any change sets" + + super().__init__(message=message) + + +class StackFetchError(UserException): + def __init__(self, stack_name, msg): + self.stack_name = stack_name + self.msg = msg + + message = f"Failed to complete an API call to fetch stack information for {stack_name}: {msg}" + super().__init__(message=message) + + +class StackProtectionEnabledError(UserException): + def __init__(self, stack_name): + self.stack_name = stack_name + + message = f"Stack {stack_name} cannot be deleted while TerminationProtection is enabled." + super().__init__(message=message) diff --git a/samcli/lib/delete/cfn_utils.py b/samcli/lib/delete/cfn_utils.py index 2a4389e026..40c2614bc9 100644 --- a/samcli/lib/delete/cfn_utils.py +++ b/samcli/lib/delete/cfn_utils.py @@ -3,11 +3,19 @@ """ import logging -from typing import Dict, List, Optional +from typing import List, Optional from botocore.exceptions import BotoCoreError, ClientError, WaiterError -from samcli.commands.delete.exceptions import CfDeleteFailedStatusError, DeleteFailedError, FetchTemplateFailedError +from samcli.commands.delete.exceptions import ( + CfDeleteFailedStatusError, + DeleteFailedError, + FetchChangeSetError, + FetchTemplateFailedError, + NoChangeSetFoundError, + StackFetchError, + StackProtectionEnabledError, +) LOG = logging.getLogger(__name__) @@ -16,12 +24,26 @@ class CfnUtils: def __init__(self, cloudformation_client): self._client = cloudformation_client - def has_stack(self, stack_name: str) -> bool: + def can_delete_stack(self, stack_name: str) -> bool: """ Checks if a CloudFormation stack with given name exists - :param stack_name: Name or ID of the stack - :return: True if stack exists. False otherwise + Parameters + ---------- + stack_name: str + Name or ID of the stack + + Returns + ------- + bool + True if stack exists. False otherwise + + Raises + ------ + StackFetchError + Raised when the boto call fails to get stack information + StackProtectionEnabledError + Raised when the stack is protected from deletions """ try: resp = self._client.describe_stacks(StackName=stack_name) @@ -30,14 +52,9 @@ def has_stack(self, stack_name: str) -> bool: stack = resp["Stacks"][0] if stack["EnableTerminationProtection"]: - message = "Stack cannot be deleted while TerminationProtection is enabled." - raise DeleteFailedError(stack_name=stack_name, msg=message) + raise StackProtectionEnabledError(stack_name=stack_name) - # Note: Stacks with REVIEW_IN_PROGRESS can be deleted - # using delete_stack but get_template does not return - # the template_str for this stack restricting deletion of - # artifacts. - return bool(stack["StackStatus"] != "REVIEW_IN_PROGRESS") + return True except ClientError as e: # If a stack does not exist, describe_stacks will throw an @@ -48,27 +65,52 @@ def has_stack(self, stack_name: str) -> bool: LOG.debug("Stack with id %s does not exist", stack_name) return False LOG.error("ClientError Exception : %s", str(e)) - raise DeleteFailedError(stack_name=stack_name, msg=str(e)) from e + raise StackFetchError(stack_name=stack_name, msg=str(e)) from e except BotoCoreError as e: # If there are credentials, environment errors, # catch that and throw a delete failed error. LOG.error("Botocore Exception : %s", str(e)) - raise DeleteFailedError(stack_name=stack_name, msg=str(e)) from e + raise StackFetchError(stack_name=stack_name, msg=str(e)) from e - def get_stack_template(self, stack_name: str, stage: str) -> Dict: + def get_stack_template(self, stack_name: str, stage: str) -> str: """ Return the Cloudformation template of the given stack_name - :param stack_name: Name or ID of the stack - :param stage: The Stage of the template Original or Processed - :return: Template body of the stack + Parameters + ---------- + + stack_name: str + Name or ID of the stack + stage: str + The Stage of the template Original or Processed + + Returns + ------- + str + Template body of the stack + + Raises + ------ + FetchTemplateFailedError + Raised when boto calls or parsing fails to fetch template """ try: resp = self._client.get_template(StackName=stack_name, TemplateStage=stage) - if not resp["TemplateBody"]: - return {} - return dict(resp) + template = resp.get("TemplateBody", "") + + # stack may not have template, check the change set + if not template: + change_set_name = self._get_change_set_name(stack_name) + + if change_set_name: + # the stack has a change set, use the template from this + resp = self._client.get_template( + StackName=stack_name, TemplateStage=stage, ChangeSetName=change_set_name + ) + template = resp.get("TemplateBody", "") + + return str(template) except (ClientError, BotoCoreError) as e: # If there are credentials, environment errors, @@ -76,7 +118,11 @@ def get_stack_template(self, stack_name: str, stage: str) -> Dict: LOG.error("Failed to fetch template for the stack : %s", str(e)) raise FetchTemplateFailedError(stack_name=stack_name, msg=str(e)) from e - + except FetchChangeSetError as ex: + raise FetchTemplateFailedError(stack_name=stack_name, msg=str(ex)) from ex + except NoChangeSetFoundError as ex: + msg = "Failed to find a change set to fetch the template" + raise FetchTemplateFailedError(stack_name=stack_name, msg=msg) from ex except Exception as e: # We don't know anything about this exception. Don't handle LOG.error("Unable to get stack details.", exc_info=e) @@ -86,8 +132,17 @@ def delete_stack(self, stack_name: str, retain_resources: Optional[List] = None) """ Delete the Cloudformation stack with the given stack_name - :param stack_name: Name or ID of the stack - :param retain_resources: List of repositories to retain if the stack has DELETE_FAILED status. + Parameters + ---------- + stack_name: + str Name or ID of the stack + retain_resources: Optional[List] + List of repositories to retain if the stack has DELETE_FAILED status. + + Raises + ------ + DeleteFailedError + Raised when the boto delete_stack call fails """ if not retain_resources: retain_resources = [] @@ -106,11 +161,21 @@ def delete_stack(self, stack_name: str, retain_resources: Optional[List] = None) LOG.error("Failed to delete stack. ", exc_info=e) raise e - def wait_for_delete(self, stack_name): + def wait_for_delete(self, stack_name: str): """ Waits until the delete stack completes - :param stack_name: Stack name + Parameter + --------- + stack_name: str + The name of the stack to watch when deleting + + Raises + ------ + CfDeleteFailedStatusError + Raised when the stack fails to delete + DeleteFailedError + Raised when the stack fails to wait when polling for status """ # Wait for Delete to Finish @@ -121,7 +186,7 @@ def wait_for_delete(self, stack_name): try: waiter.wait(StackName=stack_name, WaiterConfig=waiter_config) except WaiterError as ex: - stack_status = ex.last_response.get("Stacks", [{}])[0].get("StackStatusReason", "") + stack_status = ex.last_response.get("Stacks", [{}])[0].get("StackStatusReason", "") # type: ignore if "DELETE_FAILED" in str(ex): raise CfDeleteFailedStatusError( @@ -129,3 +194,48 @@ def wait_for_delete(self, stack_name): ) from ex raise DeleteFailedError(stack_name=stack_name, stack_status=stack_status, msg="ex: {0}".format(ex)) from ex + + def _get_change_set_name(self, stack_name: str) -> str: + """ + Returns the name of the change set for a stack + + Parameters + ---------- + stack_name: str + The name of the stack to find a change set + + Returns + ------- + str + The name of a change set + + Raises + ------ + FetchChangeSetError + Raised if there are boto call errors or parsing errors + NoChangeSetFoundError + Raised if a stack does not have any change sets + """ + try: + change_sets: dict = self._client.list_change_sets(StackName=stack_name) + except (ClientError, BotoCoreError) as ex: + LOG.debug("Failed to perform boto call to fetch change sets") + raise FetchChangeSetError(stack_name=stack_name, msg=str(ex)) from ex + + change_sets = change_sets.get("Summaries", []) + + if len(change_sets) > 1: + LOG.info( + "More than one change set was found, please clean up any " + "lingering template files that may exist in the S3 bucket." + ) + + if len(change_sets) > 0: + change_set = change_sets[0] + change_set_name = str(change_set.get("ChangeSetName", "")) + + LOG.debug(f"Returning change set: {change_set}") + return change_set_name + + LOG.debug("Stack contains no change sets") + raise NoChangeSetFoundError(stack_name=stack_name) diff --git a/tests/integration/delete/test_delete_command.py b/tests/integration/delete/test_delete_command.py index eb7e5e7a50..955916feea 100644 --- a/tests/integration/delete/test_delete_command.py +++ b/tests/integration/delete/test_delete_command.py @@ -8,10 +8,14 @@ from parameterized import parameterized from tests.integration.delete.delete_integ_base import DeleteIntegBase -from tests.integration.deploy.deploy_integ_base import DeployIntegBase -from tests.integration.package.package_integ_base import PackageIntegBase from tests.testing_utils import RUNNING_ON_CI, RUNNING_TEST_FOR_MASTER_ON_CI, RUN_BY_CANARY, CommandResult -from tests.testing_utils import run_command, run_command_with_input +from tests.testing_utils import ( + run_command, + run_command_with_input, + start_persistent_process, + read_until_string, + kill_process, +) # Delete tests require credentials and CI/CD will only add credentials to the env if the PR is from the same repo. # This is to restrict package tests to run outside of CI/CD, when the branch is not master or tests are not run by Canary @@ -78,10 +82,7 @@ def test_s3_options(self, template_file): self.validate_delete_process(delete_process_execute) # Check if the stack was deleted - try: - _ = self.cf_client.describe_stacks(StackName=stack_name) - except ClientError as ex: - self.assertIn(f"Stack with id {stack_name} does not exist", str(ex)) + self._validate_stack_deleted(stack_name=stack_name) # Check for zero objects in bucket s3_objects_resp = self.s3_client.list_objects_v2(Bucket=self.bucket_name, Prefix=self.s3_prefix) @@ -138,11 +139,7 @@ def test_delete_no_prompts_with_s3_prefix_present_zip(self, template_file): delete_process_execute = run_command(delete_command_list) self.validate_delete_process(delete_process_execute) - - try: - _ = self.cf_client.describe_stacks(StackName=stack_name) - except ClientError as ex: - self.assertIn(f"Stack with id {stack_name} does not exist", str(ex)) + self._validate_stack_deleted(stack_name=stack_name) # Remove the local config file created if os.path.isfile(config_file_path): @@ -173,11 +170,7 @@ def test_delete_no_prompts_with_s3_prefix_present_image(self, template_file): delete_process_execute = run_command(delete_command_list) self.validate_delete_process(delete_process_execute) - - try: - _ = self.cf_client.describe_stacks(StackName=stack_name) - except ClientError as ex: - self.assertIn(f"Stack with id {stack_name} does not exist", str(ex)) + self._validate_stack_deleted(stack_name=stack_name) # Remove the local config file created if os.path.isfile(config_file_path): @@ -204,11 +197,7 @@ def test_delete_guided_config_file_present(self, template_file): delete_process_execute = run_command_with_input(delete_command_list, "y\nn\ny\n".encode()) self.validate_delete_process(delete_process_execute) - - try: - _ = self.cf_client.describe_stacks(StackName=stack_name) - except ClientError as ex: - self.assertIn(f"Stack with id {stack_name} does not exist", str(ex)) + self._validate_stack_deleted(stack_name=stack_name) # Remove the local config file created if os.path.isfile(config_file_path): @@ -232,11 +221,7 @@ def test_delete_no_config_file_zip(self, template_file): ) delete_process_execute = run_command(delete_command_list) self.validate_delete_process(delete_process_execute) - - try: - _ = self.cf_client.describe_stacks(StackName=stack_name) - except ClientError as ex: - self.assertIn(f"Stack with id {stack_name} does not exist", str(ex)) + self._validate_stack_deleted(stack_name=stack_name) @parameterized.expand( [ @@ -270,11 +255,7 @@ def test_delete_no_prompts_no_s3_prefix_zip(self, template_file): ) delete_process_execute = run_command(delete_command_list) self.validate_delete_process(delete_process_execute) - - try: - _ = self.cf_client.describe_stacks(StackName=stack_name) - except ClientError as ex: - self.assertIn(f"Stack with id {stack_name} does not exist", str(ex)) + self._validate_stack_deleted(stack_name=stack_name) @parameterized.expand( [ @@ -310,11 +291,7 @@ def test_delete_no_prompts_no_s3_prefix_image(self, template_file): ) delete_process_execute = run_command(delete_command_list) self.validate_delete_process(delete_process_execute) - - try: - _ = self.cf_client.describe_stacks(StackName=stack_name) - except ClientError as ex: - self.assertIn(f"Stack with id {stack_name} does not exist", str(ex)) + self._validate_stack_deleted(stack_name=stack_name) @parameterized.expand( [os.path.join("deep-nested", "template.yaml"), os.path.join("deep-nested-image", "template.yaml")] @@ -349,11 +326,7 @@ def test_delete_nested_stacks(self, template_file): ) delete_process_execute = run_command(delete_command_list) self.validate_delete_process(delete_process_execute) - - try: - _ = self.cf_client.describe_stacks(StackName=stack_name) - except ClientError as ex: - self.assertIn(f"Stack with id {stack_name} does not exist", str(ex)) + self._validate_stack_deleted(stack_name=stack_name) def test_delete_stack_termination_protection_enabled(self): template_str = """ @@ -389,11 +362,7 @@ def test_delete_stack_termination_protection_enabled(self): delete_process_execute = run_command(delete_command_list) self.validate_delete_process(delete_process_execute) - - try: - _ = self.cf_client.describe_stacks(StackName=stack_name) - except ClientError as ex: - self.assertIn(f"Stack with id {stack_name} does not exist", str(ex)) + self._validate_stack_deleted(stack_name=stack_name) def test_no_prompts_no_stack_name(self): delete_command_list = self.get_delete_command_list(no_prompts=True) @@ -430,11 +399,7 @@ def test_delete_guided_ecr_repository_present(self, template_file): delete_process_execute = run_command_with_input(delete_command_list, "y\ny\ny\n".encode()) self.validate_delete_process(delete_process_execute) - - try: - _ = self.cf_client.describe_stacks(StackName=stack_name) - except ClientError as ex: - self.assertIn(f"Stack with id {stack_name} does not exist", str(ex)) + self._validate_stack_deleted(stack_name=stack_name) @parameterized.expand( [ @@ -469,11 +434,7 @@ def test_delete_guided_no_s3_prefix_image(self, template_file): delete_command_list = self.get_delete_command_list(stack_name=stack_name, region=self._session.region_name) delete_process_execute = run_command_with_input(delete_command_list, "y\n".encode()) self.validate_delete_process(delete_process_execute) - - try: - _ = self.cf_client.describe_stacks(StackName=stack_name) - except ClientError as ex: - self.assertIn(f"Stack with id {stack_name} does not exist", str(ex)) + self._validate_stack_deleted(stack_name=stack_name) @parameterized.expand( [ @@ -507,15 +468,55 @@ def test_delete_guided_retain_s3_artifact(self, template_file): self.validate_delete_process(delete_process_execute) - try: - resp = self.cf_client.describe_stacks(StackName=stack_name) - except ClientError as ex: - self.assertIn(f"Stack with id {stack_name} does not exist", str(ex)) + def test_delete_stack_review_in_progress(self): + template_path = self.test_data_path.joinpath("aws-serverless-function.yaml") + stack_name = self._method_to_stack_name(self.id()) + + deploy_command = self.get_deploy_command_list( + template_file=template_path, + stack_name=stack_name, + capabilities="CAPABILITY_IAM", + s3_bucket=self.bucket_name, + s3_prefix=self.s3_prefix, + force_upload=True, + no_execute_changeset=False, + confirm_changeset=True, + region=self._session.region_name, + ) + + # run deploy command and wait for it to ask about change set + deploy_process = start_persistent_process(deploy_command) + read_until_string(deploy_process, "Deploy this changeset? [y/N]:") + + # kill the deploy process so that the stack is stuck in REVIEW_IN_PROGRESS + kill_process(deploy_process) + + delete_command = self.get_delete_command_list( + stack_name=stack_name, region=self._session.region_name, no_prompts=True + ) + delete_result = run_command(delete_command) + + self.validate_delete_process(delete_result) + self._validate_stack_deleted(stack_name=stack_name) def validate_delete_process(self, command_result: CommandResult): self.assertEqual(command_result.process.returncode, 0) self.assertNotIn(b"Could not find and delete the S3 object with the key", command_result.stderr) + def _validate_stack_deleted(self, stack_name: str) -> None: + """ + Validates that the stack is deleted from Cloudformation + + Parameters + ---------- + stack_name: str + The name of the stack to check if it exists in Cloudformation + """ + try: + self.cf_client.describe_stacks(StackName=stack_name) + except ClientError as ex: + self.assertIn(f"Stack with id {stack_name} does not exist", str(ex)) + # TODO: Add 3 more tests after Auto ECR is merged to develop # 1. Create a stack using guided deploy of type image and delete # 2. Delete the ECR Companion Stack as input stack. diff --git a/tests/unit/commands/delete/test_delete_context.py b/tests/unit/commands/delete/test_delete_context.py index 92e2aa2c6a..d710f30ad5 100644 --- a/tests/unit/commands/delete/test_delete_context.py +++ b/tests/unit/commands/delete/test_delete_context.py @@ -1,3 +1,4 @@ +import json from samcli.lib.bootstrap.companion_stack.data_types import CompanionStack from unittest import TestCase from unittest.mock import patch, call, MagicMock, Mock @@ -19,7 +20,7 @@ class TestDeleteContext(TestCase): @patch("samcli.commands.delete.delete_context.click.echo") @patch("samcli.commands.delete.delete_context.click.get_current_context") - @patch.object(CfnUtils, "has_stack", MagicMock(return_value=(False))) + @patch.object(CfnUtils, "can_delete_stack", MagicMock(return_value=(False))) @patch("samcli.commands.delete.delete_context.get_boto_client_provider_with_config") def test_delete_context_stack_does_not_exist( self, get_boto_client_provider_mock, patched_click_get_current_context, patched_click_echo @@ -95,7 +96,7 @@ def test_delete_context_parse_config_file(self, get_boto_client_provider_mock, p @patch("samcli.commands.delete.delete_context.prompt") @patch("samcli.commands.delete.delete_context.confirm") @patch("samcli.commands.delete.delete_context.click.get_current_context") - @patch.object(CfnUtils, "has_stack", MagicMock(return_value=(False))) + @patch.object(CfnUtils, "can_delete_stack", MagicMock(return_value=(False))) @patch("samcli.commands.delete.delete_context.get_boto_client_provider_with_config") def test_delete_no_user_input( self, get_boto_client_provider_mock, patched_click_get_current_context, patched_confirm, patched_prompt @@ -137,8 +138,8 @@ def test_delete_no_user_input( ) ), ) - @patch.object(CfnUtils, "has_stack", MagicMock(return_value=(True))) - @patch.object(CfnUtils, "get_stack_template", MagicMock(return_value=({"TemplateBody": "Hello World"}))) + @patch.object(CfnUtils, "can_delete_stack", MagicMock(return_value=(True))) + @patch.object(CfnUtils, "get_stack_template", MagicMock(return_value="Hello World")) @patch.object(CfnUtils, "delete_stack", MagicMock()) @patch.object(CfnUtils, "wait_for_delete", MagicMock()) @patch.object(Template, "get_ecr_repos", MagicMock(return_value=({"logical_id": {"Repository": "test_id"}}))) @@ -159,7 +160,7 @@ def test_delete_context_valid_execute_run(self, get_boto_client_provider_mock, p ) as delete_context: delete_context.run() - self.assertEqual(CfnUtils.has_stack.call_count, 2) + self.assertEqual(CfnUtils.can_delete_stack.call_count, 2) self.assertEqual(CfnUtils.get_stack_template.call_count, 2) self.assertEqual(CfnUtils.delete_stack.call_count, 2) self.assertEqual(CfnUtils.wait_for_delete.call_count, 2) @@ -169,8 +170,8 @@ def test_delete_context_valid_execute_run(self, get_boto_client_provider_mock, p @patch("samcli.commands.delete.delete_context.click.echo") @patch("samcli.commands.deploy.guided_context.click.secho") @patch("samcli.commands.delete.delete_context.click.get_current_context") - @patch.object(CfnUtils, "has_stack", MagicMock(side_effect=(True, False))) - @patch.object(CfnUtils, "get_stack_template", MagicMock(return_value=({"TemplateBody": "Hello World"}))) + @patch.object(CfnUtils, "can_delete_stack", MagicMock(side_effect=(True, False))) + @patch.object(CfnUtils, "get_stack_template", MagicMock(return_value="Hello World")) @patch.object(CfnUtils, "delete_stack", MagicMock()) @patch.object(CfnUtils, "wait_for_delete", MagicMock()) @patch("samcli.commands.delete.delete_context.get_boto_client_provider_with_config") @@ -208,8 +209,8 @@ def test_delete_context_no_s3_bucket( @patch("samcli.commands.delete.delete_context.get_uploaded_s3_object_name") @patch("samcli.commands.delete.delete_context.confirm") @patch("samcli.commands.delete.delete_context.click.get_current_context") - @patch.object(CfnUtils, "has_stack", MagicMock(side_effect=(True, False))) - @patch.object(CfnUtils, "get_stack_template", MagicMock(return_value=({"TemplateBody": "Hello World"}))) + @patch.object(CfnUtils, "can_delete_stack", MagicMock(side_effect=(True, False))) + @patch.object(CfnUtils, "get_stack_template", MagicMock(return_value="Hello World")) @patch.object(CfnUtils, "delete_stack", MagicMock()) @patch.object(CfnUtils, "wait_for_delete", MagicMock()) @patch.object(S3Uploader, "delete_artifact", MagicMock()) @@ -270,8 +271,8 @@ def test_guided_prompts_s3_bucket_prefix_present_execute_run( @patch("samcli.commands.delete.delete_context.get_uploaded_s3_object_name") @patch("samcli.commands.delete.delete_context.confirm") @patch("samcli.commands.delete.delete_context.click.get_current_context") - @patch.object(CfnUtils, "has_stack", MagicMock(side_effect=(True, False))) - @patch.object(CfnUtils, "get_stack_template", MagicMock(return_value=({"TemplateBody": "Hello World"}))) + @patch.object(CfnUtils, "can_delete_stack", MagicMock(side_effect=(True, False))) + @patch.object(CfnUtils, "get_stack_template", MagicMock(return_value="Hello World")) @patch.object(CfnUtils, "delete_stack", MagicMock()) @patch.object(CfnUtils, "wait_for_delete", MagicMock()) @patch.object(S3Uploader, "delete_artifact", MagicMock()) @@ -323,8 +324,8 @@ def test_guided_prompts_s3_bucket_present_no_prefix_execute_run( @patch("samcli.commands.delete.delete_context.get_uploaded_s3_object_name") @patch("samcli.commands.delete.delete_context.confirm") @patch("samcli.commands.delete.delete_context.click.get_current_context") - @patch.object(CfnUtils, "has_stack", MagicMock(side_effect=(True, True))) - @patch.object(CfnUtils, "get_stack_template", MagicMock(return_value=({"TemplateBody": "Hello World"}))) + @patch.object(CfnUtils, "can_delete_stack", MagicMock(side_effect=(True, True))) + @patch.object(CfnUtils, "get_stack_template", MagicMock(return_value="Hello World")) @patch.object(CfnUtils, "delete_stack", MagicMock()) @patch.object(CfnUtils, "wait_for_delete", MagicMock()) @patch.object(S3Uploader, "delete_artifact", MagicMock()) @@ -404,8 +405,8 @@ def test_guided_prompts_ecr_companion_stack_present_execute_run( @patch("samcli.commands.delete.delete_context.get_uploaded_s3_object_name") @patch("samcli.commands.delete.delete_context.click.echo") @patch("samcli.commands.delete.delete_context.click.get_current_context") - @patch.object(CfnUtils, "has_stack", MagicMock(side_effect=(True, False))) - @patch.object(CfnUtils, "get_stack_template", MagicMock(return_value=({"TemplateBody": "Hello World"}))) + @patch.object(CfnUtils, "can_delete_stack", MagicMock(side_effect=(True, False))) + @patch.object(CfnUtils, "get_stack_template", MagicMock(return_value="Hello World")) @patch.object(CfnUtils, "delete_stack", MagicMock()) @patch.object(CfnUtils, "wait_for_delete", MagicMock()) @patch.object(S3Uploader, "delete_prefix_artifacts", MagicMock()) @@ -420,9 +421,9 @@ def test_no_prompts_input_is_ecr_companion_stack_present_execute_run( patched_click_echo, patched_get_cf_template_name, ): - CfnUtils.get_stack_template.return_value = { - "TemplateBody": {"Metadata": {"CompanionStackname": "Companion-Stack-Name"}} - } + CfnUtils.get_stack_template.return_value = json.dumps( + {"Metadata": {"CompanionStackname": "Companion-Stack-Name"}} + ) patched_get_cf_template_name.return_value = "hello.template" with DeleteContext( stack_name="Companion-Stack-Name", @@ -446,8 +447,8 @@ def test_no_prompts_input_is_ecr_companion_stack_present_execute_run( @patch("samcli.commands.delete.delete_context.get_uploaded_s3_object_name") @patch("samcli.commands.delete.delete_context.click.get_current_context") - @patch.object(CfnUtils, "has_stack", MagicMock(side_effect=(True, True))) - @patch.object(CfnUtils, "get_stack_template", MagicMock(return_value=({"TemplateBody": "Hello World"}))) + @patch.object(CfnUtils, "can_delete_stack", MagicMock(side_effect=(True, True))) + @patch.object(CfnUtils, "get_stack_template", MagicMock(return_value="Hello World")) @patch.object(CfnUtils, "delete_stack", MagicMock()) @patch.object( CfnUtils, @@ -484,7 +485,7 @@ def test_retain_resources_delete_stack( delete_context.run() - self.assertEqual(CfnUtils.has_stack.call_count, 2) + self.assertEqual(CfnUtils.can_delete_stack.call_count, 2) self.assertEqual(CfnUtils.get_stack_template.call_count, 2) self.assertEqual(CfnUtils.delete_stack.call_count, 4) self.assertEqual(CfnUtils.wait_for_delete.call_count, 4) diff --git a/tests/unit/lib/delete/test_cfn_utils.py b/tests/unit/lib/delete/test_cfn_utils.py index 7cd2474aea..6521fa80da 100644 --- a/tests/unit/lib/delete/test_cfn_utils.py +++ b/tests/unit/lib/delete/test_cfn_utils.py @@ -1,8 +1,17 @@ -from unittest.mock import patch, MagicMock, ANY, call +from unittest.mock import patch, MagicMock from unittest import TestCase +from parameterized import parameterized -from samcli.commands.delete.exceptions import DeleteFailedError, FetchTemplateFailedError, CfDeleteFailedStatusError +from samcli.commands.delete.exceptions import ( + DeleteFailedError, + FetchChangeSetError, + FetchTemplateFailedError, + CfDeleteFailedStatusError, + NoChangeSetFoundError, + StackFetchError, + StackProtectionEnabledError, +) from botocore.exceptions import ClientError, BotoCoreError, WaiterError from samcli.lib.delete.cfn_utils import CfnUtils @@ -31,44 +40,38 @@ def test_cf_utils_init(self): def test_cf_utils_has_no_stack(self): self.cf_utils._client.describe_stacks = MagicMock(return_value={"Stacks": []}) - self.assertEqual(self.cf_utils.has_stack("test"), False) + self.assertEqual(self.cf_utils.can_delete_stack("test"), False) - def test_cf_utils_has_stack_exception_non_existent(self): + def test_cf_utils_can_delete_stack_exception_non_existent(self): self.cf_utils._client.describe_stacks = MagicMock( side_effect=ClientError( error_response={"Error": {"Message": "Stack with id test does not exist"}}, operation_name="stack_status", ) ) - self.assertEqual(self.cf_utils.has_stack("test"), False) + self.assertEqual(self.cf_utils.can_delete_stack("test"), False) - def test_cf_utils_has_stack_exception_client_error(self): + def test_cf_utils_can_delete_stack_exception_client_error(self): self.cf_utils._client.describe_stacks = MagicMock( side_effect=ClientError( error_response={"Error": {"Message": "Error: The security token included in the request is expired"}}, operation_name="stack_status", ) ) - with self.assertRaises(DeleteFailedError): - self.cf_utils.has_stack("test") + with self.assertRaises(StackFetchError): + self.cf_utils.can_delete_stack("test") - def test_cf_utils_has_stack_termination_protection_enabled(self): + def test_cf_utils_can_delete_stack_termination_protection_enabled(self): self.cf_utils._client.describe_stacks = MagicMock( return_value={"Stacks": [{"StackStatus": "CREATE_COMPLETE", "EnableTerminationProtection": True}]} ) - with self.assertRaises(DeleteFailedError): - self.cf_utils.has_stack("test") - - def test_cf_utils_has_stack_in_review(self): - self.cf_utils._client.describe_stacks = MagicMock( - return_value={"Stacks": [{"StackStatus": "REVIEW_IN_PROGRESS", "EnableTerminationProtection": False}]} - ) - self.assertEqual(self.cf_utils.has_stack("test"), False) + with self.assertRaises(StackProtectionEnabledError): + self.cf_utils.can_delete_stack("test") - def test_cf_utils_has_stack_exception_botocore(self): + def test_cf_utils_can_delete_stack_exception_botocore(self): self.cf_utils._client.describe_stacks = MagicMock(side_effect=BotoCoreError()) - with self.assertRaises(DeleteFailedError): - self.cf_utils.has_stack("test") + with self.assertRaises(StackFetchError): + self.cf_utils.can_delete_stack("test") def test_cf_utils_get_stack_template_exception_client_error(self): self.cf_utils._client.get_template = MagicMock( @@ -94,7 +97,7 @@ def test_cf_utils_get_stack_template_success(self): self.cf_utils._client.get_template = MagicMock(return_value=({"TemplateBody": "Hello World"})) response = self.cf_utils.get_stack_template("test", "Original") - self.assertEqual(response, {"TemplateBody": "Hello World"}) + self.assertEqual(response, "Hello World") def test_cf_utils_delete_stack_exception_botocore(self): self.cf_utils._client.delete_stack = MagicMock(side_effect=BotoCoreError()) @@ -187,3 +190,74 @@ def test_cf_utils_wait_for_delete_failed_status(self): ) with self.assertRaises(CfDeleteFailedStatusError): self.cf_utils.wait_for_delete("test") + + def test_cfn_utils_has_stack(self): + self.cf_utils._client.describe_stacks = MagicMock( + return_value={"Stacks": [{"EnableTerminationProtection": False}]} + ) + + result = self.cf_utils.can_delete_stack(MagicMock()) + + self.assertTrue(result) + + def test_cfn_utils_get_change_set_name(self): + change_set_name = "hello change set" + + self.cf_utils._client.list_change_sets = MagicMock( + return_value={"Summaries": [{"ChangeSetName": change_set_name}]} + ) + + result = self.cf_utils._get_change_set_name(MagicMock()) + + self.assertEqual(change_set_name, result) + + def test_cfn_utils_get_change_set_name_raises_no_change_sets(self): + self.cf_utils._client.list_change_sets = MagicMock() + + with self.assertRaises(NoChangeSetFoundError): + self.cf_utils._get_change_set_name(MagicMock()) + + @parameterized.expand( + [ + (ClientError(MagicMock(), MagicMock()),), + (BotoCoreError(),), + ] + ) + def test_cfn_utils_get_change_set_name_reraises_api_error(self, exception): + self.cf_utils._client.list_change_sets = MagicMock(side_effect=exception) + + with self.assertRaises(FetchChangeSetError): + self.cf_utils._get_change_set_name(MagicMock()) + + def test_get_template_use_change_set(self): + change_set_template = "from change set" + + self.cf_utils._client.get_template = MagicMock( + side_effect=[{"TemplateBody": ""}, {"TemplateBody": change_set_template}] + ) + self.cf_utils._get_change_set_name = MagicMock(return_value=MagicMock()) + + result = self.cf_utils.get_stack_template(MagicMock(), MagicMock()) + + self.assertEqual(change_set_template, result) + + def test_get_template_use_change_set_empty(self): + self.cf_utils._client.get_template = MagicMock(return_value={"TemplateBody": ""}) + self.cf_utils._get_change_set_name = MagicMock(return_value=MagicMock()) + + result = self.cf_utils.get_stack_template(MagicMock(), MagicMock()) + + self.assertEqual(result, "") + + @parameterized.expand( + [ + (FetchChangeSetError(MagicMock(), MagicMock()),), + (NoChangeSetFoundError(MagicMock()),), + ] + ) + def test_get_change_set_reraises_exceptions(self, caught_exception): + self.cf_utils._client.get_template = MagicMock(return_value={"TemplateBody": ""}) + self.cf_utils._get_change_set_name = MagicMock(side_effect=caught_exception) + + with self.assertRaises(FetchTemplateFailedError): + self.cf_utils.get_stack_template(MagicMock(), MagicMock()) From b33386de6ca23df54d14faeabc8b0bae5afc0f2a Mon Sep 17 00:00:00 2001 From: Daniel Mil Date: Fri, 4 Aug 2023 14:44:26 -0700 Subject: [PATCH 12/13] test: AppVeyor Jobs Running Against Nightly Binaries --- appveyor-linux-binary.yml | 295 +++++++++++++++++ appveyor-windows-binary.yml | 309 ++++++++++++++++++ .../telemetry/test_experimental_metric.py | 3 + .../telemetry/test_installed_metric.py | 2 + tests/testing_utils.py | 18 + 5 files changed, 627 insertions(+) create mode 100644 appveyor-linux-binary.yml create mode 100644 appveyor-windows-binary.yml diff --git a/appveyor-linux-binary.yml b/appveyor-linux-binary.yml new file mode 100644 index 0000000000..f4a69d548f --- /dev/null +++ b/appveyor-linux-binary.yml @@ -0,0 +1,295 @@ +version: 1.0.{build} +image: + - Ubuntu2004 + +configuration: + - BuildIntegTesting + - LocalZipTerraformBuildIntegTesting + - LocalZipTerraformBuildInContainerIntegTesting + - S3ZipTerraformBuildIntegTesting + - S3ZipTerraformBuildInContainerIntegTesting + - OtherTerraformBuildIntegTesting + - DeployIntegTesting + - PackageIntegTesting + - DeleteIntegTesting + - SyncIntegTesting + - LocalIntegTesting + - EndToEndTesting + # other Integration testing, Dev, regression and smoke testing + - OtherTesting + +environment: + AWS_DEFAULT_REGION: us-east-1 + NODE_VERSION: "14.17.6" + AWS_S3: 'AWS_S3_TESTING' + AWS_ECR: 'AWS_ECR_TESTING' + CARGO_LAMBDA_VERSION: "v0.17.1" + PYTHON_ARCH: '64' + NOSE_PARAMETERIZED_NO_WARN: 1 + APPVEYOR_CONSOLE_DISABLE_PTY: false + APPVEYOR_DETAILED_SHELL_LOGGING: true + + matrix: + - PYTHON_HOME: "$HOME/venv3.11/bin" + PYTHON_VERSION: '3.11' + +install: + # AppVeyor's apt-get cache might be outdated, and the package could potentially be 404. + - sh: "sudo apt-get update --allow-releaseinfo-change" + + - sh: "gvm use go1.19" + - sh: "echo $PATH" + - sh: "ls /usr/" + # install latest maven which is compatible with jdk17 + - sh: "sudo apt-get -y remove maven" + - sh: "wget https://dlcdn.apache.org/maven/maven-3/3.8.8/binaries/apache-maven-3.8.8-bin.zip -P /tmp" + - sh: "sudo unzip -d /opt/mvn /tmp/apache-maven-*.zip" + - sh: "PATH=/opt/mvn/apache-maven-3.8.8/bin:$PATH" + - sh: "JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64" + - sh: "PATH=$JAVA_HOME/bin:$PATH" + - sh: "javac -version" + - sh: "java -version" + - sh: "mvn --version" + + - sh: "source ${HOME}/venv${PYTHON_VERSION}/bin/activate" + - sh: "rvm use 2.7.2" + - sh: "docker info" + - sh: "docker version" + - sh: "nvm install ${NODE_VERSION}" + - sh: "npm install npm@7.24.2 -g" + - sh: "npm -v" + + # Install latest gradle + - sh: "sudo apt-get -y remove gradle" + - sh: "wget https://services.gradle.org/distributions/gradle-7.3.1-bin.zip -P /tmp" + - sh: "sudo unzip -d /opt/gradle /tmp/gradle-*.zip" + - sh: "PATH=/opt/gradle/gradle-7.3.1/bin:$PATH" + + # Install AWS CLI + - sh: "virtualenv aws_cli" + - sh: "./aws_cli/bin/python -m pip install awscli" + - sh: "PATH=$(echo $PWD'/aws_cli/bin'):$PATH" + + # Install pytest + - sh: "pip3 install -r requirements/pre-dev.txt" + - sh: "pip3 install -r requirements/dev.txt" + - sh: "pip3 install -r requirements/base.txt" + - sh: "pytest --version" + + - sh: "PATH=$PATH:$HOME/venv3.7/bin:$HOME/venv3.8/bin:$HOME/venv3.9/bin:$HOME/venv3.10/bin" + + # update ca-certificates which causes failures with newest golang library + - sh: "sudo apt-get install --reinstall ca-certificates" + + # get testing env vars + - sh: "sudo apt install -y jq" + + # install Terraform + - sh: "sudo apt update --allow-releaseinfo-change" + - sh: "TER_VER=`curl -s https://api.github.com/repos/hashicorp/terraform/releases/latest | grep tag_name | cut -d: -f2 | tr -d \\\"\\,\\v | awk '{$1=$1};1'`" + - sh: "wget https://releases.hashicorp.com/terraform/${TER_VER}/terraform_${TER_VER}_linux_amd64.zip -P /tmp" + - sh: "sudo unzip -d /opt/terraform /tmp/terraform_${TER_VER}_linux_amd64.zip" + - sh: "sudo mv /opt/terraform/terraform /usr/local/bin/" + - sh: "terraform -version" + + # install Rust + - sh: "curl --proto '=https' --tlsv1.2 --retry 10 --retry-connrefused -fsSL https://sh.rustup.rs | sh -s -- --default-toolchain none -y > /dev/null 2>&1" + - sh: "source $HOME/.cargo/env" + - sh: "rustup toolchain install stable --profile minimal --no-self-update" + - sh: "rustup default stable" + - sh: "rustup target add x86_64-unknown-linux-gnu --toolchain stable" + - sh: "rustup target add aarch64-unknown-linux-gnu --toolchain stable" + - sh: "pip install cargo-lambda==$CARGO_LAMBDA_VERSION" + - sh: "rustc -V" + - sh: "cargo -V" + - sh: "cargo lambda -V" + + - sh: "python3.9 -m venv .venv_env_vars" + - sh: ".venv_env_vars/bin/pip install boto3" + - sh: "test_env_var=$(.venv_env_vars/bin/python tests/get_testing_resources.py)" + - sh: ' + if [ $? -ne 0 ]; then + echo "get_testing_resources failed. Failed to acquire credentials or test resources."; + false; + fi + ' + + - sh: 'export CI_ACCESS_ROLE_AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID' + - sh: 'export CI_ACCESS_ROLE_AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY' + - sh: 'export CI_ACCESS_ROLE_AWS_SESSION_TOKEN=$AWS_SESSION_TOKEN' + + - sh: 'export AWS_ACCESS_KEY_ID=$(echo "$test_env_var" | jq -j ".accessKeyID")' + - sh: 'export AWS_SECRET_ACCESS_KEY=$(echo "$test_env_var" | jq -j ".secretAccessKey")' + - sh: 'export AWS_SESSION_TOKEN=$(echo "$test_env_var" | jq -j ".sessionToken")' + - sh: 'export TASK_TOKEN=$(echo "$test_env_var" | jq -j ".taskToken")' + - sh: 'export AWS_S3_TESTING=$(echo "$test_env_var" | jq -j ".TestBucketName")' + - sh: 'export AWS_ECR_TESTING=$(echo "$test_env_var" | jq -j ".TestECRURI")' + - sh: 'export AWS_KMS_KEY=$(echo "$test_env_var" | jq -j ".TestKMSKeyArn")' + - sh: 'export AWS_SIGNING_PROFILE_NAME=$(echo "$test_env_var" | jq -j ".TestSigningProfileName")' + - sh: 'export AWS_SIGNING_PROFILE_VERSION_ARN=$(echo "$test_env_var" | jq -j ".TestSigningProfileARN")' + + # required for RIE with arm64 in linux + - sh: " + if [[ -n $BY_CANARY ]] && [[ -n $DOCKER_USER ]] && [[ -n $DOCKER_PASS ]]; + then echo Logging in Docker Hub; echo $DOCKER_PASS | docker login --username $DOCKER_USER --password-stdin registry-1.docker.io; + fi" + - sh: " + if [[ -n $BY_CANARY ]] && [[ -n $DOCKER_USER ]] && [[ -n $DOCKER_PASS ]]; + then echo Logging in Docker Hub; echo $DOCKER_PASS | docker login --username $DOCKER_USER --password-stdin; + fi" + - sh: "docker run --rm --privileged multiarch/qemu-user-static --reset -p yes" + + + # Runs only in Linux, logging Public ECR when running canary and cred is available + - sh: " + if [[ -n $BY_CANARY ]]; + then echo Logging in Public ECR; aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws; + fi" + + +build_script: + - curl -L https://github.com/aws/aws-sam-cli/releases/download/sam-cli-nightly/aws-sam-cli-linux-x86_64.zip -o aws-sam-cli-linux-x86_64.zip + - unzip aws-sam-cli-linux-x86_64.zip -d sam-installation + - sudo ./sam-installation/install + - sudo mv /usr/local/bin/sam-nightly /usr/local/bin/sam + - sam --version + +# Final clean up no matter success or failure +on_finish: + # Upload test reports as artifacts + - sh: find "$APPVEYOR_BUILD_FOLDER" -type f -name 'TEST_REPORT-*.json' -print0 | xargs -0 -I '{}' appveyor PushArtifact '{}' + - sh: > + AWS_ACCESS_KEY_ID=$TEST_REPORT_S3_BUCKET_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY=$TEST_REPORT_S3_BUCKET_SECRET_ACCESS_KEY + AWS_SESSION_TOKEN=$TEST_REPORT_S3_BUCKET_SESSION_TOKEN + aws s3 cp "$APPVEYOR_BUILD_FOLDER" "s3://$TEST_REPORT_S3_BUCKET_NAME/appveyor/$APPVEYOR_PROJECT_SLUG/$APPVEYOR_BUILD_ID/$APPVEYOR_JOB_ID/" --recursive --exclude "*" --include "TEST_REPORT-*.json" --region us-west-2 + + # notify task success + - sh: 'export AWS_ACCESS_KEY_ID=$CI_ACCESS_ROLE_AWS_ACCESS_KEY_ID' + - sh: 'export AWS_SECRET_ACCESS_KEY=$CI_ACCESS_ROLE_AWS_SECRET_ACCESS_KEY' + - sh: 'export AWS_SESSION_TOKEN=$CI_ACCESS_ROLE_AWS_SESSION_TOKEN' + + - sh: 'aws stepfunctions send-task-success --task-token "$TASK_TOKEN" --task-output "{}" --region us-west-2' + +for: + # Integ testing build + - + matrix: + only: + - configuration: BuildIntegTesting + + test_script: + - sh: "pytest -vv tests/integration/buildcmd --ignore=tests/integration/buildcmd/test_build_terraform_applications.py --ignore=tests/integration/buildcmd/test_build_terraform_applications_other_cases.py --json-report --json-report-file=TEST_REPORT-integration-buildcmd.json" + + # Set JAVA_HOME to java11 + - sh: "JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64" + - sh: "pytest -vv tests/integration/buildcmd/test_build_cmd.py -k test_building_java11_in_process --json-report --json-report-file=TEST_REPORT-integration-buildcmd-java11.json" + + # Local ZIP Terraform Build integ testing + - + matrix: + only: + - configuration: LocalZipTerraformBuildIntegTesting + + test_script: + - sh: "pytest -vv -n 4 tests/integration/buildcmd/test_build_terraform_applications.py::TestBuildTerraformApplicationsWithZipBasedLambdaFunctionAndLocalBackend_0 --json-report --json-report-file=TEST_REPORT-integration-buildcmd.json" + + # Local ZIP Terraform Build In Container integ testing + - + matrix: + only: + - configuration: LocalZipTerraformBuildInContainerIntegTesting + + test_script: + - sh: "pytest -vv -n 4 tests/integration/buildcmd/test_build_terraform_applications.py::TestBuildTerraformApplicationsWithZipBasedLambdaFunctionAndLocalBackend_1 --json-report --json-report-file=TEST_REPORT-integration-buildcmd.json" + + # S3 ZIP Terraform Build integ testing + - + matrix: + only: + - configuration: S3ZipTerraformBuildIntegTesting + + test_script: + - sh: "pytest -vv -n 4 tests/integration/buildcmd/test_build_terraform_applications.py::TestBuildTerraformApplicationsWithZipBasedLambdaFunctionAndS3Backend_0 --json-report --json-report-file=TEST_REPORT-integration-buildcmd.json" + + # S3 ZIP Terraform Build In Container integ testing + - + matrix: + only: + - configuration: S3ZipTerraformBuildInContainerIntegTesting + + test_script: + - sh: "pytest -vv -n 4 tests/integration/buildcmd/test_build_terraform_applications.py::TestBuildTerraformApplicationsWithZipBasedLambdaFunctionAndS3Backend_1 --json-report --json-report-file=TEST_REPORT-integration-buildcmd.json" + + # Other Terraform Build In Container integ testing + - + matrix: + only: + - configuration: OtherTerraformBuildIntegTesting + + test_script: + - sh: "pytest -vv -n 4 tests/integration/buildcmd/test_build_terraform_applications_other_cases.py --json-report --json-report-file=TEST_REPORT-integration-buildcmd.json" + + # Integ testing deploy + - + matrix: + only: + - configuration: DeployIntegTesting + + test_script: + - sh: "pytest -vv tests/integration/deploy -n 4 --reruns 4 --dist=loadgroup --json-report --json-report-file=TEST_REPORT-integration-deploy.json" + + # Integ testing package + - + matrix: + only: + - configuration: PackageIntegTesting + + test_script: + - sh: "pytest -vv tests/integration/package -n 4 --reruns 4 --json-report --json-report-file=TEST_REPORT-integration-package.json" + + # Integ testing delete + - + matrix: + only: + - configuration: DeleteIntegTesting + + test_script: + - sh: "pytest -vv tests/integration/delete -n 4 --reruns 4 --json-report --json-report-file=TEST_REPORT-integration-delete.json" + + # Integ testing sync + - + matrix: + only: + - configuration: SyncIntegTesting + + test_script: + - sh: "pytest -vv tests/integration/sync -n 3 --reruns 3 --dist loadscope --json-report --json-report-file=TEST_REPORT-integration-sync.json" + + # Integ testing local + - + matrix: + only: + - configuration: LocalIntegTesting + + test_script: + - sh: "pytest -vv tests/integration/local --json-report --json-report-file=TEST_REPORT-integration-local.json" + + # End-to-end testing + - + matrix: + only: + - configuration: EndToEndTesting + + test_script: + - sh: "pytest -vv -n 4 --reruns 5 --dist loadscope tests/end_to_end --json-report --json-report-file=TEST_REPORT-end-to-end.json" + + # Other testing + - + matrix: + only: + - configuration: OtherTesting + + test_script: + - sh: "pytest -vv -n 4 --reruns 4 --dist loadgroup tests/integration --ignore=tests/integration/buildcmd --ignore=tests/integration/delete --ignore=tests/integration/deploy --ignore=tests/integration/package --ignore=tests/integration/sync --ignore=tests/integration/local --json-report --json-report-file=TEST_REPORT-integration-others.json" + - sh: "pytest -vv tests/regression --json-report --json-report-file=TEST_REPORT-regression.json" diff --git a/appveyor-windows-binary.yml b/appveyor-windows-binary.yml new file mode 100644 index 0000000000..4cd5221819 --- /dev/null +++ b/appveyor-windows-binary.yml @@ -0,0 +1,309 @@ +version: 1.0.{build} +image: Visual Studio 2022 +build: off + +clone_folder: C:\source + +configuration: + - BuildIntegTesting + - LocalZipTerraformBuildIntegTesting + - LocalZipTerraformBuildInContainerIntegTesting + - S3ZipTerraformBuildIntegTesting + - S3ZipTerraformBuildInContainerIntegTesting + - OtherTerraformBuildIntegTesting + - DeployIntegTesting + - PackageIntegTesting + - DeleteIntegTesting + - SyncIntegTesting + - LocalIntegTesting + - EndToEndTesting + # other Integration testing, Dev, regression and smoke testing + - OtherTesting + +environment: + AWS_DEFAULT_REGION: us-east-1 + CARGO_LAMBDA_VERSION: "v0.17.1" + + # Python uses $TMPDIR envvar to find root of tempdir + TMPDIR: "%TEMP%" + TMP: "%TEMP%" + + # MSI Installers only use Py3.8. It is sufficient to test with this version here. + PYTHON_HOME: "C:\\Python38-x64" + PYTHON_SCRIPTS: "C:\\Python38-x64\\Scripts" + PYTHON_EXE: "C:\\Python38-x64\\python.exe" + PYTHON_ARCH: "64" + HOME: 'C:\Users\appveyor' + HOMEDRIVE: "C:" + HOMEPATH: 'C:\Users\appveyor' + NOSE_PARAMETERIZED_NO_WARN: 1 + AWS_S3: "AWS_S3_TESTING" + AWS_ECR: "AWS_ECR_TESTING" + APPVEYOR_CONSOLE_DISABLE_PTY: true + + SAM_WINDOWS_BINARY_PATH: "C:\\Program Files\\Amazon\\AWSSAMCLI_NIGHTLY\\bin\\sam-nightly.cmd" + +init: + # Uncomment this for RDP + # - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) + - ps: gcim Win32_Processor | % { "$($_.NumberOfLogicalProcessors) logical CPUs" } + - ps: gcim Win32_OperatingSystem | % { "$([int]($_.TotalVisibleMemorySize/1mb)) Gb" } + - git config --global core.autocrlf false + - ps: New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name "LongPathsEnabled" -Value 1 -PropertyType DWORD -Force + - ps: git config --system core.longpaths true + +cache: + - C:\ProgramData\chocolatey\bin -> appveyor.yml + - C:\ProgramData\chocolatey\lib -> appveyor.yml + +install: + # setup make + - "choco install make" + # setup Java, Maven and Gradle + - "choco install gradle -y --force" + - 'set JAVA_HOME=C:\Program Files\Java\jdk17' + - 'set PATH=%JAVA_HOME%\bin;%PATH%' + - "javac -version" + - "java -version" + - "gradle -v" + - "mvn --version" + + # Make sure the temp directory exists for Python to use. + - ps: "mkdir -Force C:\\tmp" + - 'set PATH=%PYTHON_HOME%;C:\Ruby27-x64\bin;%PATH%;C:\Python37-x64;C:\Python39-x64;C:\Python310-x64' + - "echo %PYTHON_HOME%" + - "echo %PATH%" + - "python --version" + - "docker info" + - "docker version" + + # install Terraform CLI + - "choco install terraform" + - "terraform -version" + + # Upgrade setuptools, wheel and virtualenv + - "python -m pip install --upgrade setuptools wheel virtualenv" + # Install pip for the python versions which is used by the tests + - "C:\\Python37-x64\\python.exe -m pip install --upgrade pip" + - "C:\\Python39-x64\\python.exe -m pip install --upgrade pip" + - "C:\\Python310-x64\\python.exe -m pip install --upgrade pip" + + # Install AWS CLI Globally via pip3 + - "pip install awscli" + + # Switch to Docker Linux containers + - ps: Switch-DockerLinux + + # Check for git executable + - "git --version" + + # Get testing env vars + - ps: " + If (Test-Path env:BY_CANARY){ + python -m virtualenv venv_env_vars; + ./venv_env_vars/Scripts/pip install boto3; + $test_env_var = ./venv_env_vars/Scripts/python tests/get_testing_resources.py; + $test_env_var_json = ConvertFrom-Json $test_env_var; + + $env:CI_ACCESS_ROLE_AWS_ACCESS_KEY_ID = $env:AWS_ACCESS_KEY_ID; + $env:CI_ACCESS_ROLE_AWS_SECRET_ACCESS_KEY = $env:AWS_SECRET_ACCESS_KEY; + $env:CI_ACCESS_ROLE_AWS_SESSION_TOKEN = $env:AWS_SESSION_TOKEN; + + $env:AWS_ACCESS_KEY_ID = $test_env_var_json.accessKeyID; + $env:AWS_SECRET_ACCESS_KEY = $test_env_var_json.secretAccessKey; + $env:AWS_SESSION_TOKEN = $test_env_var_json.sessionToken; + $env:TASK_TOKEN = $test_env_var_json.taskToken; + $env:AWS_S3_TESTING = $test_env_var_json.TestBucketName; + $env:AWS_ECR_TESTING = $test_env_var_json.TestECRURI; + $env:AWS_KMS_KEY = $test_env_var_json.TestKMSKeyArn; + $env:AWS_SIGNING_PROFILE_NAME = $test_env_var_json.TestSigningProfileName; + $env:AWS_SIGNING_PROFILE_VERSION_ARN = $test_env_var_json.TestSigningProfileARN; + }" + + + # Create new virtual environment with chosen python version and activate it + - "python -m virtualenv venv" + - "venv\\Scripts\\activate" + - "python --version" + + # Install testing pre-reqs without installing sam-cli from source + - pip install -r requirements/pre-dev.txt" + - pip install -r requirements/dev.txt" + - pip install -r requirements/base.txt + - pytest --version + + # Install aws cli + - "pip install awscli" + + # Install aws-sam-cli MSI binary + - ps: " + Invoke-WebRequest -Uri https://github.com/aws/aws-sam-cli/releases/download/sam-cli-nightly/AWS_SAM_CLI_64_PY3.msi -OutFile aws-sam-cli-installer.msi; + Start-Process 'C:\\Windows\\System32\\msiexec.exe' -ArgumentList '/i aws-sam-cli-installer.msi /qn /norestart' -wait -PassThru; + " + - 'set PATH=C:\Program Files\Amazon\AWSSAMCLI_NIGHTLY\bin\;%PATH%' + - 'sam-nightly --version' + + # Echo final Path + - "echo %PATH%" + + # use amazon-ecr-credential-helper + - choco install amazon-ecr-credential-helper + - ps: " + $docker_config = Get-Content $env:HOME/.docker/config.json -raw | ConvertFrom-Json; + $docker_config.credsStore = 'ecr-login'; + $docker_config | ConvertTo-Json | set-content $env:HOME/.docker/config.json; + " + - ps: "get-content $env:HOME/.docker/config.json" + + # claim some disk space before starting the tests + - "docker system prune -a -f" + + +# Final clean up no matter success or failure +on_finish: + # Upload test reports as artifacts + - ps: Get-ChildItem .\TEST_REPORT-*.json | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name } + - ps: ' + If (Test-Path env:BY_CANARY){ + $env:AWS_ACCESS_KEY_ID = $env:TEST_REPORT_S3_BUCKET_ACCESS_KEY_ID; + $env:AWS_SECRET_ACCESS_KEY = $env:TEST_REPORT_S3_BUCKET_SECRET_ACCESS_KEY; + $env:AWS_SESSION_TOKEN = $env:TEST_REPORT_S3_BUCKET_SESSION_TOKEN; + aws s3 cp ".\" "s3://$env:TEST_REPORT_S3_BUCKET_NAME/appveyor/$env:APPVEYOR_PROJECT_SLUG/$env:APPVEYOR_BUILD_ID/$env:APPVEYOR_JOB_ID/" --recursive --exclude "*" --include "TEST_REPORT-*.json" --region us-west-2 + }' + + # notify success + - ps: " + If (Test-Path env:BY_CANARY){ + $env:AWS_ACCESS_KEY_ID = $env:CI_ACCESS_ROLE_AWS_ACCESS_KEY_ID; + $env:AWS_SECRET_ACCESS_KEY = $env:CI_ACCESS_ROLE_AWS_SECRET_ACCESS_KEY; + $env:AWS_SESSION_TOKEN = $env:CI_ACCESS_ROLE_AWS_SESSION_TOKEN; + aws stepfunctions send-task-success --task-token \"$env:TASK_TOKEN\" --task-output \"{}\" --region us-west-2; + }" + + +for: + #Integ testing build, regression + - matrix: + only: + - configuration: BuildIntegTesting + + build_script: + # install Rust in build_script to not override the default "install" actions + - appveyor-retry appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe + - rustup-init.exe -y --default-host x86_64-pc-windows-msvc --default-toolchain stable + - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin + - set RUST_BACKTRACE=1 + - rustup toolchain install stable --profile minimal --no-self-update + - rustup default stable + - rustup target add x86_64-unknown-linux-gnu --toolchain stable + - rustup target add aarch64-unknown-linux-gnu --toolchain stable + - ps: "choco install zig" + - ps: Invoke-WebRequest -Uri https://github.com/cargo-lambda/cargo-lambda/releases/download/$env:CARGO_LAMBDA_VERSION/cargo-lambda-$env:CARGO_LAMBDA_VERSION.windows-x64.zip -OutFile C:\Users\appveyor\cargo-lambda.zip + - ps: Expand-Archive -DestinationPath C:\Users\appveyor\.cargo\bin C:\Users\appveyor\cargo-lambda.zip + - rustc -V + - cargo -V + - cargo lambda -V + + test_script: + - ps: "pytest -vv tests/integration/buildcmd --ignore tests/integration/buildcmd/test_build_terraform_applications.py --ignore=tests/integration/buildcmd/test_build_terraform_applications_other_cases.py --json-report --json-report-file=TEST_REPORT-integration-buildcmd.json" + + # Local ZIP Terraform Build integ testing + - matrix: + only: + - configuration: LocalZipTerraformBuildIntegTesting + + test_script: + - ps: "pytest -vv -n 4 tests/integration/buildcmd/test_build_terraform_applications.py::TestBuildTerraformApplicationsWithZipBasedLambdaFunctionAndLocalBackend_0 --json-report --json-report-file=TEST_REPORT-integration-buildcmd.json" + + # Local ZIP Terraform Build In Container integ testing + - matrix: + only: + - configuration: LocalZipTerraformBuildInContainerIntegTesting + + test_script: + - ps: "pytest -vv tests/integration/buildcmd/test_build_terraform_applications.py::TestBuildTerraformApplicationsWithZipBasedLambdaFunctionAndLocalBackend_1 --json-report --json-report-file=TEST_REPORT-integration-buildcmd.json" + + # S3 ZIP Terraform Build integ testing + - matrix: + only: + - configuration: S3ZipTerraformBuildIntegTesting + + test_script: + - ps: "pytest -vv -n 4 tests/integration/buildcmd/test_build_terraform_applications.py::TestBuildTerraformApplicationsWithZipBasedLambdaFunctionAndS3Backend_0 --json-report --json-report-file=TEST_REPORT-integration-buildcmd.json" + + # S3 ZIP Terraform Build In Container integ testing + - matrix: + only: + - configuration: S3ZipTerraformBuildInContainerIntegTesting + + test_script: + - ps: "pytest -vv tests/integration/buildcmd/test_build_terraform_applications.py::TestBuildTerraformApplicationsWithZipBasedLambdaFunctionAndS3Backend_1 --json-report --json-report-file=TEST_REPORT-integration-buildcmd.json" + + # Other Terraform Build integ testing + - matrix: + only: + - configuration: OtherTerraformBuildIntegTesting + + test_script: + - ps: "pytest -vv -n 4 tests/integration/buildcmd/test_build_terraform_applications_other_cases.py --json-report --json-report-file=TEST_REPORT-integration-buildcmd.json" + + #Integ testing deploy + - matrix: + only: + - configuration: DeployIntegTesting + + test_script: + - ps: "pytest -vv tests/integration/deploy -n 4 --reruns 4 --dist=loadgroup --json-report --json-report-file=TEST_REPORT-integration-deploy.json" + + # Integ testing package + - matrix: + only: + - configuration: PackageIntegTesting + + test_script: + - ps: "pytest -vv tests/integration/package -n 4 --reruns 4 --json-report --json-report-file=TEST_REPORT-integration-package.json" + + # Integ testing delete + - matrix: + only: + - configuration: DeleteIntegTesting + + test_script: + - ps: "pytest -vv tests/integration/delete -n 4 --reruns 4 --json-report --json-report-file=TEST_REPORT-integration-delete.json" + + # Integ testing sync + - matrix: + only: + - configuration: SyncIntegTesting + + test_script: + - ps: "pytest -vv tests/integration/sync -n 3 --reruns 3 --dist loadscope --json-report --json-report-file=TEST_REPORT-integration-sync.json" + + #Integ testing local + - matrix: + only: + - configuration: LocalIntegTesting + + test_script: + - ps: "pytest -vv tests/integration/local --json-report --json-report-file=TEST_REPORT-integration-local.json" + + # End-to-end testing + - matrix: + only: + - configuration: EndToEndTesting + + test_script: + - ps: "pytest -vv -n 4 --reruns 5 --dist loadscope tests/end_to_end --json-report --json-report-file=TEST_REPORT-end-to-end.json" + + #Other testing + - matrix: + only: + - configuration: OtherTesting + + test_script: + - ps: "pytest -vv -n 4 --reruns 4 --dist loadgroup tests/integration --ignore=tests/integration/buildcmd --ignore=tests/integration/delete --ignore=tests/integration/deploy --ignore=tests/integration/package --ignore=tests/integration/sync --ignore=tests/integration/local --json-report --json-report-file=TEST_REPORT-integration-others.json" + - ps: "pytest -vv tests/regression --json-report --json-report-file=TEST_REPORT-regression.json" +# Uncomment for RDP +# on_finish: +# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) + diff --git a/tests/integration/telemetry/test_experimental_metric.py b/tests/integration/telemetry/test_experimental_metric.py index 702ceb4a5f..1c8ca5b223 100644 --- a/tests/integration/telemetry/test_experimental_metric.py +++ b/tests/integration/telemetry/test_experimental_metric.py @@ -7,6 +7,7 @@ from .integ_base import IntegBase, TelemetryServer from samcli import __version__ as SAM_CLI_VERSION +from ...testing_utils import strip_nightly_installer_suffix class TestExperimentalMetric(IntegBase): @@ -162,6 +163,7 @@ def test_must_send_cdk_project_type_metrics(self): for req in all_requests: if "commandRun" in req["data"]["metrics"][0]: request = req # We're only testing the commandRun metric + strip_nightly_installer_suffix(request, "commandRun") self.assertIn("Content-Type", request["headers"]) self.assertEqual(request["headers"]["Content-Type"], "application/json") @@ -216,6 +218,7 @@ def test_must_send_not_experimental_metrics_if_not_experimental(self): # commandRun metric will be first or second, so we sort for consistency. all_requests.sort(key=lambda x: list(x["data"]["metrics"][0].keys())[0]) request = all_requests[0] # "commandRun" comes before "events" + strip_nightly_installer_suffix(request, "commandRun") self.assertIn("Content-Type", request["headers"]) self.assertEqual(request["headers"]["Content-Type"], "application/json") diff --git a/tests/integration/telemetry/test_installed_metric.py b/tests/integration/telemetry/test_installed_metric.py index 725a2d0ff5..0b0d2d550e 100644 --- a/tests/integration/telemetry/test_installed_metric.py +++ b/tests/integration/telemetry/test_installed_metric.py @@ -3,6 +3,7 @@ from unittest.mock import ANY from .integ_base import IntegBase, TelemetryServer, EXPECTED_TELEMETRY_PROMPT from samcli import __version__ as SAM_CLI_VERSION +from ...testing_utils import strip_nightly_installer_suffix class TestSendInstalledMetric(IntegBase): @@ -32,6 +33,7 @@ def test_send_installed_metric_on_first_run(self): requests = filter_installed_metric_requests(all_requests) self.assertEqual(1, len(requests), "There should be only one 'installed' metric") request = requests[0] + strip_nightly_installer_suffix(request, "installed") self.assertIn("Content-Type", request["headers"]) self.assertEqual(request["headers"]["Content-Type"], "application/json") diff --git a/tests/testing_utils.py b/tests/testing_utils.py index a52898f90b..aa281091cf 100644 --- a/tests/testing_utils.py +++ b/tests/testing_utils.py @@ -11,6 +11,8 @@ from subprocess import Popen, PIPE, TimeoutExpired from queue import Queue +from samcli import __version__ as SAM_CLI_VERSION + import shutil from uuid import uuid4 @@ -44,6 +46,9 @@ def get_sam_command(): + windows_bin_path = os.getenv("SAM_WINDOWS_BINARY_PATH") + if windows_bin_path: + return windows_bin_path return "samdev" if os.getenv("SAM_CLI_DEV") else "sam" @@ -242,6 +247,19 @@ def _get_current_account_id(): return account_id +def strip_nightly_installer_suffix(request: dict, metric_type: str): + """ + If it's a nightly release version, it will have a suffix. + We can strip it for the purpose of testing telemetry. + """ + metrics = request.get("data", {}).get("metrics", []) + if not metrics: + return + version = metrics[0].get(metric_type, {}).get("samcliVersion", "") + if version: + request["data"]["metrics"][0][metric_type]["samcliVersion"] = version[: len(SAM_CLI_VERSION)] + + class UpdatableSARTemplate: """ This class is used to replace the `${AWS::AccountId}` in the testing templates with the account id for the testing From f87d9be6a1f8d728634f8d255159c42bf7d2f347 Mon Sep 17 00:00:00 2001 From: Daniel Mil Date: Fri, 4 Aug 2023 16:57:14 -0700 Subject: [PATCH 13/13] Install deps into a virtual env --- appveyor-linux-binary.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/appveyor-linux-binary.yml b/appveyor-linux-binary.yml index f4a69d548f..5e4e849dce 100644 --- a/appveyor-linux-binary.yml +++ b/appveyor-linux-binary.yml @@ -71,9 +71,11 @@ install: - sh: "PATH=$(echo $PWD'/aws_cli/bin'):$PATH" # Install pytest - - sh: "pip3 install -r requirements/pre-dev.txt" - - sh: "pip3 install -r requirements/dev.txt" - - sh: "pip3 install -r requirements/base.txt" + - sh: "virtualenv pytest" + - sh: "./pytest/bin/python -m pip install -r requirements/pre-dev.txt" + - sh: "./pytest/bin/python -m pip install -r requirements/dev.txt" + - sh: "./pytest/bin/python -m pip install -r requirements/base.txt" + - sh: "PATH=$(echo $PWD'/pytest/bin'):$PATH" - sh: "pytest --version" - sh: "PATH=$PATH:$HOME/venv3.7/bin:$HOME/venv3.8/bin:$HOME/venv3.9/bin:$HOME/venv3.10/bin"