Skip to content

Commit

Permalink
Bypass python version runtime check when code run in docker (zappa#1180)
Browse files Browse the repository at this point in the history
* ✨ Handle spaces in x-forwared-for (zappa#1127)

* 🔥 remove `six` (no longer needed as 2.x is no longer supported)

* ✅ add testcase for SUPPORTED_VERSION check to increase code coverage.

* 🎨 run black/isort

* 🔧 rename function for clarity

* 🔥 remove unnecessary import

* 🔧 change name of unused mock instance

* ✨ (zappa#879) Fix url decoding for query string

* 🔧 change docstring type multi-line comment to standard multiline comment
✨ handle case where "requestContext" is not provided by the event.

> Systems calling the Lambda (other than API Gateway) may not provide the field requestContext in the event.

✅ add testcases

* 🔥 remove duplicate comment

* 📝 add docstring to util function, `get_unsupported_sys_versioninfo()`

* ✨ Add any python version support in the case where code is run in docker

* 🎨 run black/isort

* ✅ fix testcase
✅ update testcase to output the full filepath of file you are expected to compare the README.md to.

* 🔧 Add python minor version check when using docker.

* 🎨 fix flake8

* 🔧 don't limit the upper version of zappa on setup.  Internal checks will perform version check, but docker based installs shouldn't be capped.
  • Loading branch information
monkut authored and Ian288 committed Jul 11, 2023
1 parent 4bc65c3 commit 7cb1e17
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 13 deletions.
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,20 @@ This creates a new archive, uploads it to S3 and updates the Lambda function to

#### Docker Workflows

In [version 0.53.0](https://github.com/zappa/Zappa/blob/master/CHANGELOG.md), support was added to deploy & update Lambda functions using Docker. Refer to [the blog post](https://ianwhitestone.work/zappa-serverless-docker/) for more details about how to leverage this functionality, and when you may want to.
In [version 0.53.0](https://github.com/zappa/Zappa/blob/master/CHANGELOG.md), support was added to deploy & update Lambda functions using Docker.

You can specify an ECR image using the `--docker-image-uri` option to the zappa command on `deploy` and `update`.
Zappa expects that the image is built and pushed to a Amazon ECR repository.

Deploy Example:

$ zappa deploy --docker-image-uri {AWS ACCOUNT ID}.dkr.ecr.{REGION}.amazonaws.com/{REPOSITORY NAME}:latest

Update Example:

$ zappa update --docker-image-uri {AWS ACCOUNT ID}.dkr.ecr.{REGION}.amazonaws.com/{REPOSITORY NAME}:latest

Refer to [the blog post](https://ianwhitestone.work/zappa-serverless-docker/) for more details about how to leverage this functionality, and when you may want to.

### Rollback

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
version=__version__,
packages=["zappa"],
install_requires=required,
python_requires=">=3.7, <3.10",
python_requires=">=3.7",
tests_require=test_required,
test_suite="nose.collector",
include_package_data=True,
Expand Down
27 changes: 25 additions & 2 deletions tests/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import unittest
import uuid
import zipfile
from functools import partial
from io import BytesIO
from subprocess import check_output

Expand Down Expand Up @@ -40,7 +41,7 @@
)
from zappa.wsgi import common_log, create_wsgi_request

from .utils import get_unsupported_sys_versioninfo
from .utils import get_sys_versioninfo


def random_string(length):
Expand Down Expand Up @@ -2553,7 +2554,7 @@ def test_delete_lambda_concurrency(self, client):
FunctionName="abc",
)

@mock.patch("sys.version_info", new_callable=get_unsupported_sys_versioninfo)
@mock.patch("sys.version_info", new_callable=get_sys_versioninfo)
def test_unsupported_version_error(self, *_):
from importlib import reload

Expand All @@ -2562,6 +2563,28 @@ def test_unsupported_version_error(self, *_):

reload(zappa)

@mock.patch("pathlib.Path.read_text", return_value="/docker/")
@mock.patch("sys.version_info", new_callable=partial(get_sys_versioninfo, 6))
def test_minor_version_only_check_when_in_docker(self, *_):
from importlib import reload

with self.assertRaises(RuntimeError):
import zappa

reload(zappa)

@mock.patch("pathlib.Path.read_text", return_value="/docker/")
@mock.patch("sys.version_info", new_callable=partial(get_sys_versioninfo, 7))
def test_no_runtimeerror_when_in_docker(self, *_):
from importlib import reload

try:
import zappa

reload(zappa)
except RuntimeError:
self.fail()

def test_wsgi_query_string_unquoted(self):
event = {
"body": {},
Expand Down
5 changes: 3 additions & 2 deletions tests/tests_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,11 @@ def test_readmetoc(self):
)

if environ.get("ZAPPA_TEST_SAVE_README_NEW"):
with open(path.join(path.dirname(DIR), "README.test.md"), "w") as f:
readme_test_output_filepath = path.join(path.dirname(DIR), "README.test.md")
with open(readme_test_output_filepath, "w") as f:
f.write(new_readme)

msg = "README.test.md written so you can manually compare."
msg = f"{readme_test_output_filepath} written so you can manually compare."

else:
msg = "You can set environ[ZAPPA_TEST_SAVE_README_NEW]=1 to generate\n" " README.test.md to manually compare."
Expand Down
6 changes: 3 additions & 3 deletions tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def is_base64(test_string: str) -> bool:
return False


def get_unsupported_sys_versioninfo() -> tuple:
"""Mock used to test the python unsupported version testcase"""
def get_sys_versioninfo(minor_version: int = 6) -> tuple:
"""Mock used to test the python version check testcases"""
invalid_versioninfo = namedtuple("version_info", ["major", "minor", "micro", "releaselevel", "serial"])
return invalid_versioninfo(3, 6, 1, "final", 0)
return invalid_versioninfo(3, minor_version, 1, "final", 0)
32 changes: 28 additions & 4 deletions zappa/__init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,36 @@
import sys
from pathlib import Path


def running_in_docker() -> bool:
"""
Determine if zappa is running in docker.
- When docker is used allow usage of any python version
"""
# https://stackoverflow.com/a/20012536/24718
cgroup_content = Path("/proc/1/cgroup").read_text()
in_docker = "/docker/" in cgroup_content or "/lxc/" in cgroup_content
return in_docker


SUPPORTED_VERSIONS = [(3, 7), (3, 8), (3, 9)]
MINIMUM_SUPPORTED_MINOR_VERSION = 7

if sys.version_info[:2] not in SUPPORTED_VERSIONS:
if not running_in_docker() and sys.version_info[:2] not in SUPPORTED_VERSIONS:
print(running_in_docker())
formatted_supported_versions = ["{}.{}".format(*version) for version in SUPPORTED_VERSIONS]
err_msg = "This version of Python ({}.{}) is not supported!\n".format(
*sys.version_info
) + "Zappa (and AWS Lambda) support the following versions of Python: {}".format(formatted_supported_versions)
err_msg = (
f"This version of Python ({sys.version_info.major}.{sys.version_info.minor}) is not supported!\n"
f"Zappa (and AWS Lambda) support the following versions of Python: {formatted_supported_versions}"
)
raise RuntimeError(err_msg)
elif running_in_docker() and sys.version_info.minor < MINIMUM_SUPPORTED_MINOR_VERSION:
# when running in docker enforce minimum version only
err_msg = (
f"This version of Python ({sys.version_info.major}.{sys.version_info.minor}) is not supported!\n"
f"Zappa requires a minimum version of 3.{MINIMUM_SUPPORTED_MINOR_VERSION}"
)
raise RuntimeError(err_msg)


__version__ = "0.55.0"

0 comments on commit 7cb1e17

Please sign in to comment.