diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 422cd3a0a9..7fded9266b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -141,6 +141,7 @@ jobs: 3.9 3.10 3.11 + 3.12 ${{ matrix.python }} - uses: actions/setup-go@v4 with: @@ -157,7 +158,11 @@ jobs: - uses: actions/setup-java@v3 with: distribution: 'corretto' - java-version: '17' + java-version: | + 8 + 11 + 17 + 21 # Install and configure Rust & Cargo Lambda - name: Install and configure Rust & Cargo Lambda if: ${{ matrix.os == 'ubuntu-latest' }} @@ -172,6 +177,19 @@ jobs: pip install cargo-lambda==$CARGO_LAMBDA_VERSION echo "$HOME/.local/bin" >> $GITHUB_PATH + - name: Upgrade pip in Python3.12 (Linux) + run: | + python3.12 -m pip install pip --upgrade + python3.12 -m pip install setuptools --upgrade + if: ${{ matrix.os == 'ubuntu-latest' }} + + - name: Upgrade pip in Python3.12 (Windows) + run: | + py -3.12 -m pip install pip --upgrade + py -3.12 -m pip install setuptools --upgrade + if: ${{ matrix.os == 'windows-latest' }} + + - name: Init samdev run: make init - name: Run integration tests for ${{ matrix.tests_config }} @@ -231,6 +249,7 @@ jobs: 3.9 3.10 3.11 + 3.12 - name: Stop Docker Linux if: ${{ matrix.os == 'ubuntu-latest' }} run: | @@ -241,6 +260,16 @@ jobs: if: ${{ matrix.os == 'windows-latest' }} shell: pwsh run: stop-service docker + - name: Upgrade pip in Python3.12 (Linux) + run: | + python3.12 -m pip install pip --upgrade + python3.12 -m pip install setuptools --upgrade + if: ${{ matrix.os == 'ubuntu-latest' }} + - name: Upgrade pip in Python3.12 (Windows) + run: | + py -3.12 -m pip install pip --upgrade + py -3.12 -m pip install setuptools --upgrade + if: ${{ matrix.os == 'windows-latest' }} - name: Check Docker not Running run: docker info id: run-docker-info diff --git a/pytest.ini b/pytest.ini index bbdd3d7ed7..1f186fe400 100644 --- a/pytest.ini +++ b/pytest.ini @@ -9,6 +9,8 @@ filterwarnings = ignore::DeprecationWarning:docker ignore::DeprecationWarning:urllib3.poolmanager default::ResourceWarning +; Ignore below warning to not fail in Python3.12. Remove once dateutil updates itself or botocore use another way to generate EPOCH + ignore::DeprecationWarning:dateutil.tz.tz: ; The following deprecation warnings are treated as failures unless we explicitly tell pytest not to ; Remove once we no longer support python3.7 ignore::boto3.exceptions.PythonDeprecationWarning @@ -19,4 +21,4 @@ markers = java python provided - dotnet \ No newline at end of file + dotnet diff --git a/requirements/base.txt b/requirements/base.txt index 790da82013..7dcdf21723 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -6,12 +6,12 @@ jmespath~=1.0.1 ruamel_yaml~=0.18.5 PyYAML~=6.0,>=6.0.1 cookiecutter~=2.4.0 -aws-sam-translator==1.79.0 +aws-sam-translator==1.80.0 #docker minor version updates can include breaking changes. Auto update micro version only. docker~=6.1.0 dateparser~=1.1 requests~=2.31.0 -aws_lambda_builders==1.41.0 +aws_lambda_builders==1.42.0 tomlkit==0.12.2 watchdog==3.0.0 rich~=13.6.0 @@ -31,4 +31,4 @@ tzlocal==5.2 cfn-lint~=0.83.1 # Type checking boto3 objects -boto3-stubs[apigateway,cloudformation,ecr,iam,lambda,s3,schemas,secretsmanager,signer,stepfunctions,sts,xray,sqs,kinesis]==1.28.80 +boto3-stubs[apigateway,cloudformation,ecr,iam,lambda,s3,schemas,secretsmanager,signer,stepfunctions,sts,xray,sqs,kinesis]==1.29.0 diff --git a/requirements/reproducible-linux.txt b/requirements/reproducible-linux.txt index ed3acf8832..a671b20c03 100644 --- a/requirements/reproducible-linux.txt +++ b/requirements/reproducible-linux.txt @@ -20,13 +20,13 @@ attrs==23.1.0 \ # jsonschema # referencing # sarif-om -aws-lambda-builders==1.41.0 \ - --hash=sha256:b26280609269696d4c7ebe6ea208de5d02a8e4f14711ceac265510e28de65258 \ - --hash=sha256:d48d0d9b704319cdb6bb19918a72bf6c06fd3a7012848f6bcc4b906d5686db17 +aws-lambda-builders==1.42.0 \ + --hash=sha256:c0d3c4e1d9d663ccc9d13470487958fd4cc0918610786a454759b8d383a10043 \ + --hash=sha256:f2d6dc0ca6cb454d4419b8df1e2a5b4dc4973484a16b809bdb8e00620f95e6af # via aws-sam-cli (setup.py) -aws-sam-translator==1.79.0 \ - --hash=sha256:6f0c6bbcebcc98c4f98dc238352a06b0befe7fb72535cca75712fffff4873875 \ - --hash=sha256:990f3043d00b6fd801b38ad780ecd058c315b7581b2e43fc013c9b6253f876e8 +aws-sam-translator==1.80.0 \ + --hash=sha256:36afb8b802af0180a35efa68a8ab19d5d929d0a6a649a0101e8a4f8e1f05681f \ + --hash=sha256:f00215f9314cef1bbbdbd7520e3b0c75a76b88bdc3f0dedb6a2c69a12e904b12 # via # aws-sam-cli (setup.py) # cfn-lint @@ -38,27 +38,27 @@ blinker==1.7.0 \ --hash=sha256:c3f865d4d54db7abc53758a01601cf343fe55b84c1de4e3fa910e420b438d5b9 \ --hash=sha256:e6820ff6fa4e4d1d8e2747c2283749c3f547e4fee112b98555cdcdae32996182 # via flask -boto3==1.28.80 \ - --hash=sha256:2f43e032ab804a3c39996d524003d2b906e5d86856a32da3427e36912a22d2b7 \ - --hash=sha256:c48c6e04e43f894881b883a28fd032f16805f6cb2771b85f0c97f3fe34db0a41 +boto3==1.29.0 \ + --hash=sha256:3e90ea2faa3e9892b9140f857911f9ef0013192a106f50d0ec7b71e8d1afc90a \ + --hash=sha256:91c72fa4848eda9311c273db667946bd9d953285ae8d54b7bbad541b74adc254 # via # aws-sam-cli (setup.py) # aws-sam-translator -boto3-stubs[apigateway,cloudformation,ecr,iam,kinesis,lambda,s3,schemas,secretsmanager,signer,sqs,stepfunctions,sts,xray]==1.28.80 \ - --hash=sha256:544bcf2e1c32f34ca445948d7594af37325704476765c01bf5934cedc8efd8bc \ - --hash=sha256:b9a995abb8dd698865d48a12fdd64385b658f5014f22c329ac5de15e6165c178 +boto3-stubs[apigateway,cloudformation,ecr,iam,kinesis,lambda,s3,schemas,secretsmanager,signer,sqs,stepfunctions,sts,xray]==1.29.0 \ + --hash=sha256:897cb22cbf7971809cac10470121ac194a5cc57d5fb3d8bfec09e07b3cb7646b \ + --hash=sha256:e0ffd497ebd63b5d66b7eeef3192201be5453e8e5f449c864dd23877cf18fe3e # via # aws-sam-cli (setup.py) # boto3-stubs -botocore==1.31.80 \ - --hash=sha256:1c693c0f8b2553fcbe0df223241191e6f9f60b4245d65c1822c08f659274fef2 \ - --hash=sha256:d43fe303530c12efca9be4ec3a9104e8a669f11d1ba9feb18f0284d751a9672c +botocore==1.32.0 \ + --hash=sha256:95fe3357b9ddc4559941dbea0f0a6b8fc043305f013b7ae2a85dff0c3b36ee92 \ + --hash=sha256:9c1e143feb6a04235cec342d2acb31a0f44df3c89f309f839e03e38a75f3f44e # via # boto3 # s3transfer -botocore-stubs==1.31.80 \ - --hash=sha256:72472310a21171425f738fe13c26fc2fa0a890bbaf8bb89f82d464e9acb9dd2c \ - --hash=sha256:873349ae1d5dc306e08be41eb890d907074b4369bbff9a65e1247c3752923429 +botocore-stubs==1.32.0 \ + --hash=sha256:6b854253820fe080451753442cd9ee1b89ed36cfe0d452a222fff1c8e490c2b0 \ + --hash=sha256:90acea20f9e9f5838ec8330568915d10c8fc1e2c34967bc0988f7b8ab1e09822 # via boto3-stubs certifi==2023.7.22 \ --hash=sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082 \ @@ -388,61 +388,61 @@ mpmath==1.3.0 \ --hash=sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f \ --hash=sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c # via sympy -mypy-boto3-apigateway==1.28.36 \ - --hash=sha256:aa2c710c7fcc505f4c0a0c851bf872c1426b948d23314d3bcf27ee09e46c9ba7 \ - --hash=sha256:e460e5b40b28fbe292f842993e7bf3ad514d0073774b30f1c5e137de6abac681 +mypy-boto3-apigateway==1.29.0 \ + --hash=sha256:2f905563c4b96c2e22e6cbaa2f85cf732d405ac4d60b6c6c70675bea717f895a \ + --hash=sha256:e43a402334f5d2b5e91de23f7d496b72730e7445302147cc4ca6f2bd1214650f # via boto3-stubs -mypy-boto3-cloudformation==1.28.64 \ - --hash=sha256:b353d52a5607c54d2916f4bde26e9be90920635beb9ffb9255cd862dca3b56bf \ - --hash=sha256:f5c9012d7fbf9c39bb314ac192e14115dbca9495e364479a16e1fa21cac23d78 +mypy-boto3-cloudformation==1.29.0 \ + --hash=sha256:91b7202a439d31f7e6645f34ea810f1900f23214900fdf6de210a0704c14da70 \ + --hash=sha256:b719c35be8b4d5606e9b4fd66d4d0c0e3d5eaf9508a72099053c8e0640b652af # via boto3-stubs -mypy-boto3-ecr==1.28.45 \ - --hash=sha256:3584a19a018bacd7b6e8147bc9ef6932967815c0918c6cf3929ff55f1c9be601 \ - --hash=sha256:d603236d984182dcf7f196517753679fbe6a3fd05feb4c3c1d2f325b065384dc +mypy-boto3-ecr==1.29.0 \ + --hash=sha256:513c13f6a8ce6ac6cbc6127e533cd5780a8b98dfc9823576b6e0c633328618c0 \ + --hash=sha256:cecdfa399f1970deab9b3dc2e57228d976b87b62fc7f81424319a85d41d21835 # via boto3-stubs -mypy-boto3-iam==1.28.79 \ - --hash=sha256:9dca1b7a3052b512dac7d4c9a58b713d5c53e216dd2c396eb64c75b083ed0727 \ - --hash=sha256:b5f8bce0d34966c917445e002c51c7e0cde553bfa62f44b131ceb52d82fec45e +mypy-boto3-iam==1.29.0 \ + --hash=sha256:26b617b134ed0a1011b0ccc7e94792899591f19ae2f0e9305789a0d1c7f5a427 \ + --hash=sha256:629495854a1608e137a0ef01f0f30247082148b554533ccfaba4e13f33bb7ebb # via boto3-stubs -mypy-boto3-kinesis==1.28.36 \ - --hash=sha256:43713c0ce8f63b2cbd181132e71371031bd90eac250aef7357b239d4da6b8504 \ - --hash=sha256:ab37194c4f69fead34f1ba12dfa520ad6c1aed9236316df453e9f3c873f2420a +mypy-boto3-kinesis==1.29.0 \ + --hash=sha256:3e91c91b984399f8b1610b76dce94f9c3dc7ef6020bebb129ff51af23a83447a \ + --hash=sha256:45fd67bc4147a19ca6511f992241844ff88c28c9e1d66f9a99d77bd8ac29ee31 # via boto3-stubs -mypy-boto3-lambda==1.28.63 \ - --hash=sha256:7cbbee5560f347548a8f43324b31b2abfa1f56ec7380f20dadb837533fc0552a \ - --hash=sha256:bcfc747594704664d41fb904f59e4173c718d1bffc92555fc9ca57f8c4b1b970 +mypy-boto3-lambda==1.29.0 \ + --hash=sha256:cc3f4dee77181feb2a1ec90f72258a32bdc75f83d01b3c637ca791073279d3e5 \ + --hash=sha256:e4537261f7b675b1c165a7dc04d4b661f2f338a45e57bd2bee92d9a41a9cd407 # via boto3-stubs -mypy-boto3-s3==1.28.55 \ - --hash=sha256:11a3db97398973d4ae28489b94c010778a0a5c65f99e00268456c3fea67eca79 \ - --hash=sha256:b008809f448e74075012d4fc54b0176de0b4f49bc38e39de30ca0e764eb75056 +mypy-boto3-s3==1.29.0 \ + --hash=sha256:3c8473974e304aa512abbf6a47454d9834674e89db414545e2f0cb4fcdd227c9 \ + --hash=sha256:f5040429b0c3814c6ec9c1a59256976186acb7376fd3b56c4e7e5d03272bb1a8 # via boto3-stubs -mypy-boto3-schemas==1.28.36 \ - --hash=sha256:82af1ad64d0c1275c576607920f13dcc7605d6b7e8483dd58aced8395c824d5f \ - --hash=sha256:ec2648ae282cbd5efd4cd0e866d2e0fee0b73bfc4ce8273484e4194582e688d4 +mypy-boto3-schemas==1.29.0 \ + --hash=sha256:2332f348ffcb7544e76a84bba0b82cd3d47c2dff3e000176a3818aac6d9c8908 \ + --hash=sha256:590fe23c13a2fa129f25e8b37285061d6264f4aed53ac26fcbcf1aace29775b4 # via boto3-stubs -mypy-boto3-secretsmanager==1.28.67 \ - --hash=sha256:37d34d2e038164bda8beb605bcc7133ef49f058e08102f5699f8d20790ead3f0 \ - --hash=sha256:d2424597eb357ef73f5cc798aa8a130fc9ae78f5eadabf206c183085d6bb57f5 +mypy-boto3-secretsmanager==1.29.0 \ + --hash=sha256:2cd901588b54425825884a515bd48937d77f3aaa67acc1a0dfaae8d00a015eca \ + --hash=sha256:f0bd7f33d7b0025258c9a45c229970735f9f1d05c3eef0077d285c34eebe230e # via boto3-stubs -mypy-boto3-signer==1.28.36 \ - --hash=sha256:152fc0f05eda925e3ac10aa10bff2d2a9f85431e883e8103fc8463d888f347e0 \ - --hash=sha256:e008e2f4bf8023aea207d35a8ae57de9879fba8109d2cf813ddb0ebbf5300e93 +mypy-boto3-signer==1.29.0 \ + --hash=sha256:3446b001ecad6c63e6e5e28d81a4e982f704b79b8c8a9272d244bae267361e74 \ + --hash=sha256:fee1b7eda26be4b59fb1d4d880f42f7d35a19d1685c46dbf19faaab65ac168f0 # via boto3-stubs -mypy-boto3-sqs==1.28.36 \ - --hash=sha256:8457aa9f2a6da44e8543e547597773f67a04e517f6a398989117cf1fa3f70d6e \ - --hash=sha256:d9c159e020f0ef225a6d5850a3673e8b236327243ba5ffe0d13762ae4fdc0e21 +mypy-boto3-sqs==1.29.0 \ + --hash=sha256:0835256e3aabd27b2acf613c1b82a22b9de18412a0b07bd04d6d214c3f063906 \ + --hash=sha256:db88751bd7765f51c2b1f9061545ddb06639d301c3d981d3b3fa4b367f0ca8ea # via boto3-stubs -mypy-boto3-stepfunctions==1.28.36 \ - --hash=sha256:3b88c34db51ea3158d7944d3d6f5bd67b823d21d9b09e79a7ce37d36c4a69cf2 \ - --hash=sha256:8c794e98abc5ca23ef13e351f46bb849de634baca6f35286e31e58dede40b687 +mypy-boto3-stepfunctions==1.29.0 \ + --hash=sha256:1f53d60178cf95df698835502266977911460fde7cebb495b05642f5aea3cbb4 \ + --hash=sha256:3c87706c229b9e57298362dda4b3b920ac5fafcf304ce565f76179abbb222275 # via boto3-stubs -mypy-boto3-sts==1.28.58 \ - --hash=sha256:9bb44163aed4efa5d1f82084ea18c0cd5e6622dca62798c487e9604d9bb45c77 \ - --hash=sha256:beffec705f1f0b449da3c1f52ac7658627bb289aecec1a4408266479c46e053b +mypy-boto3-sts==1.29.0 \ + --hash=sha256:4750a19470241f2bc260e244f90818e79f62fe0da480eae816d7847004613852 \ + --hash=sha256:f5b847e5ae3919ec9f9d1ca1f199a260dd8dd21dd359391a6690d551d507c992 # via boto3-stubs -mypy-boto3-xray==1.28.64 \ - --hash=sha256:0657a2317de5e296fe4e0c784a3594c4c8bd8d63f801594650472e773a9619de \ - --hash=sha256:5c7135fa5aa3e4eabd5689ac266ed2fb129da9da9f641d47d4d982e1d526ed61 +mypy-boto3-xray==1.29.0 \ + --hash=sha256:ddc37e681d73c56f88268eff13d98572888ab4ea10430af7d181b39f3aca40f7 \ + --hash=sha256:ec68909f30158e155631d2934c7936daa0c1d80b083cdbe1719c349d0d4ff342 # via boto3-stubs networkx==3.2 \ --hash=sha256:8b25f564bd28f94ac821c58b04ae1a3109e73b001a7d476e4bb0d00d63706bf8 \ diff --git a/requirements/reproducible-mac.txt b/requirements/reproducible-mac.txt index 7e00908439..38e50ba9f7 100644 --- a/requirements/reproducible-mac.txt +++ b/requirements/reproducible-mac.txt @@ -20,13 +20,13 @@ attrs==23.1.0 \ # jsonschema # referencing # sarif-om -aws-lambda-builders==1.41.0 \ - --hash=sha256:b26280609269696d4c7ebe6ea208de5d02a8e4f14711ceac265510e28de65258 \ - --hash=sha256:d48d0d9b704319cdb6bb19918a72bf6c06fd3a7012848f6bcc4b906d5686db17 +aws-lambda-builders==1.42.0 \ + --hash=sha256:c0d3c4e1d9d663ccc9d13470487958fd4cc0918610786a454759b8d383a10043 \ + --hash=sha256:f2d6dc0ca6cb454d4419b8df1e2a5b4dc4973484a16b809bdb8e00620f95e6af # via aws-sam-cli (setup.py) -aws-sam-translator==1.79.0 \ - --hash=sha256:6f0c6bbcebcc98c4f98dc238352a06b0befe7fb72535cca75712fffff4873875 \ - --hash=sha256:990f3043d00b6fd801b38ad780ecd058c315b7581b2e43fc013c9b6253f876e8 +aws-sam-translator==1.80.0 \ + --hash=sha256:36afb8b802af0180a35efa68a8ab19d5d929d0a6a649a0101e8a4f8e1f05681f \ + --hash=sha256:f00215f9314cef1bbbdbd7520e3b0c75a76b88bdc3f0dedb6a2c69a12e904b12 # via # aws-sam-cli (setup.py) # cfn-lint @@ -56,27 +56,27 @@ blinker==1.7.0 \ --hash=sha256:c3f865d4d54db7abc53758a01601cf343fe55b84c1de4e3fa910e420b438d5b9 \ --hash=sha256:e6820ff6fa4e4d1d8e2747c2283749c3f547e4fee112b98555cdcdae32996182 # via flask -boto3==1.28.80 \ - --hash=sha256:2f43e032ab804a3c39996d524003d2b906e5d86856a32da3427e36912a22d2b7 \ - --hash=sha256:c48c6e04e43f894881b883a28fd032f16805f6cb2771b85f0c97f3fe34db0a41 +boto3==1.29.0 \ + --hash=sha256:3e90ea2faa3e9892b9140f857911f9ef0013192a106f50d0ec7b71e8d1afc90a \ + --hash=sha256:91c72fa4848eda9311c273db667946bd9d953285ae8d54b7bbad541b74adc254 # via # aws-sam-cli (setup.py) # aws-sam-translator -boto3-stubs[apigateway,cloudformation,ecr,iam,kinesis,lambda,s3,schemas,secretsmanager,signer,sqs,stepfunctions,sts,xray]==1.28.80 \ - --hash=sha256:544bcf2e1c32f34ca445948d7594af37325704476765c01bf5934cedc8efd8bc \ - --hash=sha256:b9a995abb8dd698865d48a12fdd64385b658f5014f22c329ac5de15e6165c178 +boto3-stubs[apigateway,cloudformation,ecr,iam,kinesis,lambda,s3,schemas,secretsmanager,signer,sqs,stepfunctions,sts,xray]==1.29.0 \ + --hash=sha256:897cb22cbf7971809cac10470121ac194a5cc57d5fb3d8bfec09e07b3cb7646b \ + --hash=sha256:e0ffd497ebd63b5d66b7eeef3192201be5453e8e5f449c864dd23877cf18fe3e # via # aws-sam-cli (setup.py) # boto3-stubs -botocore==1.31.80 \ - --hash=sha256:1c693c0f8b2553fcbe0df223241191e6f9f60b4245d65c1822c08f659274fef2 \ - --hash=sha256:d43fe303530c12efca9be4ec3a9104e8a669f11d1ba9feb18f0284d751a9672c +botocore==1.32.0 \ + --hash=sha256:95fe3357b9ddc4559941dbea0f0a6b8fc043305f013b7ae2a85dff0c3b36ee92 \ + --hash=sha256:9c1e143feb6a04235cec342d2acb31a0f44df3c89f309f839e03e38a75f3f44e # via # boto3 # s3transfer -botocore-stubs==1.31.80 \ - --hash=sha256:72472310a21171425f738fe13c26fc2fa0a890bbaf8bb89f82d464e9acb9dd2c \ - --hash=sha256:873349ae1d5dc306e08be41eb890d907074b4369bbff9a65e1247c3752923429 +botocore-stubs==1.32.0 \ + --hash=sha256:6b854253820fe080451753442cd9ee1b89ed36cfe0d452a222fff1c8e490c2b0 \ + --hash=sha256:90acea20f9e9f5838ec8330568915d10c8fc1e2c34967bc0988f7b8ab1e09822 # via boto3-stubs certifi==2023.7.22 \ --hash=sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082 \ @@ -296,9 +296,9 @@ importlib-metadata==6.8.0 \ --hash=sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb \ --hash=sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743 # via flask -importlib-resources==6.1.0 \ - --hash=sha256:9d48dcccc213325e810fd723e7fbb45ccb39f6cf5c31f00cf2b965f5f10f3cb9 \ - --hash=sha256:aa50258bbfa56d4e33fbd8aa3ef48ded10d1735f11532b8df95388cc6bdb7e83 +importlib-resources==6.1.1 \ + --hash=sha256:3893a00122eafde6894c59914446a512f728a0c1a45f9bb9b63721b6bacf0b4a \ + --hash=sha256:e8bf90d8213b486f428c9c39714b920041cb02c184686a3dee24905aaa8105d6 # via # jsonschema # jsonschema-specifications @@ -416,61 +416,61 @@ mpmath==1.3.0 \ --hash=sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f \ --hash=sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c # via sympy -mypy-boto3-apigateway==1.28.36 \ - --hash=sha256:aa2c710c7fcc505f4c0a0c851bf872c1426b948d23314d3bcf27ee09e46c9ba7 \ - --hash=sha256:e460e5b40b28fbe292f842993e7bf3ad514d0073774b30f1c5e137de6abac681 +mypy-boto3-apigateway==1.29.0 \ + --hash=sha256:2f905563c4b96c2e22e6cbaa2f85cf732d405ac4d60b6c6c70675bea717f895a \ + --hash=sha256:e43a402334f5d2b5e91de23f7d496b72730e7445302147cc4ca6f2bd1214650f # via boto3-stubs -mypy-boto3-cloudformation==1.28.64 \ - --hash=sha256:b353d52a5607c54d2916f4bde26e9be90920635beb9ffb9255cd862dca3b56bf \ - --hash=sha256:f5c9012d7fbf9c39bb314ac192e14115dbca9495e364479a16e1fa21cac23d78 +mypy-boto3-cloudformation==1.29.0 \ + --hash=sha256:91b7202a439d31f7e6645f34ea810f1900f23214900fdf6de210a0704c14da70 \ + --hash=sha256:b719c35be8b4d5606e9b4fd66d4d0c0e3d5eaf9508a72099053c8e0640b652af # via boto3-stubs -mypy-boto3-ecr==1.28.45 \ - --hash=sha256:3584a19a018bacd7b6e8147bc9ef6932967815c0918c6cf3929ff55f1c9be601 \ - --hash=sha256:d603236d984182dcf7f196517753679fbe6a3fd05feb4c3c1d2f325b065384dc +mypy-boto3-ecr==1.29.0 \ + --hash=sha256:513c13f6a8ce6ac6cbc6127e533cd5780a8b98dfc9823576b6e0c633328618c0 \ + --hash=sha256:cecdfa399f1970deab9b3dc2e57228d976b87b62fc7f81424319a85d41d21835 # via boto3-stubs -mypy-boto3-iam==1.28.79 \ - --hash=sha256:9dca1b7a3052b512dac7d4c9a58b713d5c53e216dd2c396eb64c75b083ed0727 \ - --hash=sha256:b5f8bce0d34966c917445e002c51c7e0cde553bfa62f44b131ceb52d82fec45e +mypy-boto3-iam==1.29.0 \ + --hash=sha256:26b617b134ed0a1011b0ccc7e94792899591f19ae2f0e9305789a0d1c7f5a427 \ + --hash=sha256:629495854a1608e137a0ef01f0f30247082148b554533ccfaba4e13f33bb7ebb # via boto3-stubs -mypy-boto3-kinesis==1.28.36 \ - --hash=sha256:43713c0ce8f63b2cbd181132e71371031bd90eac250aef7357b239d4da6b8504 \ - --hash=sha256:ab37194c4f69fead34f1ba12dfa520ad6c1aed9236316df453e9f3c873f2420a +mypy-boto3-kinesis==1.29.0 \ + --hash=sha256:3e91c91b984399f8b1610b76dce94f9c3dc7ef6020bebb129ff51af23a83447a \ + --hash=sha256:45fd67bc4147a19ca6511f992241844ff88c28c9e1d66f9a99d77bd8ac29ee31 # via boto3-stubs -mypy-boto3-lambda==1.28.63 \ - --hash=sha256:7cbbee5560f347548a8f43324b31b2abfa1f56ec7380f20dadb837533fc0552a \ - --hash=sha256:bcfc747594704664d41fb904f59e4173c718d1bffc92555fc9ca57f8c4b1b970 +mypy-boto3-lambda==1.29.0 \ + --hash=sha256:cc3f4dee77181feb2a1ec90f72258a32bdc75f83d01b3c637ca791073279d3e5 \ + --hash=sha256:e4537261f7b675b1c165a7dc04d4b661f2f338a45e57bd2bee92d9a41a9cd407 # via boto3-stubs -mypy-boto3-s3==1.28.55 \ - --hash=sha256:11a3db97398973d4ae28489b94c010778a0a5c65f99e00268456c3fea67eca79 \ - --hash=sha256:b008809f448e74075012d4fc54b0176de0b4f49bc38e39de30ca0e764eb75056 +mypy-boto3-s3==1.29.0 \ + --hash=sha256:3c8473974e304aa512abbf6a47454d9834674e89db414545e2f0cb4fcdd227c9 \ + --hash=sha256:f5040429b0c3814c6ec9c1a59256976186acb7376fd3b56c4e7e5d03272bb1a8 # via boto3-stubs -mypy-boto3-schemas==1.28.36 \ - --hash=sha256:82af1ad64d0c1275c576607920f13dcc7605d6b7e8483dd58aced8395c824d5f \ - --hash=sha256:ec2648ae282cbd5efd4cd0e866d2e0fee0b73bfc4ce8273484e4194582e688d4 +mypy-boto3-schemas==1.29.0 \ + --hash=sha256:2332f348ffcb7544e76a84bba0b82cd3d47c2dff3e000176a3818aac6d9c8908 \ + --hash=sha256:590fe23c13a2fa129f25e8b37285061d6264f4aed53ac26fcbcf1aace29775b4 # via boto3-stubs -mypy-boto3-secretsmanager==1.28.67 \ - --hash=sha256:37d34d2e038164bda8beb605bcc7133ef49f058e08102f5699f8d20790ead3f0 \ - --hash=sha256:d2424597eb357ef73f5cc798aa8a130fc9ae78f5eadabf206c183085d6bb57f5 +mypy-boto3-secretsmanager==1.29.0 \ + --hash=sha256:2cd901588b54425825884a515bd48937d77f3aaa67acc1a0dfaae8d00a015eca \ + --hash=sha256:f0bd7f33d7b0025258c9a45c229970735f9f1d05c3eef0077d285c34eebe230e # via boto3-stubs -mypy-boto3-signer==1.28.36 \ - --hash=sha256:152fc0f05eda925e3ac10aa10bff2d2a9f85431e883e8103fc8463d888f347e0 \ - --hash=sha256:e008e2f4bf8023aea207d35a8ae57de9879fba8109d2cf813ddb0ebbf5300e93 +mypy-boto3-signer==1.29.0 \ + --hash=sha256:3446b001ecad6c63e6e5e28d81a4e982f704b79b8c8a9272d244bae267361e74 \ + --hash=sha256:fee1b7eda26be4b59fb1d4d880f42f7d35a19d1685c46dbf19faaab65ac168f0 # via boto3-stubs -mypy-boto3-sqs==1.28.36 \ - --hash=sha256:8457aa9f2a6da44e8543e547597773f67a04e517f6a398989117cf1fa3f70d6e \ - --hash=sha256:d9c159e020f0ef225a6d5850a3673e8b236327243ba5ffe0d13762ae4fdc0e21 +mypy-boto3-sqs==1.29.0 \ + --hash=sha256:0835256e3aabd27b2acf613c1b82a22b9de18412a0b07bd04d6d214c3f063906 \ + --hash=sha256:db88751bd7765f51c2b1f9061545ddb06639d301c3d981d3b3fa4b367f0ca8ea # via boto3-stubs -mypy-boto3-stepfunctions==1.28.36 \ - --hash=sha256:3b88c34db51ea3158d7944d3d6f5bd67b823d21d9b09e79a7ce37d36c4a69cf2 \ - --hash=sha256:8c794e98abc5ca23ef13e351f46bb849de634baca6f35286e31e58dede40b687 +mypy-boto3-stepfunctions==1.29.0 \ + --hash=sha256:1f53d60178cf95df698835502266977911460fde7cebb495b05642f5aea3cbb4 \ + --hash=sha256:3c87706c229b9e57298362dda4b3b920ac5fafcf304ce565f76179abbb222275 # via boto3-stubs -mypy-boto3-sts==1.28.58 \ - --hash=sha256:9bb44163aed4efa5d1f82084ea18c0cd5e6622dca62798c487e9604d9bb45c77 \ - --hash=sha256:beffec705f1f0b449da3c1f52ac7658627bb289aecec1a4408266479c46e053b +mypy-boto3-sts==1.29.0 \ + --hash=sha256:4750a19470241f2bc260e244f90818e79f62fe0da480eae816d7847004613852 \ + --hash=sha256:f5b847e5ae3919ec9f9d1ca1f199a260dd8dd21dd359391a6690d551d507c992 # via boto3-stubs -mypy-boto3-xray==1.28.64 \ - --hash=sha256:0657a2317de5e296fe4e0c784a3594c4c8bd8d63f801594650472e773a9619de \ - --hash=sha256:5c7135fa5aa3e4eabd5689ac266ed2fb129da9da9f641d47d4d982e1d526ed61 +mypy-boto3-xray==1.29.0 \ + --hash=sha256:ddc37e681d73c56f88268eff13d98572888ab4ea10430af7d181b39f3aca40f7 \ + --hash=sha256:ec68909f30158e155631d2934c7936daa0c1d80b083cdbe1719c349d0d4ff342 # via boto3-stubs networkx==3.1 \ --hash=sha256:4f33f68cb2afcf86f28a45f43efc27a9386b535d567d2127f8f61d51dec58d36 \ diff --git a/requirements/reproducible-win.txt b/requirements/reproducible-win.txt index 105c771941..2545f5ce80 100644 --- a/requirements/reproducible-win.txt +++ b/requirements/reproducible-win.txt @@ -20,13 +20,13 @@ attrs==23.1.0 \ # jsonschema # referencing # sarif-om -aws-lambda-builders==1.41.0 \ - --hash=sha256:b26280609269696d4c7ebe6ea208de5d02a8e4f14711ceac265510e28de65258 \ - --hash=sha256:d48d0d9b704319cdb6bb19918a72bf6c06fd3a7012848f6bcc4b906d5686db17 +aws-lambda-builders==1.42.0 \ + --hash=sha256:c0d3c4e1d9d663ccc9d13470487958fd4cc0918610786a454759b8d383a10043 \ + --hash=sha256:f2d6dc0ca6cb454d4419b8df1e2a5b4dc4973484a16b809bdb8e00620f95e6af # via aws-sam-cli (setup.py) -aws-sam-translator==1.79.0 \ - --hash=sha256:6f0c6bbcebcc98c4f98dc238352a06b0befe7fb72535cca75712fffff4873875 \ - --hash=sha256:990f3043d00b6fd801b38ad780ecd058c315b7581b2e43fc013c9b6253f876e8 +aws-sam-translator==1.80.0 \ + --hash=sha256:36afb8b802af0180a35efa68a8ab19d5d929d0a6a649a0101e8a4f8e1f05681f \ + --hash=sha256:f00215f9314cef1bbbdbd7520e3b0c75a76b88bdc3f0dedb6a2c69a12e904b12 # via # aws-sam-cli (setup.py) # cfn-lint @@ -38,27 +38,27 @@ blinker==1.7.0 \ --hash=sha256:c3f865d4d54db7abc53758a01601cf343fe55b84c1de4e3fa910e420b438d5b9 \ --hash=sha256:e6820ff6fa4e4d1d8e2747c2283749c3f547e4fee112b98555cdcdae32996182 # via flask -boto3==1.28.80 \ - --hash=sha256:2f43e032ab804a3c39996d524003d2b906e5d86856a32da3427e36912a22d2b7 \ - --hash=sha256:c48c6e04e43f894881b883a28fd032f16805f6cb2771b85f0c97f3fe34db0a41 +boto3==1.29.0 \ + --hash=sha256:3e90ea2faa3e9892b9140f857911f9ef0013192a106f50d0ec7b71e8d1afc90a \ + --hash=sha256:91c72fa4848eda9311c273db667946bd9d953285ae8d54b7bbad541b74adc254 # via # aws-sam-cli (setup.py) # aws-sam-translator -boto3-stubs[apigateway,cloudformation,ecr,iam,kinesis,lambda,s3,schemas,secretsmanager,signer,sqs,stepfunctions,sts,xray]==1.28.80 \ - --hash=sha256:544bcf2e1c32f34ca445948d7594af37325704476765c01bf5934cedc8efd8bc \ - --hash=sha256:b9a995abb8dd698865d48a12fdd64385b658f5014f22c329ac5de15e6165c178 +boto3-stubs[apigateway,cloudformation,ecr,iam,kinesis,lambda,s3,schemas,secretsmanager,signer,sqs,stepfunctions,sts,xray]==1.29.0 \ + --hash=sha256:897cb22cbf7971809cac10470121ac194a5cc57d5fb3d8bfec09e07b3cb7646b \ + --hash=sha256:e0ffd497ebd63b5d66b7eeef3192201be5453e8e5f449c864dd23877cf18fe3e # via # aws-sam-cli (setup.py) # boto3-stubs -botocore==1.31.80 \ - --hash=sha256:1c693c0f8b2553fcbe0df223241191e6f9f60b4245d65c1822c08f659274fef2 \ - --hash=sha256:d43fe303530c12efca9be4ec3a9104e8a669f11d1ba9feb18f0284d751a9672c +botocore==1.32.0 \ + --hash=sha256:95fe3357b9ddc4559941dbea0f0a6b8fc043305f013b7ae2a85dff0c3b36ee92 \ + --hash=sha256:9c1e143feb6a04235cec342d2acb31a0f44df3c89f309f839e03e38a75f3f44e # via # boto3 # s3transfer -botocore-stubs==1.31.80 \ - --hash=sha256:72472310a21171425f738fe13c26fc2fa0a890bbaf8bb89f82d464e9acb9dd2c \ - --hash=sha256:873349ae1d5dc306e08be41eb890d907074b4369bbff9a65e1247c3752923429 +botocore-stubs==1.32.0 \ + --hash=sha256:6b854253820fe080451753442cd9ee1b89ed36cfe0d452a222fff1c8e490c2b0 \ + --hash=sha256:90acea20f9e9f5838ec8330568915d10c8fc1e2c34967bc0988f7b8ab1e09822 # via boto3-stubs certifi==2023.7.22 \ --hash=sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082 \ @@ -392,61 +392,61 @@ mpmath==1.3.0 \ --hash=sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f \ --hash=sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c # via sympy -mypy-boto3-apigateway==1.28.36 \ - --hash=sha256:aa2c710c7fcc505f4c0a0c851bf872c1426b948d23314d3bcf27ee09e46c9ba7 \ - --hash=sha256:e460e5b40b28fbe292f842993e7bf3ad514d0073774b30f1c5e137de6abac681 +mypy-boto3-apigateway==1.29.0 \ + --hash=sha256:2f905563c4b96c2e22e6cbaa2f85cf732d405ac4d60b6c6c70675bea717f895a \ + --hash=sha256:e43a402334f5d2b5e91de23f7d496b72730e7445302147cc4ca6f2bd1214650f # via boto3-stubs -mypy-boto3-cloudformation==1.28.64 \ - --hash=sha256:b353d52a5607c54d2916f4bde26e9be90920635beb9ffb9255cd862dca3b56bf \ - --hash=sha256:f5c9012d7fbf9c39bb314ac192e14115dbca9495e364479a16e1fa21cac23d78 +mypy-boto3-cloudformation==1.29.0 \ + --hash=sha256:91b7202a439d31f7e6645f34ea810f1900f23214900fdf6de210a0704c14da70 \ + --hash=sha256:b719c35be8b4d5606e9b4fd66d4d0c0e3d5eaf9508a72099053c8e0640b652af # via boto3-stubs -mypy-boto3-ecr==1.28.45 \ - --hash=sha256:3584a19a018bacd7b6e8147bc9ef6932967815c0918c6cf3929ff55f1c9be601 \ - --hash=sha256:d603236d984182dcf7f196517753679fbe6a3fd05feb4c3c1d2f325b065384dc +mypy-boto3-ecr==1.29.0 \ + --hash=sha256:513c13f6a8ce6ac6cbc6127e533cd5780a8b98dfc9823576b6e0c633328618c0 \ + --hash=sha256:cecdfa399f1970deab9b3dc2e57228d976b87b62fc7f81424319a85d41d21835 # via boto3-stubs -mypy-boto3-iam==1.28.79 \ - --hash=sha256:9dca1b7a3052b512dac7d4c9a58b713d5c53e216dd2c396eb64c75b083ed0727 \ - --hash=sha256:b5f8bce0d34966c917445e002c51c7e0cde553bfa62f44b131ceb52d82fec45e +mypy-boto3-iam==1.29.0 \ + --hash=sha256:26b617b134ed0a1011b0ccc7e94792899591f19ae2f0e9305789a0d1c7f5a427 \ + --hash=sha256:629495854a1608e137a0ef01f0f30247082148b554533ccfaba4e13f33bb7ebb # via boto3-stubs -mypy-boto3-kinesis==1.28.36 \ - --hash=sha256:43713c0ce8f63b2cbd181132e71371031bd90eac250aef7357b239d4da6b8504 \ - --hash=sha256:ab37194c4f69fead34f1ba12dfa520ad6c1aed9236316df453e9f3c873f2420a +mypy-boto3-kinesis==1.29.0 \ + --hash=sha256:3e91c91b984399f8b1610b76dce94f9c3dc7ef6020bebb129ff51af23a83447a \ + --hash=sha256:45fd67bc4147a19ca6511f992241844ff88c28c9e1d66f9a99d77bd8ac29ee31 # via boto3-stubs -mypy-boto3-lambda==1.28.63 \ - --hash=sha256:7cbbee5560f347548a8f43324b31b2abfa1f56ec7380f20dadb837533fc0552a \ - --hash=sha256:bcfc747594704664d41fb904f59e4173c718d1bffc92555fc9ca57f8c4b1b970 +mypy-boto3-lambda==1.29.0 \ + --hash=sha256:cc3f4dee77181feb2a1ec90f72258a32bdc75f83d01b3c637ca791073279d3e5 \ + --hash=sha256:e4537261f7b675b1c165a7dc04d4b661f2f338a45e57bd2bee92d9a41a9cd407 # via boto3-stubs -mypy-boto3-s3==1.28.55 \ - --hash=sha256:11a3db97398973d4ae28489b94c010778a0a5c65f99e00268456c3fea67eca79 \ - --hash=sha256:b008809f448e74075012d4fc54b0176de0b4f49bc38e39de30ca0e764eb75056 +mypy-boto3-s3==1.29.0 \ + --hash=sha256:3c8473974e304aa512abbf6a47454d9834674e89db414545e2f0cb4fcdd227c9 \ + --hash=sha256:f5040429b0c3814c6ec9c1a59256976186acb7376fd3b56c4e7e5d03272bb1a8 # via boto3-stubs -mypy-boto3-schemas==1.28.36 \ - --hash=sha256:82af1ad64d0c1275c576607920f13dcc7605d6b7e8483dd58aced8395c824d5f \ - --hash=sha256:ec2648ae282cbd5efd4cd0e866d2e0fee0b73bfc4ce8273484e4194582e688d4 +mypy-boto3-schemas==1.29.0 \ + --hash=sha256:2332f348ffcb7544e76a84bba0b82cd3d47c2dff3e000176a3818aac6d9c8908 \ + --hash=sha256:590fe23c13a2fa129f25e8b37285061d6264f4aed53ac26fcbcf1aace29775b4 # via boto3-stubs -mypy-boto3-secretsmanager==1.28.67 \ - --hash=sha256:37d34d2e038164bda8beb605bcc7133ef49f058e08102f5699f8d20790ead3f0 \ - --hash=sha256:d2424597eb357ef73f5cc798aa8a130fc9ae78f5eadabf206c183085d6bb57f5 +mypy-boto3-secretsmanager==1.29.0 \ + --hash=sha256:2cd901588b54425825884a515bd48937d77f3aaa67acc1a0dfaae8d00a015eca \ + --hash=sha256:f0bd7f33d7b0025258c9a45c229970735f9f1d05c3eef0077d285c34eebe230e # via boto3-stubs -mypy-boto3-signer==1.28.36 \ - --hash=sha256:152fc0f05eda925e3ac10aa10bff2d2a9f85431e883e8103fc8463d888f347e0 \ - --hash=sha256:e008e2f4bf8023aea207d35a8ae57de9879fba8109d2cf813ddb0ebbf5300e93 +mypy-boto3-signer==1.29.0 \ + --hash=sha256:3446b001ecad6c63e6e5e28d81a4e982f704b79b8c8a9272d244bae267361e74 \ + --hash=sha256:fee1b7eda26be4b59fb1d4d880f42f7d35a19d1685c46dbf19faaab65ac168f0 # via boto3-stubs -mypy-boto3-sqs==1.28.36 \ - --hash=sha256:8457aa9f2a6da44e8543e547597773f67a04e517f6a398989117cf1fa3f70d6e \ - --hash=sha256:d9c159e020f0ef225a6d5850a3673e8b236327243ba5ffe0d13762ae4fdc0e21 +mypy-boto3-sqs==1.29.0 \ + --hash=sha256:0835256e3aabd27b2acf613c1b82a22b9de18412a0b07bd04d6d214c3f063906 \ + --hash=sha256:db88751bd7765f51c2b1f9061545ddb06639d301c3d981d3b3fa4b367f0ca8ea # via boto3-stubs -mypy-boto3-stepfunctions==1.28.36 \ - --hash=sha256:3b88c34db51ea3158d7944d3d6f5bd67b823d21d9b09e79a7ce37d36c4a69cf2 \ - --hash=sha256:8c794e98abc5ca23ef13e351f46bb849de634baca6f35286e31e58dede40b687 +mypy-boto3-stepfunctions==1.29.0 \ + --hash=sha256:1f53d60178cf95df698835502266977911460fde7cebb495b05642f5aea3cbb4 \ + --hash=sha256:3c87706c229b9e57298362dda4b3b920ac5fafcf304ce565f76179abbb222275 # via boto3-stubs -mypy-boto3-sts==1.28.58 \ - --hash=sha256:9bb44163aed4efa5d1f82084ea18c0cd5e6622dca62798c487e9604d9bb45c77 \ - --hash=sha256:beffec705f1f0b449da3c1f52ac7658627bb289aecec1a4408266479c46e053b +mypy-boto3-sts==1.29.0 \ + --hash=sha256:4750a19470241f2bc260e244f90818e79f62fe0da480eae816d7847004613852 \ + --hash=sha256:f5b847e5ae3919ec9f9d1ca1f199a260dd8dd21dd359391a6690d551d507c992 # via boto3-stubs -mypy-boto3-xray==1.28.64 \ - --hash=sha256:0657a2317de5e296fe4e0c784a3594c4c8bd8d63f801594650472e773a9619de \ - --hash=sha256:5c7135fa5aa3e4eabd5689ac266ed2fb129da9da9f641d47d4d982e1d526ed61 +mypy-boto3-xray==1.29.0 \ + --hash=sha256:ddc37e681d73c56f88268eff13d98572888ab4ea10430af7d181b39f3aca40f7 \ + --hash=sha256:ec68909f30158e155631d2934c7936daa0c1d80b083cdbe1719c349d0d4ff342 # via boto3-stubs networkx==3.1 \ --hash=sha256:4f33f68cb2afcf86f28a45f43efc27a9386b535d567d2127f8f61d51dec58d36 \ diff --git a/samcli/__init__.py b/samcli/__init__.py index 2a0e5ce3be..90e77ee3ca 100644 --- a/samcli/__init__.py +++ b/samcli/__init__.py @@ -2,4 +2,4 @@ SAM CLI version """ -__version__ = "1.102.0" +__version__ = "1.103.0" diff --git a/samcli/commands/build/command.py b/samcli/commands/build/command.py index 23784295ba..7f235a3c35 100644 --- a/samcli/commands/build/command.py +++ b/samcli/commands/build/command.py @@ -52,10 +52,10 @@ \b Supported Runtimes ------------------ - 1. Python 3.7, 3.8, 3.9, 3.10, 3.11 using PIP\n + 1. Python 3.7, 3.8, 3.9, 3.10, 3.11, 3.12 using PIP\n 2. Nodejs 20.x, 18.x, 16.x, 14.x, 12.x using NPM\n 3. Ruby 2.7, 3.2 using Bundler\n - 4. Java 8, Java 11, Java 17 using Gradle and Maven\n + 4. Java 8, Java 11, Java 17, Java 21 using Gradle and Maven\n 5. Dotnet6 using Dotnet CLI (without --use-container)\n 6. Go 1.x using Go Modules (without --use-container)\n """ diff --git a/samcli/commands/init/command.py b/samcli/commands/init/command.py index 0d26b79a72..6f60ca1d86 100644 --- a/samcli/commands/init/command.py +++ b/samcli/commands/init/command.py @@ -226,6 +226,11 @@ def wrapped(*args, **kwargs): default=None, help="Enable CloudWatch Application Insights monitoring for application.", ) +@click.option( + "--structured-logging/--no-structured-logging", + default=None, + help="Enable Structured Logging for application.", +) @common_options @save_params_option @non_interactive_validation @@ -249,6 +254,7 @@ def cli( extra_context, tracing, application_insights, + structured_logging, save_params, config_file, config_env, @@ -273,6 +279,7 @@ def cli( extra_context, tracing, application_insights, + structured_logging, ) # pragma: no cover @@ -294,6 +301,7 @@ def do_cli( extra_context, tracing, application_insights, + structured_logging, ): """ Implementation of the ``cli`` method @@ -346,6 +354,7 @@ def do_cli( extra_context, tracing, application_insights, + structured_logging, ) else: if not (pt_explicit or runtime or dependency_manager or base_image or architecture): @@ -366,6 +375,7 @@ def do_cli( no_input, tracing, application_insights, + structured_logging, ) diff --git a/samcli/commands/init/core/options.py b/samcli/commands/init/core/options.py index fc5c3ac4ac..586c919ba5 100644 --- a/samcli/commands/init/core/options.py +++ b/samcli/commands/init/core/options.py @@ -25,10 +25,7 @@ CONFIGURATION_OPTION_NAMES: List[str] = ["config_env", "config_file"] + SAVE_PARAMS_OPTIONS -ADDITIONAL_OPTIONS: List[str] = [ - "tracing", - "application_insights", -] +ADDITIONAL_OPTIONS: List[str] = ["tracing", "application_insights", "structured_logging"] ALL_OPTIONS: List[str] = ( APPLICATION_OPTIONS + NON_INTERACTIVE_OPTIONS + CONFIGURATION_OPTION_NAMES + ADDITIONAL_OPTIONS + ALL_COMMON_OPTIONS diff --git a/samcli/commands/init/init_generator.py b/samcli/commands/init/init_generator.py index 8927e3fd05..454405615b 100644 --- a/samcli/commands/init/init_generator.py +++ b/samcli/commands/init/init_generator.py @@ -18,6 +18,7 @@ def do_generate( extra_context, tracing, application_insights, + structured_logging, ): try: generate_project( @@ -31,6 +32,7 @@ def do_generate( extra_context, tracing, application_insights, + structured_logging, ) except InitErrorException as e: raise UserException(str(e), wrapped_from=e.__class__.__name__) from e diff --git a/samcli/commands/init/interactive_init_flow.py b/samcli/commands/init/interactive_init_flow.py index 004243724c..8f724dbed1 100644 --- a/samcli/commands/init/interactive_init_flow.py +++ b/samcli/commands/init/interactive_init_flow.py @@ -53,6 +53,7 @@ def do_interactive( no_input, tracing, application_insights, + structured_logging, ): """ Implementation of the ``cli`` method when --interactive is provided. @@ -80,6 +81,7 @@ def do_interactive( location_opt_choice, tracing, application_insights, + structured_logging, ) @@ -98,6 +100,7 @@ def generate_application( location_opt_choice, tracing, application_insights, + structured_logging, ): # pylint: disable=too-many-arguments """ The method holds the decision logic for generating an application @@ -132,6 +135,8 @@ def generate_application( boolen value to determine if X-Ray tracing show be activated or not application_insights : bool boolean value to determine if AppInsights monitoring should be enabled or not + structured_logging: bool + boolean value to determine if Json structured logging should be enabled or not """ if location_opt_choice == "1": _generate_from_use_case( @@ -147,6 +152,7 @@ def generate_application( architecture, tracing, application_insights, + structured_logging, ) else: @@ -160,12 +166,22 @@ def generate_application( no_input, tracing, application_insights, + structured_logging, ) # pylint: disable=too-many-statements def _generate_from_location( - location, package_type, runtime, dependency_manager, output_dir, name, no_input, tracing, application_insights + location, + package_type, + runtime, + dependency_manager, + output_dir, + name, + no_input, + tracing, + application_insights, + structured_logging, ): location = click.prompt("\nTemplate location (git, mercurial, http(s), zip, path)", type=str) summary_msg = """ @@ -189,6 +205,7 @@ def _generate_from_location( None, tracing, application_insights, + structured_logging, ) @@ -206,6 +223,7 @@ def _generate_from_use_case( architecture: Optional[str], tracing: Optional[bool], application_insights: Optional[bool], + structured_logging: Optional[bool], ) -> None: templates = InitTemplates() runtime_or_base_image = runtime if runtime else base_image @@ -236,6 +254,9 @@ def _generate_from_use_case( if application_insights is None: application_insights = prompt_user_to_enable_application_insights() + if structured_logging is None: + structured_logging = prompt_user_to_enable_structured_logging() + app_template = template_chosen["appTemplate"] base_image = ( LAMBDA_IMAGES_RUNTIMES_MAP.get(str(runtime)) if not base_image and package_type == IMAGE else base_image @@ -292,6 +313,7 @@ def _generate_from_use_case( extra_context, tracing, application_insights, + structured_logging, ) # executing event_bridge logic if call is for Schema dynamic template if is_dynamic_schemas_template: @@ -426,6 +448,23 @@ def prompt_user_to_enable_application_insights(): return False +def prompt_user_to_enable_structured_logging(): + """ + Prompt user to choose if structured loggingConfig should activated + for their functions in the SAM template and vice versa + """ + if click.confirm("\nWould you like to set Structured Logging in JSON format on your Lambda functions? "): + doc_link = ( + "https://docs.aws.amazon.com/lambda/latest/dg/" + "monitoring-cloudwatchlogs.html#monitoring-cloudwatchlogs-pricing" + ) + click.echo( + f"Structured Logging in JSON format might incur an additional cost. View {doc_link} for more details" + ) + return True + return False + + def _get_choice_from_options(chosen, options, question, msg): if chosen: return chosen diff --git a/samcli/commands/local/lib/local_lambda.py b/samcli/commands/local/lib/local_lambda.py index d0d1446b5c..14f7578187 100644 --- a/samcli/commands/local/lib/local_lambda.py +++ b/samcli/commands/local/lib/local_lambda.py @@ -296,6 +296,7 @@ def _make_env_vars(self, function: Function) -> EnvironmentVariables: function.memory, function.timeout, function.handler, + function.logging_config, variables=variables, shell_env_values=shell_env, override_values=overrides, diff --git a/samcli/lib/build/workflow_config.py b/samcli/lib/build/workflow_config.py index b100621ce2..f13d02a3e6 100644 --- a/samcli/lib/build/workflow_config.py +++ b/samcli/lib/build/workflow_config.py @@ -90,6 +90,7 @@ def get_layer_subfolder(build_workflow: str) -> str: "python3.9": "python", "python3.10": "python", "python3.11": "python", + "python3.12": "python", "nodejs4.3": "nodejs", "nodejs6.10": "nodejs", "nodejs8.10": "nodejs", @@ -104,6 +105,7 @@ def get_layer_subfolder(build_workflow: str) -> str: "java11": "java", "java8.al2": "java", "java17": "java", + "java21": "java", "dotnet6": "dotnet", # User is responsible for creating subfolder in these workflows "makefile": "", @@ -158,6 +160,7 @@ def get_workflow_config( "python3.9": BasicWorkflowSelector(PYTHON_PIP_CONFIG), "python3.10": BasicWorkflowSelector(PYTHON_PIP_CONFIG), "python3.11": BasicWorkflowSelector(PYTHON_PIP_CONFIG), + "python3.12": BasicWorkflowSelector(PYTHON_PIP_CONFIG), "nodejs12.x": BasicWorkflowSelector(NODEJS_NPM_CONFIG), "nodejs14.x": BasicWorkflowSelector(NODEJS_NPM_CONFIG), "nodejs16.x": BasicWorkflowSelector(NODEJS_NPM_CONFIG), @@ -201,6 +204,14 @@ def get_workflow_config( JAVA_MAVEN_CONFIG, ] ), + "java21": ManifestWorkflowSelector( + [ + # Gradle builder needs custom executable paths to find `gradlew` binary + JAVA_GRADLE_CONFIG._replace(executable_search_paths=[code_dir, project_dir]), + JAVA_KOTLIN_GRADLE_CONFIG._replace(executable_search_paths=[code_dir, project_dir]), + JAVA_MAVEN_CONFIG, + ] + ), "provided": BasicWorkflowSelector(PROVIDED_MAKE_CONFIG), "provided.al2": BasicWorkflowSelector(PROVIDED_MAKE_CONFIG), "provided.al2023": BasicWorkflowSelector(PROVIDED_MAKE_CONFIG), diff --git a/samcli/lib/init/__init__.py b/samcli/lib/init/__init__.py index a4eac534f5..e0b8ff0e5b 100644 --- a/samcli/lib/init/__init__.py +++ b/samcli/lib/init/__init__.py @@ -15,6 +15,7 @@ from samcli.lib.init.template_modifiers.application_insights_template_modifier import ( ApplicationInsightsTemplateModifier, ) +from samcli.lib.init.template_modifiers.structured_logging_template_modifier import StructuredLoggingTemplateModifier from samcli.lib.init.template_modifiers.xray_tracing_template_modifier import XRayTracingTemplateModifier from samcli.lib.telemetry.event import EventName, EventTracker, UsedFeature from samcli.lib.utils import osutils @@ -38,6 +39,7 @@ def generate_project( extra_context=None, tracing=False, application_insights=False, + structured_logging=False, ): """Generates project using cookiecutter and options given @@ -70,6 +72,8 @@ def generate_project( Enable or disable X-Ray Tracing application_insights: Optional[str] Enable or disable AppInsights Monitoring + structured_logging: Optional[bool] + boolean value to determine if Json structured logging should be enabled or not Raises ------ @@ -132,6 +136,8 @@ def generate_project( _enable_application_insights(application_insights, output_dir, name) + _enable_structured_logging(structured_logging, output_dir, name) + _create_default_samconfig(package_type, output_dir, name) @@ -150,6 +156,13 @@ def _enable_application_insights(application_insights: bool, output_dir: str, na EventTracker.track_event(EventName.USED_FEATURE.value, UsedFeature.INIT_WITH_APPLICATION_INSIGHTS.value) +def _enable_structured_logging(structured_logging, output_dir, name): + if structured_logging: + template_file_path = f"{output_dir}/{name}/template.yaml" + template_modifier = StructuredLoggingTemplateModifier(template_file_path) + template_modifier.modify_template() + + def _create_default_samconfig(package_type: str, output_dir: str, name: str) -> None: """ Init post-processing function to create a default samconfig.toml diff --git a/samcli/lib/init/template_modifiers/structured_logging_template_modifier.py b/samcli/lib/init/template_modifiers/structured_logging_template_modifier.py new file mode 100644 index 0000000000..798ce9cd18 --- /dev/null +++ b/samcli/lib/init/template_modifiers/structured_logging_template_modifier.py @@ -0,0 +1,98 @@ +""" +Class used to parse and update template when structured logging is enabled +""" +import logging +from typing import Any + +from ruamel.yaml import YAML +from ruamel.yaml.comments import CommentedMap +from ruamel.yaml.representer import RoundTripRepresenter + +from samcli.lib.init.template_modifiers.cli_template_modifier import TemplateModifier + +LOG = logging.getLogger(__name__) + + +class StructuredLoggingTemplateModifier(TemplateModifier): + GLOBALS = "Globals" + RESOURCE = "Resources" + FUNCTION = "Function" + LOGGING_CONFIG = "LoggingConfig" + JSON_LOGFORMAT = {"LogFormat": "JSON"} + DOC_LINK = ( + "https://docs.aws.amazon.com/serverless-application-model/latest/" + "developerguide/sam-resource-function.html#sam-function-loggingconfig" + ) + + COMMENT = ( + "More info about Globals: " + "https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst\n" + ) + + MESSAGE = ( + "You can add LoggingConfig parameters such as the Logformat, " + "Log Group, and SystemLogLevel or ApplicationLogLevel. " + f"Learn more here {DOC_LINK}.\n" + ) + + # set ignore aliases to true. This configuration avoids usage yaml aliases which is not parsed by CloudFormation. + class NonAliasingRTRepresenter(RoundTripRepresenter): + def ignore_aliases(self, data): + return True + + def __init__(self, location): + self.yaml = YAML() + self.yaml.Representer = StructuredLoggingTemplateModifier.NonAliasingRTRepresenter + super().__init__(location) + + def _get_template(self) -> Any: + with open(self.template_location) as file: + return self.yaml.load(file) + + def _update_template_fields(self): + """ + Add new field to SAM template + """ + if self.template.get(self.GLOBALS): + template_globals = self.template.get(self.GLOBALS) + + function_globals = template_globals.get(self.FUNCTION, {}) + if not function_globals: + template_globals[self.FUNCTION] = {} + template_globals[self.FUNCTION][self.LOGGING_CONFIG] = CommentedMap(self.JSON_LOGFORMAT) + template_globals[self.FUNCTION].yaml_set_comment_before_after_key( + self.LOGGING_CONFIG, before=self.MESSAGE, indent=4 + ) + + else: + self._add_logging_config_with_globals() + + def _add_logging_config_with_globals(self): + """Adds Globals and LoggingConfig fields""" + global_section = { + self.FUNCTION: {self.LOGGING_CONFIG: self.JSON_LOGFORMAT}, + } + + self.template = CommentedMap(self.template) + self.template[self.GLOBALS] = CommentedMap(global_section) + self.template[self.GLOBALS].yaml_set_comment_before_after_key(self.LOGGING_CONFIG, before=self.MESSAGE) + self.template.yaml_set_comment_before_after_key(self.GLOBALS, before=self.COMMENT) + + def _print_sanity_check_error(self): + message = ( + "Warning: Unable to add LoggingConfig to the project. " + "To learn more about LoggingConfig visit {self.DOC_LINK}" + ) + LOG.warning(message) + + def _write(self, template: list): + """ + write generated template into SAM template + + Parameters + ---------- + template : list + array with updated template data + """ + with open(self.template_location, "w") as file: + self.yaml.dump(self.template, file) diff --git a/samcli/lib/observability/cw_logs/cw_log_group_provider.py b/samcli/lib/observability/cw_logs/cw_log_group_provider.py index faee3d8297..0ff83925e5 100644 --- a/samcli/lib/observability/cw_logs/cw_log_group_provider.py +++ b/samcli/lib/observability/cw_logs/cw_log_group_provider.py @@ -24,7 +24,7 @@ class LogGroupProvider: def for_resource(boto_client_provider: BotoProviderType, resource_type: str, name: str) -> Optional[str]: log_group = None if resource_type == AWS_LAMBDA_FUNCTION: - log_group = LogGroupProvider.for_lambda_function(name) + log_group = LogGroupProvider.for_lambda_function(boto_client_provider, name) elif resource_type == AWS_APIGATEWAY_RESTAPI: log_group = LogGroupProvider.for_apigw_rest_api(name) elif resource_type == AWS_APIGATEWAY_V2_API: @@ -35,12 +35,14 @@ def for_resource(boto_client_provider: BotoProviderType, resource_type: str, nam return log_group @staticmethod - def for_lambda_function(function_name: str) -> str: + def for_lambda_function(boto_client_provider: BotoProviderType, function_name: str) -> str: """ Returns the CloudWatch Log Group Name created by default for the AWS Lambda function with given name Parameters ---------- + boto_client_provider: BotoProviderType + Boto client provider which contains region and other configurations function_name : str Name of the Lambda function @@ -49,7 +51,16 @@ def for_lambda_function(function_name: str) -> str: str Default Log Group name used by this function """ - return "/aws/lambda/{}".format(function_name) + log_group_name = "" + try: + function_configuration = boto_client_provider("lambda").get_function_configuration(function_name) + logging_config = function_configuration.get("LoggingConfig") + if logging_config: + log_group_name = logging_config.get("LogGroup") + except Exception as ex: + LOG.debug("Could not retrive function configuration for function (%s): (%s)", function_name, str(ex)) + + return log_group_name if bool(log_group_name) else f"/aws/lambda/{function_name}" @staticmethod def for_apigw_rest_api(rest_api_id: str, stage: str = "Prod") -> str: diff --git a/samcli/lib/providers/provider.py b/samcli/lib/providers/provider.py index 58e2febdb7..71c593a249 100644 --- a/samcli/lib/providers/provider.py +++ b/samcli/lib/providers/provider.py @@ -111,6 +111,8 @@ class Function(NamedTuple): stack_path: str = "" # Configuration for runtime management. Includes the fields `UpdateRuntimeOn` and `RuntimeVersionArn` (optional). runtime_management_config: Optional[Dict] = None + # LoggingConfig for Advanced logging + logging_config: Optional[Dict] = None @property def full_path(self) -> str: diff --git a/samcli/lib/providers/sam_function_provider.py b/samcli/lib/providers/sam_function_provider.py index b7adfa597a..fde30ba502 100644 --- a/samcli/lib/providers/sam_function_provider.py +++ b/samcli/lib/providers/sam_function_provider.py @@ -473,6 +473,7 @@ def _build_function_configuration( function_url_config=resource_properties.get("FunctionUrlConfig"), runtime_management_config=resource_properties.get("RuntimeManagementConfig"), function_build_info=function_build_info, + logging_config=resource_properties.get("LoggingConfig"), ) @staticmethod diff --git a/samcli/lib/utils/architecture.py b/samcli/lib/utils/architecture.py index 8cddfc9e3d..8c394d6229 100644 --- a/samcli/lib/utils/architecture.py +++ b/samcli/lib/utils/architecture.py @@ -24,12 +24,14 @@ "python3.9": [ARM64, X86_64], "python3.10": [ARM64, X86_64], "python3.11": [ARM64, X86_64], + "python3.12": [ARM64, X86_64], "ruby2.7": [ARM64, X86_64], "ruby3.2": [ARM64, X86_64], "java8": [X86_64], "java8.al2": [ARM64, X86_64], "java11": [ARM64, X86_64], "java17": [ARM64, X86_64], + "java21": [ARM64, X86_64], "go1.x": [X86_64], "dotnet6": [ARM64, X86_64], "provided": [X86_64], diff --git a/samcli/lib/utils/preview_runtimes.py b/samcli/lib/utils/preview_runtimes.py index c17ae95cf8..6bea7bb6de 100644 --- a/samcli/lib/utils/preview_runtimes.py +++ b/samcli/lib/utils/preview_runtimes.py @@ -4,4 +4,4 @@ """ from typing import Set -PREVIEW_RUNTIMES: Set[str] = set() +PREVIEW_RUNTIMES: Set[str] = {"python3.12"} diff --git a/samcli/local/common/runtime_template.py b/samcli/local/common/runtime_template.py index b7ba6219d1..94fe22d754 100644 --- a/samcli/local/common/runtime_template.py +++ b/samcli/local/common/runtime_template.py @@ -16,7 +16,7 @@ RUNTIME_DEP_TEMPLATE_MAPPING = { "python": [ { - "runtimes": ["python3.11", "python3.10", "python3.9", "python3.8", "python3.7"], + "runtimes": ["python3.12", "python3.11", "python3.10", "python3.9", "python3.8", "python3.7"], "dependency_manager": "pip", "init_location": os.path.join(_templates, "cookiecutter-aws-sam-hello-python"), "build": True, @@ -56,13 +56,13 @@ ], "java": [ { - "runtimes": ["java11", "java8", "java8.al2", "java17"], + "runtimes": ["java11", "java8", "java8.al2", "java17", "java21"], "dependency_manager": "maven", "init_location": os.path.join(_templates, "cookiecutter-aws-sam-hello-java-maven"), "build": True, }, { - "runtimes": ["java11", "java8", "java8.al2", "java17"], + "runtimes": ["java11", "java8", "java8.al2", "java17", "java21"], "dependency_manager": "gradle", "init_location": os.path.join(_templates, "cookiecutter-aws-sam-hello-java-gradle"), "build": True, @@ -102,6 +102,7 @@ def get_local_lambda_images_location(mapping, runtime): "dotnet6", "go1.x", # java runtimes in descending order + "java21", "java17", "java11", "java8.al2", @@ -117,6 +118,7 @@ def get_local_lambda_images_location(mapping, runtime): "provided.al2", "provided", # python runtimes in descending order + "python3.12", "python3.11", "python3.10", "python3.9", @@ -133,6 +135,7 @@ def get_local_lambda_images_location(mapping, runtime): "go1.x": "amazon/go1.x-base", "go (provided.al2)": "amazon/go-provided.al2-base", "go (provided.al2023)": "amazon/go-provided.al2023-base", + "java21": "amazon/java21-base", "java17": "amazon/java17-base", "java11": "amazon/java11-base", "java8.al2": "amazon/java8.al2-base", @@ -142,6 +145,7 @@ def get_local_lambda_images_location(mapping, runtime): "nodejs16.x": "amazon/nodejs16.x-base", "nodejs14.x": "amazon/nodejs14.x-base", "nodejs12.x": "amazon/nodejs12.x-base", + "python3.12": "amazon/python3.12-base", "python3.11": "amazon/python3.11-base", "python3.10": "amazon/python3.10-base", "python3.9": "amazon/python3.9-base", @@ -155,16 +159,19 @@ def get_local_lambda_images_location(mapping, runtime): # Schemas Code lang is a MINIMUM supported version # - this is why later Lambda runtimes can be mapped to earlier Schemas Code Languages +# event schema registry supports only java8, python3.6, dotnet6, and Go1 for code binding SAM_RUNTIME_TO_SCHEMAS_CODE_LANG_MAPPING = { "java8": "Java8", "java8.al2": "Java8", "java11": "Java8", - "java17": "Java17", + "java17": "Java8", + "java21": "Java8", "python3.7": "Python36", "python3.8": "Python36", "python3.9": "Python36", "python3.10": "Python36", "python3.11": "Python36", + "python3.12": "Python36", "dotnet6": "dotnet6", "go1.x": "Go1", } diff --git a/samcli/local/docker/lambda_debug_settings.py b/samcli/local/docker/lambda_debug_settings.py index 6b8c9bea65..05956e0eac 100644 --- a/samcli/local/docker/lambda_debug_settings.py +++ b/samcli/local/docker/lambda_debug_settings.py @@ -93,6 +93,16 @@ def get_debug_settings(debug_port, debug_args_list, _container_env_vars, runtime **_container_env_vars, }, ), + Runtime.java21.value: lambda: DebugSettings( + entry, + container_env_vars={ + "_JAVA_OPTIONS": "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,quiet=y," + f"address=*:{debug_port} -XX:MaxHeapSize=2834432k -XX:+UseSerialGC " + "-XX:+TieredCompilation -XX:TieredStopAtLevel=1 " + "-Djava.net.preferIPv4Stack=true" + " ".join(debug_args_list), + **_container_env_vars, + }, + ), Runtime.dotnet6.value: lambda: DebugSettings( entry + ["/var/runtime/bootstrap"] + debug_args_list, container_env_vars={"_AWS_LAMBDA_DOTNET_DEBUGGING": "1", **_container_env_vars}, @@ -197,6 +207,10 @@ def get_debug_settings(debug_port, debug_args_list, _container_env_vars, runtime entry + ["/var/lang/bin/python3.11"] + debug_args_list + ["/var/runtime/bootstrap.py"], container_env_vars=_container_env_vars, ), + Runtime.python312.value: lambda: DebugSettings( + entry + ["/var/lang/bin/python3.12"] + debug_args_list + ["/var/runtime/bootstrap.py"], + container_env_vars=_container_env_vars, + ), } try: return entrypoint_mapping[runtime]() diff --git a/samcli/local/docker/lambda_image.py b/samcli/local/docker/lambda_image.py index 2cee356a5c..58b633735e 100644 --- a/samcli/local/docker/lambda_image.py +++ b/samcli/local/docker/lambda_image.py @@ -42,12 +42,14 @@ class Runtime(Enum): python39 = "python3.9" python310 = "python3.10" python311 = "python3.11" + python312 = "python3.12" ruby27 = "ruby2.7" ruby32 = "ruby3.2" java8 = "java8" java8al2 = "java8.al2" java11 = "java11" java17 = "java17" + java21 = "java21" go1x = "go1.x" dotnet6 = "dotnet6" provided = "provided" diff --git a/samcli/local/lambdafn/env_vars.py b/samcli/local/lambdafn/env_vars.py index 4aefb76bef..ebf52ce5be 100644 --- a/samcli/local/lambdafn/env_vars.py +++ b/samcli/local/lambdafn/env_vars.py @@ -44,6 +44,7 @@ def __init__( function_memory=None, function_timeout=None, function_handler=None, + function_logging_config=None, variables=None, shell_env_values=None, override_values=None, @@ -58,6 +59,7 @@ def __init__( :param integer function_memory: Memory size of the function in megabytes :param integer function_timeout: Function's timeout in seconds :param string function_handler: Handler of the function + :param string function_logging_config: Logging Config for the function :param dict variables: Optional. Dict whose key is the environment variable names and value is the default values for the variable. :param dict shell_env_values: Optional. Dict containing values for the variables grabbed from the shell's @@ -79,6 +81,7 @@ def __init__( self.shell_env_values = shell_env_values or {} self.override_values = override_values or {} self.aws_creds = aws_creds or {} + self.logging_config = function_logging_config or {} def resolve(self): """ @@ -179,6 +182,17 @@ def _get_aws_variables(self): if self.aws_creds.get("sessiontoken"): result["AWS_SESSION_TOKEN"] = self.aws_creds.get("sessiontoken") + # Add the ApplicationLogLevel as a env variable and also update the function's LogGroup name + log_group = self.logging_config.get("LogGroup") + if log_group: + result["AWS_LAMBDA_LOG_GROUP_NAME"] = log_group + + log_format = self.logging_config.get("LogFormat") + if log_format: + result["AWS_LAMBDA_LOG_FORMAT"] = log_format + if log_format == "JSON": + result["AWS_LAMBDA_LOG_LEVEL"] = self.logging_config.get("ApplicationLogLevel", "INFO") + return result def _stringify_value(self, value): diff --git a/samcli/runtime_config.json b/samcli/runtime_config.json index 340d51f5f0..e84460793d 100644 --- a/samcli/runtime_config.json +++ b/samcli/runtime_config.json @@ -1,3 +1,3 @@ { - "app_template_repo_commit": "36ba1b7994f98a52bfdc81cca58705814a9a2578" + "app_template_repo_commit": "163c4f746c210ada70815df6a52639fca03d707b" } diff --git a/schema/samcli.json b/schema/samcli.json index 47eeb6a3ce..69420d9d40 100644 --- a/schema/samcli.json +++ b/schema/samcli.json @@ -23,7 +23,7 @@ "properties": { "parameters": { "title": "Parameters for the init command", - "description": "Available parameters for the init command:\n* no_interactive:\nDisable interactive prompting for init parameters. (fail if any required values are missing)\n* architecture:\nArchitectures for Lambda functions.\n\nArchitectures: ['arm64', 'x86_64']\n* location:\nTemplate location (git, mercurial, http(s), zip, path).\n* runtime:\nLambda runtime for application.\n\nRuntimes: dotnet6, go1.x, java17, java11, java8.al2, java8, nodejs18.x, nodejs16.x, nodejs14.x, nodejs12.x, provided, provided.al2, provided.al2023, python3.9, python3.8, python3.7, python3.11, python3.10, ruby3.2, ruby2.7\n* package_type:\nLambda deployment package type.\n\nPackage Types: Zip, Image\n* base_image:\nLambda base image for deploying IMAGE based package type.\n\nBase images: amazon/dotnet6-base, amazon/go-provided.al2-base, amazon/go-provided.al2023-base, amazon/go1.x-base, amazon/java11-base, amazon/java17-base, amazon/java8-base, amazon/java8.al2-base, amazon/nodejs12.x-base, amazon/nodejs14.x-base, amazon/nodejs16.x-base, amazon/nodejs18.x-base, amazon/python3.10-base, amazon/python3.11-base, amazon/python3.7-base, amazon/python3.8-base, amazon/python3.9-base, amazon/ruby2.7-base, amazon/ruby3.2-base\n* dependency_manager:\nDependency manager for Lambda runtime.\n\nDependency managers: bundler, cli-package, gradle, maven, mod, npm, pip\n* output_dir:\nDirectory to initialize AWS SAM application.\n* name:\nName of AWS SAM Application.\n* app_template:\nIdentifier of the managed application template to be used. Alternatively, run '$sam init' without options for an interactive workflow.\n* no_input:\nDisable Cookiecutter prompting and accept default values defined in the cookiecutter config.\n* extra_context:\nOverride custom parameters in the template's cookiecutter.json configuration e.g. {\"customParam1\": \"customValue1\", \"customParam2\":\"customValue2\"}\n* tracing:\nEnable AWS X-Ray tracing for application.\n* application_insights:\nEnable CloudWatch Application Insights monitoring for application.\n* beta_features:\nEnable/Disable beta features.\n* debug:\nTurn on debug logging to print debug message generated by AWS SAM CLI and display timestamps.\n* save_params:\nSave the parameters provided via the command line to the configuration file.", + "description": "Available parameters for the init command:\n* no_interactive:\nDisable interactive prompting for init parameters. (fail if any required values are missing)\n* architecture:\nArchitectures for Lambda functions.\n\nArchitectures: ['arm64', 'x86_64']\n* location:\nTemplate location (git, mercurial, http(s), zip, path).\n* runtime:\nLambda runtime for application.\n\nRuntimes: dotnet6, go1.x, java17, java11, java8.al2, java8, nodejs18.x, nodejs16.x, nodejs14.x, nodejs12.x, provided, provided.al2, python3.9, python3.8, python3.7, python3.11, python3.10, ruby3.2, ruby2.7\n* package_type:\nLambda deployment package type.\n\nPackage Types: Zip, Image\n* base_image:\nLambda base image for deploying IMAGE based package type.\n\nBase images: amazon/dotnet6-base, amazon/go-provided.al2-base, amazon/go1.x-base, amazon/java11-base, amazon/java17-base, amazon/java8-base, amazon/java8.al2-base, amazon/nodejs12.x-base, amazon/nodejs14.x-base, amazon/nodejs16.x-base, amazon/nodejs18.x-base, amazon/python3.10-base, amazon/python3.11-base, amazon/python3.7-base, amazon/python3.8-base, amazon/python3.9-base, amazon/ruby2.7-base, amazon/ruby3.2-base\n* dependency_manager:\nDependency manager for Lambda runtime.\n\nDependency managers: bundler, cli-package, gradle, maven, mod, npm, pip\n* output_dir:\nDirectory to initialize AWS SAM application.\n* name:\nName of AWS SAM Application.\n* app_template:\nIdentifier of the managed application template to be used. Alternatively, run '$sam init' without options for an interactive workflow.\n* no_input:\nDisable Cookiecutter prompting and accept default values defined in the cookiecutter config.\n* extra_context:\nOverride custom parameters in the template's cookiecutter.json configuration e.g. {\"customParam1\": \"customValue1\", \"customParam2\":\"customValue2\"}\n* tracing:\nEnable AWS X-Ray tracing for application.\n* application_insights:\nEnable CloudWatch Application Insights monitoring for application.\n* structured_logging:\nEnable Structured Logging for application.\n* beta_features:\nEnable/Disable beta features.\n* debug:\nTurn on debug logging to print debug message generated by AWS SAM CLI and display timestamps.\n* save_params:\nSave the parameters provided via the command line to the configuration file.", "type": "object", "properties": { "no_interactive": { @@ -65,6 +65,7 @@ "provided.al2023", "python3.10", "python3.11", + "python3.12", "python3.7", "python3.8", "python3.9", @@ -100,6 +101,7 @@ "amazon/nodejs18.x-base", "amazon/python3.10-base", "amazon/python3.11-base", + "amazon/python3.12-base", "amazon/python3.7-base", "amazon/python3.8-base", "amazon/python3.9-base", @@ -157,6 +159,11 @@ "type": "boolean", "description": "Enable CloudWatch Application Insights monitoring for application." }, + "structured_logging": { + "title": "structured_logging", + "type": "boolean", + "description": "Enable Structured Logging for application." + }, "beta_features": { "title": "beta_features", "type": "boolean", diff --git a/tests/functional/commands/init/test_interactive_init_flow.py b/tests/functional/commands/init/test_interactive_init_flow.py index 2d5226ba0d..da05965fea 100644 --- a/tests/functional/commands/init/test_interactive_init_flow.py +++ b/tests/functional/commands/init/test_interactive_init_flow.py @@ -60,6 +60,7 @@ def test_unknown_runtime(self, git_repo_mock, requests_mock): no_input=False, tracing=False, application_insights=False, + structured_logging=False, ) output_files = list(self.output_dir.rglob("*")) self.assertEqual(len(output_files), 9) diff --git a/tests/integration/buildcmd/test_build_cmd.py b/tests/integration/buildcmd/test_build_cmd.py index 40cbdb1666..c8e059217f 100644 --- a/tests/integration/buildcmd/test_build_cmd.py +++ b/tests/integration/buildcmd/test_build_cmd.py @@ -452,6 +452,7 @@ def _validate_skipped_built_function( ("template.yaml", "Function", True, "python3.9", "Python", False, "CodeUri"), ("template.yaml", "Function", True, "python3.10", "Python", False, "CodeUri"), ("template.yaml", "Function", True, "python3.11", "Python", False, "CodeUri"), + ("template.yaml", "Function", True, "python3.12", "Python", False, "CodeUri"), ("template.yaml", "Function", True, "python3.7", "PythonPEP600", False, "CodeUri"), ("template.yaml", "Function", True, "python3.8", "PythonPEP600", False, "CodeUri"), ], @@ -491,6 +492,7 @@ def test_with_default_requirements(self): ("template.yaml", "Function", True, "python3.9", "Python", False, "CodeUri"), ("template.yaml", "Function", True, "python3.10", "Python", False, "CodeUri"), ("template.yaml", "Function", True, "python3.11", "Python", False, "CodeUri"), + ("template.yaml", "Function", True, "python3.12", "Python", False, "CodeUri"), ], ) class TestBuildCommand_PythonFunctions_WithDocker(BuildIntegPythonBase): @@ -601,11 +603,23 @@ class TestBuildCommand_PythonFunctions_With_Specified_Architecture(BuildIntegPyt [ ("python3.7", "Python", False, "x86_64"), ("python3.8", "Python", False, "x86_64"), + ("python3.9", "Python", False, "x86_64"), + ("python3.10", "Python", False, "x86_64"), + ("python3.11", "Python", False, "x86_64"), + ("python3.12", "Python", False, "x86_64"), # numpy 1.20.3 (in PythonPEP600/requirements.txt) only support python 3.7+ ("python3.7", "PythonPEP600", False, "x86_64"), ("python3.8", "PythonPEP600", False, "x86_64"), + ("python3.9", "PythonPEP600", False, "x86_64"), + ("python3.10", "PythonPEP600", False, "x86_64"), + ("python3.11", "PythonPEP600", False, "x86_64"), + ("python3.12", "PythonPEP600", False, "x86_64"), ("python3.7", "Python", "use_container", "x86_64"), ("python3.8", "Python", "use_container", "x86_64"), + ("python3.9", "Python", "use_container", "x86_64"), + ("python3.10", "Python", "use_container", "x86_64"), + ("python3.11", "Python", "use_container", "x86_64"), + ("python3.12", "Python", "use_container", "x86_64"), ] ) def test_with_default_requirements(self, runtime, codeuri, use_container, architecture): @@ -888,6 +902,16 @@ class TestBuildCommand_Java(BuildIntegJavaBase): EXPECTED_GRADLE_DEPENDENCIES, ), ("java17", "17", USING_MAVEN_PATH, EXPECTED_FILES_PROJECT_MANIFEST_MAVEN, EXPECTED_MAVEN_DEPENDENCIES), + ("java21", "21", USING_GRADLE_PATH, EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, EXPECTED_GRADLE_DEPENDENCIES), + ("java21", "21", USING_GRADLEW_PATH, EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, EXPECTED_GRADLE_DEPENDENCIES), + ( + "java21", + "21", + USING_GRADLE_KOTLIN_PATH, + EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, + EXPECTED_GRADLE_DEPENDENCIES, + ), + ("java21", "21", USING_MAVEN_PATH, EXPECTED_FILES_PROJECT_MANIFEST_MAVEN, EXPECTED_MAVEN_DEPENDENCIES), ] ) @skipIf(SKIP_DOCKER_TESTS or SKIP_DOCKER_BUILD, SKIP_DOCKER_MESSAGE) @@ -905,50 +929,72 @@ def test_building_java_in_container( @parameterized.expand( [ - ("java8", USING_GRADLE_PATH, EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, EXPECTED_GRADLE_DEPENDENCIES), - ("java8", USING_GRADLEW_PATH, EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, EXPECTED_GRADLE_DEPENDENCIES), - ("java8", USING_GRADLE_KOTLIN_PATH, EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, EXPECTED_GRADLE_DEPENDENCIES), - ("java8", USING_MAVEN_PATH, EXPECTED_FILES_PROJECT_MANIFEST_MAVEN, EXPECTED_MAVEN_DEPENDENCIES), - ("java8.al2", USING_GRADLE_PATH, EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, EXPECTED_GRADLE_DEPENDENCIES), - ("java8.al2", USING_GRADLEW_PATH, EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, EXPECTED_GRADLE_DEPENDENCIES), + ("java8", "8", USING_GRADLE_PATH, EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, EXPECTED_GRADLE_DEPENDENCIES), + ("java8", "8", USING_GRADLEW_PATH, EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, EXPECTED_GRADLE_DEPENDENCIES), + ( + "java8", + "8", + USING_GRADLE_KOTLIN_PATH, + EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, + EXPECTED_GRADLE_DEPENDENCIES, + ), + ("java8", "8", USING_MAVEN_PATH, EXPECTED_FILES_PROJECT_MANIFEST_MAVEN, EXPECTED_MAVEN_DEPENDENCIES), + ("java8.al2", "8", USING_GRADLE_PATH, EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, EXPECTED_GRADLE_DEPENDENCIES), ( "java8.al2", + "8", + USING_GRADLEW_PATH, + EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, + EXPECTED_GRADLE_DEPENDENCIES, + ), + ( + "java8.al2", + "8", USING_GRADLE_KOTLIN_PATH, EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, EXPECTED_GRADLE_DEPENDENCIES, ), - ("java8.al2", USING_MAVEN_PATH, EXPECTED_FILES_PROJECT_MANIFEST_MAVEN, EXPECTED_MAVEN_DEPENDENCIES), - ] - ) - def test_building_java8_in_process(self, runtime, code_path, expected_files, expected_dependencies): - self._test_with_building_java( - runtime, os.path.join(code_path, "8"), expected_files, expected_dependencies, False, self.test_data_path - ) - - @parameterized.expand( - [ - ("java11", USING_GRADLE_PATH, EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, EXPECTED_GRADLE_DEPENDENCIES), - ("java11", USING_GRADLEW_PATH, EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, EXPECTED_GRADLE_DEPENDENCIES), - ("java11", USING_GRADLE_KOTLIN_PATH, EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, EXPECTED_GRADLE_DEPENDENCIES), - ("java11", USING_MAVEN_PATH, EXPECTED_FILES_PROJECT_MANIFEST_MAVEN, EXPECTED_MAVEN_DEPENDENCIES), - ] - ) - def test_building_java11_in_process(self, runtime, code_path, expected_files, expected_dependencies): - self._test_with_building_java( - runtime, os.path.join(code_path, "11"), expected_files, expected_dependencies, False, self.test_data_path - ) - - @parameterized.expand( - [ - ("java17", USING_GRADLE_PATH, EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, EXPECTED_GRADLE_DEPENDENCIES), - ("java17", USING_GRADLEW_PATH, EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, EXPECTED_GRADLE_DEPENDENCIES), - ("java17", USING_GRADLE_KOTLIN_PATH, EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, EXPECTED_GRADLE_DEPENDENCIES), - ("java17", USING_MAVEN_PATH, EXPECTED_FILES_PROJECT_MANIFEST_MAVEN, EXPECTED_MAVEN_DEPENDENCIES), + ("java8.al2", "8", USING_MAVEN_PATH, EXPECTED_FILES_PROJECT_MANIFEST_MAVEN, EXPECTED_MAVEN_DEPENDENCIES), + ("java11", "11", USING_GRADLE_PATH, EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, EXPECTED_GRADLE_DEPENDENCIES), + ("java11", "11", USING_GRADLEW_PATH, EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, EXPECTED_GRADLE_DEPENDENCIES), + ( + "java11", + "11", + USING_GRADLE_KOTLIN_PATH, + EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, + EXPECTED_GRADLE_DEPENDENCIES, + ), + ("java11", "11", USING_MAVEN_PATH, EXPECTED_FILES_PROJECT_MANIFEST_MAVEN, EXPECTED_MAVEN_DEPENDENCIES), + ("java17", "17", USING_GRADLE_PATH, EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, EXPECTED_GRADLE_DEPENDENCIES), + ("java17", "17", USING_GRADLEW_PATH, EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, EXPECTED_GRADLE_DEPENDENCIES), + ( + "java17", + "17", + USING_GRADLE_KOTLIN_PATH, + EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, + EXPECTED_GRADLE_DEPENDENCIES, + ), + ("java17", "17", USING_MAVEN_PATH, EXPECTED_FILES_PROJECT_MANIFEST_MAVEN, EXPECTED_MAVEN_DEPENDENCIES), + ("java21", "21", USING_GRADLE_PATH, EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, EXPECTED_GRADLE_DEPENDENCIES), + ("java21", "21", USING_GRADLEW_PATH, EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, EXPECTED_GRADLE_DEPENDENCIES), + ( + "java21", + "21", + USING_GRADLE_KOTLIN_PATH, + EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, + EXPECTED_GRADLE_DEPENDENCIES, + ), + ("java21", "21", USING_MAVEN_PATH, EXPECTED_FILES_PROJECT_MANIFEST_MAVEN, EXPECTED_MAVEN_DEPENDENCIES), ] ) - def test_building_java17_in_process(self, runtime, code_path, expected_files, expected_dependencies): + def test_building_java_in_process(self, runtime, runtime_version, code_path, expected_files, expected_dependencies): self._test_with_building_java( - runtime, os.path.join(code_path, "17"), expected_files, expected_dependencies, False, self.test_data_path + runtime, + os.path.join(code_path, runtime_version), + expected_files, + expected_dependencies, + False, + self.test_data_path, ) diff --git a/tests/integration/buildcmd/test_build_cmd_arm64.py b/tests/integration/buildcmd/test_build_cmd_arm64.py index e0e080e284..cb7b4c5c58 100644 --- a/tests/integration/buildcmd/test_build_cmd_arm64.py +++ b/tests/integration/buildcmd/test_build_cmd_arm64.py @@ -31,8 +31,20 @@ class TestBuildCommand_PythonFunctions_With_Specified_Architecture_arm64(BuildIn @parameterized.expand( [ ("python3.8", "Python", False), + ("python3.9", "Python", False), + ("python3.10", "Python", False), + ("python3.11", "Python", False), + ("python3.12", "Python", False), ("python3.8", "PythonPEP600", False), + ("python3.9", "PythonPEP600", False), + ("python3.10", "PythonPEP600", False), + ("python3.11", "PythonPEP600", False), + ("python3.12", "PythonPEP600", False), ("python3.8", "Python", "use_container"), + ("python3.9", "Python", "use_container"), + ("python3.10", "Python", "use_container"), + ("python3.11", "Python", "use_container"), + ("python3.12", "Python", "use_container"), ] ) def test_with_default_requirements(self, runtime, codeuri, use_container): @@ -254,6 +266,34 @@ class TestBuildCommand_Java_With_Specified_Architecture_arm64(BuildIntegJavaBase EXPECTED_FILES_PROJECT_MANIFEST_MAVEN, EXPECTED_MAVEN_DEPENDENCIES, ), + ( + "java21", + "21", + USING_GRADLE_PATH, + EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, + EXPECTED_GRADLE_DEPENDENCIES, + ), + ( + "java21", + "21", + USING_GRADLEW_PATH, + EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, + EXPECTED_GRADLE_DEPENDENCIES, + ), + ( + "java21", + "21", + USING_GRADLE_KOTLIN_PATH, + EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, + EXPECTED_GRADLE_DEPENDENCIES, + ), + ( + "java21", + "21", + USING_MAVEN_PATH, + EXPECTED_FILES_PROJECT_MANIFEST_MAVEN, + EXPECTED_MAVEN_DEPENDENCIES, + ), ] ) @skipIf(SKIP_DOCKER_TESTS or SKIP_DOCKER_BUILD, SKIP_DOCKER_MESSAGE) @@ -274,118 +314,124 @@ def test_building_java_in_container_with_arm64_architecture( [ ( "java8.al2", + "8", USING_GRADLE_PATH, EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, EXPECTED_GRADLE_DEPENDENCIES, ), ( "java8.al2", + "8", USING_GRADLEW_PATH, EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, EXPECTED_GRADLE_DEPENDENCIES, ), ( "java8.al2", + "8", USING_GRADLE_KOTLIN_PATH, EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, EXPECTED_GRADLE_DEPENDENCIES, ), ( "java8.al2", + "8", USING_MAVEN_PATH, EXPECTED_FILES_PROJECT_MANIFEST_MAVEN, EXPECTED_MAVEN_DEPENDENCIES, ), - ] - ) - def test_building_java8_in_process_with_arm_architecture( - self, runtime, code_path, expected_files, expected_dependencies - ): - self._test_with_building_java( - runtime, - os.path.join(code_path, "8"), - expected_files, - expected_dependencies, - False, - self.test_data_path, - ARM64, - ) - - @parameterized.expand( - [ ( "java11", + "11", USING_GRADLE_PATH, EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, EXPECTED_GRADLE_DEPENDENCIES, ), ( "java11", + "11", USING_GRADLEW_PATH, EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, EXPECTED_GRADLE_DEPENDENCIES, ), ( "java11", + "11", USING_GRADLE_KOTLIN_PATH, EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, EXPECTED_GRADLE_DEPENDENCIES, ), ( "java11", + "11", USING_MAVEN_PATH, EXPECTED_FILES_PROJECT_MANIFEST_MAVEN, EXPECTED_MAVEN_DEPENDENCIES, ), - ] - ) - def test_building_java11_in_process_with_arm_architecture( - self, runtime, code_path, expected_files, expected_dependencies - ): - self._test_with_building_java( - runtime, - os.path.join(code_path, "11"), - expected_files, - expected_dependencies, - False, - self.test_data_path, - ARM64, - ) - - @parameterized.expand( - [ ( "java17", + "17", USING_GRADLE_PATH, EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, EXPECTED_GRADLE_DEPENDENCIES, ), ( "java17", + "17", USING_GRADLEW_PATH, EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, EXPECTED_GRADLE_DEPENDENCIES, ), ( "java17", + "17", USING_GRADLE_KOTLIN_PATH, EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, EXPECTED_GRADLE_DEPENDENCIES, ), ( "java17", + "17", + USING_MAVEN_PATH, + EXPECTED_FILES_PROJECT_MANIFEST_MAVEN, + EXPECTED_MAVEN_DEPENDENCIES, + ), + ( + "java21", + "21", + USING_GRADLE_PATH, + EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, + EXPECTED_GRADLE_DEPENDENCIES, + ), + ( + "java21", + "21", + USING_GRADLEW_PATH, + EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, + EXPECTED_GRADLE_DEPENDENCIES, + ), + ( + "java21", + "21", + USING_GRADLE_KOTLIN_PATH, + EXPECTED_FILES_PROJECT_MANIFEST_GRADLE, + EXPECTED_GRADLE_DEPENDENCIES, + ), + ( + "java21", + "21", USING_MAVEN_PATH, EXPECTED_FILES_PROJECT_MANIFEST_MAVEN, EXPECTED_MAVEN_DEPENDENCIES, ), ] ) - def test_building_java17_in_process_with_arm_architecture( - self, runtime, code_path, expected_files, expected_dependencies + def test_building_java_in_process_with_arm_architecture( + self, runtime, runtime_version, code_path, expected_files, expected_dependencies ): self._test_with_building_java( runtime, - os.path.join(code_path, "17"), + os.path.join(code_path, runtime_version), expected_files, expected_dependencies, False, diff --git a/tests/integration/init/test_init_command.py b/tests/integration/init/test_init_command.py index 0e6a40737f..d59519e448 100644 --- a/tests/integration/init/test_init_command.py +++ b/tests/integration/init/test_init_command.py @@ -476,6 +476,69 @@ def test_init_command_passes_with_disabled_application_insights(self): self.assertTrue(Path(temp, "sam-app").is_dir()) self._assert_template_with_cfn_lint(Path(temp, "sam-app")) + def test_init_command_passes_with_structured_logging(self): + with tempfile.TemporaryDirectory() as temp: + process = Popen( + [ + get_sam_command(), + "init", + "--runtime", + "nodejs14.x", + "--dependency-manager", + "npm", + "--app-template", + "hello-world", + "--name", + "sam-app", + "--no-interactive", + "-o", + temp, + "--tracing", + "--structured-logging", + ] + ) + try: + process.communicate(timeout=TIMEOUT) + except TimeoutExpired: + process.kill() + raise + + self.assertEqual(process.returncode, 0) + self.assertTrue(Path(temp, "sam-app").is_dir()) + # TODO: ungate once cfn-lint support `Structured Logging` + # self._assert_template_with_cfn_lint(Path(temp, "sam-app")) + + def test_init_command_passes_with_no_structured_logging(self): + with tempfile.TemporaryDirectory() as temp: + process = Popen( + [ + get_sam_command(), + "init", + "--runtime", + "nodejs14.x", + "--dependency-manager", + "npm", + "--app-template", + "hello-world", + "--name", + "sam-app", + "--no-interactive", + "-o", + temp, + "--no-tracing", + "--no-structured-logging", + ] + ) + try: + process.communicate(timeout=TIMEOUT) + except TimeoutExpired: + process.kill() + raise + + self.assertEqual(process.returncode, 0) + self.assertTrue(Path(temp, "sam-app").is_dir()) + self._assert_template_with_cfn_lint(Path(temp, "sam-app")) + def _assert_template_with_cfn_lint(self, cwd): """Assert if the generated project passes cfn-lint""" cmd_list = [ @@ -843,6 +906,7 @@ def test_interactive_init(self): # 1: Hello World Example # N: Would you like to enable X-Ray tracing on the function(s) in your application? [y/N] # Y: Would you like to enable monitoring using Cloudwatch Application Insights? [y/N] + # Y: Would you like to set Structured Logging in JSON format on your Lambda functions? [y/N] user_input = """ 1 1 @@ -852,6 +916,7 @@ def test_interactive_init(self): 1 N Y +Y sam-interactive-init-app """ with tempfile.TemporaryDirectory() as temp: @@ -872,6 +937,7 @@ def test_interactive_init_default_runtime(self): Y N N +N sam-interactive-init-app-default-runtime """ with tempfile.TemporaryDirectory() as temp: diff --git a/tests/integration/testdata/buildcmd/Java/gradle-kotlin/21/build.gradle.kts b/tests/integration/testdata/buildcmd/Java/gradle-kotlin/21/build.gradle.kts new file mode 100644 index 0000000000..c5fcad46e6 --- /dev/null +++ b/tests/integration/testdata/buildcmd/Java/gradle-kotlin/21/build.gradle.kts @@ -0,0 +1,15 @@ +plugins { + java +} + +repositories { + mavenCentral() +} + +dependencies { + implementation("software.amazon.awssdk:annotations:2.1.0") + implementation("com.amazonaws:aws-lambda-java-core:1.1.0") +} + +java.sourceCompatibility = JavaVersion.VERSION_21 +java.targetCompatibility = JavaVersion.VERSION_21 \ No newline at end of file diff --git a/tests/integration/testdata/buildcmd/Java/gradle-kotlin/21/src/main/java/aws/example/Hello.java b/tests/integration/testdata/buildcmd/Java/gradle-kotlin/21/src/main/java/aws/example/Hello.java new file mode 100644 index 0000000000..db02d37583 --- /dev/null +++ b/tests/integration/testdata/buildcmd/Java/gradle-kotlin/21/src/main/java/aws/example/Hello.java @@ -0,0 +1,13 @@ +package aws.example; + + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.LambdaLogger; + +public class Hello { + public String myHandler(Context context) { + LambdaLogger logger = context.getLogger(); + logger.log("Function Invoked\n"); + return "Hello World"; + } +} diff --git a/tests/integration/testdata/buildcmd/Java/gradle/21/build.gradle b/tests/integration/testdata/buildcmd/Java/gradle/21/build.gradle new file mode 100644 index 0000000000..7d6d11838d --- /dev/null +++ b/tests/integration/testdata/buildcmd/Java/gradle/21/build.gradle @@ -0,0 +1,15 @@ +plugins { + id 'java' +} + +repositories { + mavenCentral() +} + +dependencies { + implementation 'software.amazon.awssdk:annotations:2.1.0' + implementation 'com.amazonaws:aws-lambda-java-core:1.1.0' +} + +java.sourceCompatibility = JavaVersion.VERSION_21 +java.targetCompatibility = JavaVersion.VERSION_21 \ No newline at end of file diff --git a/tests/integration/testdata/buildcmd/Java/gradle/21/src/main/java/aws/example/Hello.java b/tests/integration/testdata/buildcmd/Java/gradle/21/src/main/java/aws/example/Hello.java new file mode 100644 index 0000000000..db02d37583 --- /dev/null +++ b/tests/integration/testdata/buildcmd/Java/gradle/21/src/main/java/aws/example/Hello.java @@ -0,0 +1,13 @@ +package aws.example; + + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.LambdaLogger; + +public class Hello { + public String myHandler(Context context) { + LambdaLogger logger = context.getLogger(); + logger.log("Function Invoked\n"); + return "Hello World"; + } +} diff --git a/tests/integration/testdata/buildcmd/Java/gradlew/11/gradle/wrapper/gradle-wrapper.jar b/tests/integration/testdata/buildcmd/Java/gradlew/11/gradle/wrapper/gradle-wrapper.jar index 41d9927a4d..7f93135c49 100644 Binary files a/tests/integration/testdata/buildcmd/Java/gradlew/11/gradle/wrapper/gradle-wrapper.jar and b/tests/integration/testdata/buildcmd/Java/gradlew/11/gradle/wrapper/gradle-wrapper.jar differ diff --git a/tests/integration/testdata/buildcmd/Java/gradlew/11/gradle/wrapper/gradle-wrapper.properties b/tests/integration/testdata/buildcmd/Java/gradlew/11/gradle/wrapper/gradle-wrapper.properties index 41dfb87909..3fa8f862f7 100644 --- a/tests/integration/testdata/buildcmd/Java/gradlew/11/gradle/wrapper/gradle-wrapper.properties +++ b/tests/integration/testdata/buildcmd/Java/gradlew/11/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/tests/integration/testdata/buildcmd/Java/gradlew/11/gradlew b/tests/integration/testdata/buildcmd/Java/gradlew/11/gradlew index 1b6c787337..1aa94a4269 100755 --- a/tests/integration/testdata/buildcmd/Java/gradlew/11/gradlew +++ b/tests/integration/testdata/buildcmd/Java/gradlew/11/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -80,13 +80,11 @@ do esac done -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" +# This is normally unused +# shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -133,22 +131,29 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -193,11 +198,15 @@ if "$cygwin" || "$msys" ; then done fi -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ @@ -205,6 +214,12 @@ set -- \ org.gradle.wrapper.GradleWrapperMain \ "$@" +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. diff --git a/tests/integration/testdata/buildcmd/Java/gradlew/11/gradlew.bat b/tests/integration/testdata/buildcmd/Java/gradlew/11/gradlew.bat index 107acd32c4..6689b85bee 100644 --- a/tests/integration/testdata/buildcmd/Java/gradlew/11/gradlew.bat +++ b/tests/integration/testdata/buildcmd/Java/gradlew/11/gradlew.bat @@ -1,89 +1,92 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/tests/integration/testdata/buildcmd/Java/gradlew/17/gradle/wrapper/gradle-wrapper.jar b/tests/integration/testdata/buildcmd/Java/gradlew/17/gradle/wrapper/gradle-wrapper.jar index 41d9927a4d..7f93135c49 100644 Binary files a/tests/integration/testdata/buildcmd/Java/gradlew/17/gradle/wrapper/gradle-wrapper.jar and b/tests/integration/testdata/buildcmd/Java/gradlew/17/gradle/wrapper/gradle-wrapper.jar differ diff --git a/tests/integration/testdata/buildcmd/Java/gradlew/17/gradle/wrapper/gradle-wrapper.properties b/tests/integration/testdata/buildcmd/Java/gradlew/17/gradle/wrapper/gradle-wrapper.properties index 41dfb87909..3fa8f862f7 100644 --- a/tests/integration/testdata/buildcmd/Java/gradlew/17/gradle/wrapper/gradle-wrapper.properties +++ b/tests/integration/testdata/buildcmd/Java/gradlew/17/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/tests/integration/testdata/buildcmd/Java/gradlew/17/gradlew b/tests/integration/testdata/buildcmd/Java/gradlew/17/gradlew index 1b6c787337..1aa94a4269 100755 --- a/tests/integration/testdata/buildcmd/Java/gradlew/17/gradlew +++ b/tests/integration/testdata/buildcmd/Java/gradlew/17/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -80,13 +80,11 @@ do esac done -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" +# This is normally unused +# shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -133,22 +131,29 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -193,11 +198,15 @@ if "$cygwin" || "$msys" ; then done fi -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ @@ -205,6 +214,12 @@ set -- \ org.gradle.wrapper.GradleWrapperMain \ "$@" +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. diff --git a/tests/integration/testdata/buildcmd/Java/gradlew/17/gradlew.bat b/tests/integration/testdata/buildcmd/Java/gradlew/17/gradlew.bat index 107acd32c4..6689b85bee 100644 --- a/tests/integration/testdata/buildcmd/Java/gradlew/17/gradlew.bat +++ b/tests/integration/testdata/buildcmd/Java/gradlew/17/gradlew.bat @@ -1,89 +1,92 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/tests/integration/testdata/buildcmd/Java/gradlew/21/build.gradle b/tests/integration/testdata/buildcmd/Java/gradlew/21/build.gradle new file mode 100644 index 0000000000..7d6d11838d --- /dev/null +++ b/tests/integration/testdata/buildcmd/Java/gradlew/21/build.gradle @@ -0,0 +1,15 @@ +plugins { + id 'java' +} + +repositories { + mavenCentral() +} + +dependencies { + implementation 'software.amazon.awssdk:annotations:2.1.0' + implementation 'com.amazonaws:aws-lambda-java-core:1.1.0' +} + +java.sourceCompatibility = JavaVersion.VERSION_21 +java.targetCompatibility = JavaVersion.VERSION_21 \ No newline at end of file diff --git a/tests/integration/testdata/buildcmd/Java/gradlew/21/gradle/wrapper/gradle-wrapper.jar b/tests/integration/testdata/buildcmd/Java/gradlew/21/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000..7f93135c49 Binary files /dev/null and b/tests/integration/testdata/buildcmd/Java/gradlew/21/gradle/wrapper/gradle-wrapper.jar differ diff --git a/tests/integration/testdata/buildcmd/Java/gradlew/21/gradle/wrapper/gradle-wrapper.properties b/tests/integration/testdata/buildcmd/Java/gradlew/21/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000..3fa8f862f7 --- /dev/null +++ b/tests/integration/testdata/buildcmd/Java/gradlew/21/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/tests/integration/testdata/buildcmd/Java/gradlew/21/gradlew b/tests/integration/testdata/buildcmd/Java/gradlew/21/gradlew new file mode 100755 index 0000000000..1aa94a4269 --- /dev/null +++ b/tests/integration/testdata/buildcmd/Java/gradlew/21/gradlew @@ -0,0 +1,249 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/tests/integration/testdata/buildcmd/Java/gradlew/21/gradlew.bat b/tests/integration/testdata/buildcmd/Java/gradlew/21/gradlew.bat new file mode 100644 index 0000000000..6689b85bee --- /dev/null +++ b/tests/integration/testdata/buildcmd/Java/gradlew/21/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/tests/integration/testdata/buildcmd/Java/gradlew/21/src/main/java/aws/example/Hello.java b/tests/integration/testdata/buildcmd/Java/gradlew/21/src/main/java/aws/example/Hello.java new file mode 100644 index 0000000000..db02d37583 --- /dev/null +++ b/tests/integration/testdata/buildcmd/Java/gradlew/21/src/main/java/aws/example/Hello.java @@ -0,0 +1,13 @@ +package aws.example; + + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.LambdaLogger; + +public class Hello { + public String myHandler(Context context) { + LambdaLogger logger = context.getLogger(); + logger.log("Function Invoked\n"); + return "Hello World"; + } +} diff --git a/tests/integration/testdata/buildcmd/Java/gradlew/21/src/main/java/aws/example/SecondFunction.java b/tests/integration/testdata/buildcmd/Java/gradlew/21/src/main/java/aws/example/SecondFunction.java new file mode 100644 index 0000000000..24a06e2582 --- /dev/null +++ b/tests/integration/testdata/buildcmd/Java/gradlew/21/src/main/java/aws/example/SecondFunction.java @@ -0,0 +1,13 @@ +package aws.example; + + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.LambdaLogger; + +public class SecondFunction { + public String myHandler(Context context) { + LambdaLogger logger = context.getLogger(); + logger.log("Second function Invoked\n"); + return "Hello Mars"; + } +} \ No newline at end of file diff --git a/tests/integration/testdata/buildcmd/Java/gradlew/8/build.gradle b/tests/integration/testdata/buildcmd/Java/gradlew/8/build.gradle index ba05d418ef..104fbd0644 100644 --- a/tests/integration/testdata/buildcmd/Java/gradlew/8/build.gradle +++ b/tests/integration/testdata/buildcmd/Java/gradlew/8/build.gradle @@ -11,5 +11,10 @@ dependencies { implementation 'com.amazonaws:aws-lambda-java-core:1.1.0' } -java.sourceCompatibility = JavaVersion.VERSION_1_8 -java.targetCompatibility = JavaVersion.VERSION_1_8 \ No newline at end of file +// java.sourceCompatibility = JavaVersion.VERSION_1_8 +// java.targetCompatibility = JavaVersion.VERSION_1_8 +java { + toolchain { + languageVersion = JavaLanguageVersion.of(8) + } +} \ No newline at end of file diff --git a/tests/integration/testdata/buildcmd/Java/gradlew/8/gradle/wrapper/gradle-wrapper.jar b/tests/integration/testdata/buildcmd/Java/gradlew/8/gradle/wrapper/gradle-wrapper.jar index 41d9927a4d..7f93135c49 100644 Binary files a/tests/integration/testdata/buildcmd/Java/gradlew/8/gradle/wrapper/gradle-wrapper.jar and b/tests/integration/testdata/buildcmd/Java/gradlew/8/gradle/wrapper/gradle-wrapper.jar differ diff --git a/tests/integration/testdata/buildcmd/Java/gradlew/8/gradle/wrapper/gradle-wrapper.properties b/tests/integration/testdata/buildcmd/Java/gradlew/8/gradle/wrapper/gradle-wrapper.properties index 41dfb87909..3fa8f862f7 100644 --- a/tests/integration/testdata/buildcmd/Java/gradlew/8/gradle/wrapper/gradle-wrapper.properties +++ b/tests/integration/testdata/buildcmd/Java/gradlew/8/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/tests/integration/testdata/buildcmd/Java/gradlew/8/gradlew b/tests/integration/testdata/buildcmd/Java/gradlew/8/gradlew index 1b6c787337..1aa94a4269 100755 --- a/tests/integration/testdata/buildcmd/Java/gradlew/8/gradlew +++ b/tests/integration/testdata/buildcmd/Java/gradlew/8/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -80,13 +80,11 @@ do esac done -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" +# This is normally unused +# shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -133,22 +131,29 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -193,11 +198,15 @@ if "$cygwin" || "$msys" ; then done fi -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ @@ -205,6 +214,12 @@ set -- \ org.gradle.wrapper.GradleWrapperMain \ "$@" +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. diff --git a/tests/integration/testdata/buildcmd/Java/gradlew/8/gradlew.bat b/tests/integration/testdata/buildcmd/Java/gradlew/8/gradlew.bat index 107acd32c4..6689b85bee 100644 --- a/tests/integration/testdata/buildcmd/Java/gradlew/8/gradlew.bat +++ b/tests/integration/testdata/buildcmd/Java/gradlew/8/gradlew.bat @@ -1,89 +1,92 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/tests/integration/testdata/buildcmd/Java/maven/21/pom.xml b/tests/integration/testdata/buildcmd/Java/maven/21/pom.xml new file mode 100644 index 0000000000..69d4f4a969 --- /dev/null +++ b/tests/integration/testdata/buildcmd/Java/maven/21/pom.xml @@ -0,0 +1,26 @@ + + 4.0.0 + helloworld + HelloWorld + 1.0 + jar + A sample Hello World created for SAM CLI. + + 21 + 21 + + + + + com.amazonaws + aws-lambda-java-core + 1.1.0 + + + software.amazon.awssdk + annotations + 2.1.0 + + + \ No newline at end of file diff --git a/tests/integration/testdata/buildcmd/Java/maven/21/src/main/java/aws/example/Hello.java b/tests/integration/testdata/buildcmd/Java/maven/21/src/main/java/aws/example/Hello.java new file mode 100644 index 0000000000..9f6e4084e9 --- /dev/null +++ b/tests/integration/testdata/buildcmd/Java/maven/21/src/main/java/aws/example/Hello.java @@ -0,0 +1,13 @@ +package aws.example; + + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.LambdaLogger; + +public class Hello { + public String myHandler(Context context) { + LambdaLogger logger = context.getLogger(); + logger.log("Function Invoked\n"); + return "Hello World"; + } +} \ No newline at end of file diff --git a/tests/integration/testdata/buildcmd/Python/requirements.txt b/tests/integration/testdata/buildcmd/Python/requirements.txt index cfc5fd779a..830e1c4b89 100644 --- a/tests/integration/testdata/buildcmd/Python/requirements.txt +++ b/tests/integration/testdata/buildcmd/Python/requirements.txt @@ -2,7 +2,9 @@ # NOTE: Fixing to <1.20.3 as numpy1.20.3 started to use a new wheel naming convention (PEP 600) numpy<1.20.3; python_version <= '3.9' -numpy==1.23.5; python_version >= '3.10' +numpy==1.23.5; python_version == '3.10' +numpy==1.23.5; python_version == '3.11' +numpy==1.26.1; python_version == '3.12' # `cryptography` has a dependency on `pycparser` which, for some reason doesn't build inside a Docker container. # Turning this off until we resolve this issue: https://github.com/awslabs/aws-lambda-builders/issues/29 # cryptography~=2.4 diff --git a/tests/integration/testdata/buildcmd/PythonPEP600/requirements.txt b/tests/integration/testdata/buildcmd/PythonPEP600/requirements.txt index a58b87977c..af06dbb85c 100644 --- a/tests/integration/testdata/buildcmd/PythonPEP600/requirements.txt +++ b/tests/integration/testdata/buildcmd/PythonPEP600/requirements.txt @@ -1,6 +1,9 @@ # These are some hard packages to build. Using them here helps us verify that building works on various platforms # these dependency versions use PEP600 -numpy==1.20.3 -greenlet==1.1.0 -sqlalchemy==1.4.15 +numpy==1.20.3; python_version <= '3.9' +numpy==1.23.5; python_version == '3.10' +numpy==1.23.5; python_version == '3.11' +numpy==1.26.1; python_version == '3.12' +greenlet==3.0.1 +sqlalchemy==2.0.23 diff --git a/tests/integration/validate/test_validate_command.py b/tests/integration/validate/test_validate_command.py index 01bf663abb..900a3af480 100644 --- a/tests/integration/validate/test_validate_command.py +++ b/tests/integration/validate/test_validate_command.py @@ -133,6 +133,7 @@ def test_lint_supported_runtimes(self): supported_runtimes = [ "dotnet6", "go1.x", + "java21", "java17", "java11", "java8", diff --git a/tests/unit/commands/init/test_cli.py b/tests/unit/commands/init/test_cli.py index 776bce490b..d6518927ed 100644 --- a/tests/unit/commands/init/test_cli.py +++ b/tests/unit/commands/init/test_cli.py @@ -118,6 +118,7 @@ def test_init_cli(self, generate_project_patch, git_repo_clone_mock): extra_context=None, tracing=False, application_insights=False, + structured_logging=True, ) # THEN we should receive no errors @@ -134,6 +135,7 @@ def test_init_cli(self, generate_project_patch, git_repo_clone_mock): self.extra_context_as_json, False, False, + True, ) @patch("samcli.lib.utils.git_repo.GitRepo.clone") @@ -158,6 +160,7 @@ def test_init_cli_node(self, generate_project_patch, git_repo_clone_mock): extra_context=None, tracing=False, application_insights=False, + structured_logging=False, ) # THEN we should receive no errors @@ -173,6 +176,7 @@ def test_init_cli_node(self, generate_project_patch, git_repo_clone_mock): {"runtime": "nodejs20.x", "project_name": "testing project", "architectures": {"value": ["x86_64"]}}, False, False, + False, ) @patch("samcli.lib.utils.git_repo.GitRepo.clone") @@ -197,6 +201,7 @@ def test_init_image_cli(self, generate_project_patch, git_repo_clone_mock): extra_context=None, tracing=False, application_insights=False, + structured_logging=False, ) # THEN we should receive no errors @@ -212,6 +217,7 @@ def test_init_image_cli(self, generate_project_patch, git_repo_clone_mock): {"runtime": "nodejs12.x", "project_name": "testing project", "architectures": {"value": [ARM64]}}, False, False, + False, ) @patch("samcli.lib.utils.git_repo.GitRepo.clone") @@ -236,6 +242,7 @@ def test_init_cli_with_tracing(self, generate_project_patch, git_repo_clone_mock extra_context=None, tracing=True, application_insights=False, + structured_logging=False, ) # THEN we should receive no errors @@ -252,6 +259,7 @@ def test_init_cli_with_tracing(self, generate_project_patch, git_repo_clone_mock self.extra_context_as_json, True, False, + False, ) @patch("samcli.lib.utils.git_repo.GitRepo.clone") @@ -276,6 +284,7 @@ def test_init_cli_with_application_insights(self, generate_project_patch, git_re extra_context=None, tracing=False, application_insights=True, + structured_logging=False, ) # THEN we should receive no errors @@ -292,6 +301,7 @@ def test_init_cli_with_application_insights(self, generate_project_patch, git_re self.extra_context_as_json, False, True, + False, ) @patch("samcli.lib.utils.git_repo.GitRepo.clone") @@ -316,6 +326,7 @@ def test_init_image_java_cli(self, generate_project_patch, git_repo_clone_mock): extra_context=None, tracing=False, application_insights=False, + structured_logging=True, ) # THEN we should receive no errors @@ -331,6 +342,7 @@ def test_init_image_java_cli(self, generate_project_patch, git_repo_clone_mock): {"runtime": "java11", "project_name": "testing project", "architectures": {"value": [X86_64]}}, False, False, + True, ) @patch("samcli.lib.utils.git_repo.GitRepo.clone") @@ -355,6 +367,7 @@ def test_init_fails_invalid_template(self, git_repo_clone_mock): extra_context=None, tracing=False, application_insights=False, + structured_logging=False, ) @patch("samcli.lib.utils.git_repo.GitRepo.clone") @@ -379,6 +392,7 @@ def test_init_fails_invalid_dep_mgr(self, git_repo_clone_mock): extra_context=None, tracing=False, application_insights=False, + structured_logging=False, ) @patch("samcli.lib.utils.git_repo.GitRepo.clone") @@ -409,6 +423,7 @@ def test_init_cli_generate_project_fails(self, generate_project_patch, git_repo_ extra_context=None, tracing=False, application_insights=False, + structured_logging=False, ) generate_project_patch.assert_called_with( @@ -420,6 +435,7 @@ def test_init_cli_generate_project_fails(self, generate_project_patch, git_repo_ self.no_input, False, False, + False, ) @patch("samcli.lib.utils.git_repo.GitRepo.clone") @@ -450,6 +466,7 @@ def test_init_cli_generate_project_image_fails(self, generate_project_patch, git extra_context=None, tracing=False, application_insights=False, + structured_logging=False, ) generate_project_patch.assert_called_with( @@ -461,6 +478,7 @@ def test_init_cli_generate_project_image_fails(self, generate_project_patch, git self.no_input, False, False, + False, ) @patch("samcli.lib.utils.git_repo.GitRepo.clone") @@ -485,6 +503,7 @@ def test_init_cli_with_extra_context_parameter_not_passed(self, generate_project extra_context=None, tracing=False, application_insights=False, + structured_logging=False, ) # THEN we should receive no errors @@ -500,6 +519,7 @@ def test_init_cli_with_extra_context_parameter_not_passed(self, generate_project self.extra_context_as_json, False, False, + False, ) @patch("samcli.lib.utils.git_repo.GitRepo.clone") @@ -524,6 +544,7 @@ def test_init_cli_with_extra_context_parameter_passed(self, generate_project_pat extra_context='{"schema_name":"events", "schema_type":"aws"}', tracing=False, application_insights=False, + structured_logging=False, ) # THEN we should receive no errors and right extra_context should be passed @@ -544,6 +565,7 @@ def test_init_cli_with_extra_context_parameter_passed(self, generate_project_pat }, False, False, + False, ) @patch("samcli.lib.utils.git_repo.GitRepo.clone") @@ -570,6 +592,7 @@ def test_init_cli_with_extra_context_not_overriding_default_parameter( extra_context='{"project_name": "my_project", "runtime": "java8", "schema_name":"events", "schema_type": "aws"}', tracing=False, application_insights=False, + structured_logging=False, ) # THEN extra_context should have not overridden default_parameters(name, runtime) @@ -590,6 +613,7 @@ def test_init_cli_with_extra_context_not_overriding_default_parameter( }, False, False, + False, ) @patch("samcli.lib.utils.git_repo.GitRepo.clone") @@ -614,6 +638,7 @@ def test_init_cli_with_extra_context_input_as_wrong_json_raises_exception(self, extra_context='{"project_name", "my_project", "runtime": "java8", "schema_name":"events", "schema_type": "aws"}', tracing=False, application_insights=False, + structured_logging=False, ) @patch("samcli.commands.init.init_generator.generate_project") @@ -637,6 +662,7 @@ def test_init_cli_must_set_default_context_when_location_is_provided(self, gener extra_context='{"schema_name":"events", "schema_type": "aws"}', tracing=False, application_insights=False, + structured_logging=False, ) # THEN should set default parameter(name, runtime) as extra_context @@ -657,6 +683,7 @@ def test_init_cli_must_set_default_context_when_location_is_provided(self, gener }, False, False, + False, ) @patch("samcli.commands.init.init_generator.generate_project") @@ -680,6 +707,7 @@ def test_init_cli_must_only_set_passed_project_name_when_location_is_provided(se extra_context='{"schema_name":"events", "schema_type": "aws"}', tracing=False, application_insights=False, + structured_logging=True, ) # THEN extra_context should be without runtime @@ -699,6 +727,7 @@ def test_init_cli_must_only_set_passed_project_name_when_location_is_provided(se }, False, False, + True, ) @patch("samcli.commands.init.init_generator.generate_project") @@ -722,6 +751,7 @@ def test_init_cli_must_only_set_passed_runtime_when_location_is_provided(self, g extra_context='{"schema_name":"events", "schema_type": "aws"}', tracing=False, application_insights=False, + structured_logging=True, ) # THEN extra_context should be without name @@ -741,6 +771,7 @@ def test_init_cli_must_only_set_passed_runtime_when_location_is_provided(self, g }, False, False, + True, ) @patch("samcli.lib.utils.git_repo.GitRepo.clone") @@ -766,6 +797,7 @@ def test_init_cli_with_extra_context_parameter_passed_as_escaped(self, generate_ extra_context='{\"schema_name\":\"events\", \"schema_type\":\"aws\"}', tracing=False, application_insights= False, + structured_logging=False # fmt: on ) @@ -787,6 +819,7 @@ def test_init_cli_with_extra_context_parameter_passed_as_escaped(self, generate_ }, False, False, + False, ) @patch.object(InitTemplates, "__init__", MockInitTemplates.__init__) @@ -900,6 +933,7 @@ def test_init_cli_int_with_event_bridge_app_template( 2 N N +N test-project Y 1 @@ -930,6 +964,7 @@ def test_init_cli_int_with_event_bridge_app_template( }, False, False, + False, ) get_schemas_client_mock.assert_called_once_with(None, "ap-northeast-1") do_extract_and_merge_schemas_code_mock.do_extract_and_merge_schemas_code_mock( @@ -984,6 +1019,7 @@ def test_init_cli_int_with_image_app_template( 1 N N +y test-project """ runner = CliRunner() @@ -1000,6 +1036,7 @@ def test_init_cli_int_with_image_app_template( {"project_name": "test-project", "runtime": "java8", "architectures": {"value": [X86_64]}}, False, False, + True, ) @patch.object(InitTemplates, "__init__", MockInitTemplates.__init__) @@ -1116,6 +1153,7 @@ def test_init_cli_int_with_event_bridge_app_template_and_aws_configuration( 2 N N +N test-project N 1 @@ -1148,6 +1186,7 @@ def test_init_cli_int_with_event_bridge_app_template_and_aws_configuration( }, False, False, + False, ) get_schemas_client_mock.assert_called_once_with("default", "us-east-1") do_extract_and_merge_schemas_code_mock.do_extract_and_merge_schemas_code("result.zip", ".", "test-project", ANY) @@ -1245,6 +1284,7 @@ def test_init_cli_int_with_event_bridge_app_template_and_aws_configuration_with_ 1 N N +N test-project N 1 @@ -1372,6 +1412,7 @@ def test_init_cli_int_with_download_manager_raises_exception( 2 N N +N test-project Y 1 @@ -1402,6 +1443,7 @@ def test_init_cli_int_with_download_manager_raises_exception( }, False, False, + False, ) get_schemas_client_mock.assert_called_once_with(None, "ap-northeast-1") do_extract_and_merge_schemas_code_mock.do_extract_and_merge_schemas_code_mock( @@ -1516,6 +1558,7 @@ def test_init_cli_int_with_schemas_details_raises_exception( 1 N N +N test-project Y 1 @@ -1551,6 +1594,7 @@ def test_init_passes_dynamic_event_bridge_template(self, generate_project_patch, architecture=ARM64, tracing=False, application_insights=False, + structured_logging=False, ) self.extra_context_as_json["architectures"] = {"value": [ARM64]} @@ -1566,6 +1610,7 @@ def test_init_passes_dynamic_event_bridge_template(self, generate_project_patch, self.extra_context_as_json, False, False, + False, ) @patch("samcli.lib.utils.git_repo.GitRepo.clone") @@ -1597,6 +1642,7 @@ def test_init_cli_int_from_location(self, generate_project_patch, git_repo_clone None, None, None, + None, ) @patch("samcli.commands.init.init_templates.InitTemplates._get_manifest") @@ -1624,6 +1670,7 @@ def test_init_cli_no_package_type(self, generate_project_patch, git_repo_clone_m "amazon/python3.8-base", "--dependency-manager", "pip", + "--no-structured-logging", ] runner = CliRunner() result = runner.invoke(init_cmd, args=args, input=user_input) @@ -1631,7 +1678,7 @@ def test_init_cli_no_package_type(self, generate_project_patch, git_repo_clone_m # THEN we should receive no errors self.assertFalse(result.exception) generate_project_patch.assert_called_once_with( - ANY, IMAGE, "python3.8", "pip", ".", "untitled6", True, ANY, False, False + ANY, IMAGE, "python3.8", "pip", ".", "untitled6", True, ANY, False, False, False ) @patch.object(InitTemplates, "__init__", MockInitTemplates.__init__) @@ -1674,6 +1721,7 @@ def test_init_cli_image_pool_with_base_image_having_multiple_managed_template_bu extra_context=self.extra_context, tracing=False, application_insights=False, + structured_logging=False, ) @patch.object(InitTemplates, "__init__", MockInitTemplates.__init__) @@ -1716,6 +1764,7 @@ def test_init_cli_image_pool_with_base_image_having_multiple_managed_template_an extra_context=self.extra_context, tracing=False, application_insights=False, + structured_logging=False, ) @patch.object(InitTemplates, "__init__", MockInitTemplates.__init__) @@ -1759,6 +1808,7 @@ def test_init_cli_image_pool_with_base_image_having_multiple_managed_template_wi extra_context=None, tracing=False, application_insights=False, + structured_logging=False, ) generate_project_patch.assert_called_once_with( ANY, # location @@ -1771,6 +1821,7 @@ def test_init_cli_image_pool_with_base_image_having_multiple_managed_template_wi ANY, False, False, + False, ) @patch.object(InitTemplates, "__init__", MockInitTemplates.__init__) @@ -1807,6 +1858,7 @@ def test_init_cli_image_pool_with_base_image_having_one_managed_template_does_no tracing=False, application_insights=False, architecture=None, + structured_logging=False, ) generate_project_patch.assert_called_once_with( ANY, # location @@ -1819,6 +1871,7 @@ def test_init_cli_image_pool_with_base_image_having_one_managed_template_does_no ANY, False, False, + False, ) @patch.object(InitTemplates, "__init__", MockInitTemplates.__init__) @@ -1855,6 +1908,7 @@ def test_init_cli_image_pool_with_base_image_having_one_managed_template_with_pr tracing=False, application_insights=False, architecture=None, + structured_logging=False, ) generate_project_patch.assert_called_once_with( ANY, # location @@ -1867,6 +1921,7 @@ def test_init_cli_image_pool_with_base_image_having_one_managed_template_with_pr ANY, False, False, + False, ) @patch.object(InitTemplates, "__init__", MockInitTemplates.__init__) @@ -1904,6 +1959,7 @@ def test_init_cli_image_pool_with_base_image_having_one_managed_template_with_pr tracing=False, application_insights=False, architecture=None, + structured_logging=False, ) @patch("samcli.lib.utils.git_repo.GitRepo.clone") @@ -1933,7 +1989,7 @@ def test_init_cli_must_pass_with_architecture_and_base_image(self, generate_proj # THEN we should receive no errors self.assertFalse(result.exception) generate_project_patch.assert_called_once_with( - ANY, IMAGE, "java11", "gradle", ".", "untitled6", True, ANY, None, None + ANY, IMAGE, "java11", "gradle", ".", "untitled6", True, ANY, None, None, None ) PackageType.explicit = ( False # Other tests fail after we pass --packge-type in this test, so let's reset this variable @@ -2008,6 +2064,7 @@ def test_init_cli_generate_default_hello_world_app( y N N +N test-project """ @@ -2025,6 +2082,7 @@ def test_init_cli_generate_default_hello_world_app( {"project_name": "test-project", "runtime": "python3.9", "architectures": {"value": ["x86_64"]}}, False, False, + False, ) @patch("samcli.commands.init.init_templates.InitTemplates.get_preprocessed_manifest") @@ -2097,6 +2155,7 @@ def test_init_cli_must_not_generate_default_hello_world_app( 1 N N +N test-project """ @@ -2114,6 +2173,7 @@ def test_init_cli_must_not_generate_default_hello_world_app( {"project_name": "test-project", "runtime": "java11", "architectures": {"value": ["x86_64"]}}, False, False, + False, ) def test_must_return_runtime_from_base_image_name(self): @@ -2278,6 +2338,7 @@ def test_init_fails_unsupported_dep_mgr_for_runtime(self, git_repo_clone_mock, c tracing=False, application_insights=False, architecture=X86_64, + structured_logging=False, ) expected_error_message = ( "Lambda Runtime java8 and dependency manager pip does not have an available initialization template." @@ -2298,14 +2359,7 @@ def test_init_cli_with_mismatch_dep_runtime(self, git_repo_clone_mock, _get_mani n """ - args = [ - "--name", - "untitled6", - "--runtime", - "go1.x", - "--dependency-manager", - "pip", - ] + args = ["--name", "untitled6", "--runtime", "go1.x", "--dependency-manager", "pip", "--no-structured-logging"] runner = CliRunner() result = runner.invoke(init_cmd, args=args, input=user_input) @@ -2379,6 +2433,7 @@ def test_init_cli_int_with_multiple_app_templates( 1 N N +N test-project """ runner = CliRunner() @@ -2395,6 +2450,7 @@ def test_init_cli_int_with_multiple_app_templates( {"project_name": "test-project", "runtime": "java11", "architectures": {"value": ["x86_64"]}}, False, False, + False, ) @patch("samcli.commands.init.init_templates.LOG") @@ -2463,6 +2519,7 @@ def test_init_cli_int_must_raise_for_unsupported_runtime( 1 N N +N test-project """ runner = CliRunner() @@ -2518,6 +2575,7 @@ def test_init_cli_int_must_raise_for_unsupported_dependency( 1 N N +N test-project """ runner = CliRunner() @@ -2591,6 +2649,7 @@ def test_init_cli_generate_hello_world_app_without_default_prompt( 1 N N +N test-project """ @@ -2608,6 +2667,7 @@ def test_init_cli_generate_hello_world_app_without_default_prompt( {"project_name": "test-project", "runtime": "java11", "architectures": {"value": ["x86_64"]}}, False, False, + False, ) @patch.object(InitTemplates, "__init__", MockInitTemplates.__init__) @@ -2682,6 +2742,7 @@ def test_init_cli_generate_app_template_provide_via_options( 1 N N +N test-project """ @@ -2699,6 +2760,7 @@ def test_init_cli_generate_app_template_provide_via_options( {"project_name": "test-project", "runtime": "java11", "architectures": {"value": ["x86_64"]}}, False, False, + False, ) def does_template_meet_filter_criteria(self): @@ -2765,6 +2827,7 @@ def test_init_cli_generate_app_template_from_local_cli_templates( 2 N N +N test-project """ @@ -2782,6 +2845,7 @@ def test_init_cli_generate_app_template_from_local_cli_templates( {"project_name": "test-project", "runtime": "java11", "architectures": {"value": ["x86_64"]}}, False, False, + False, ) @patch("samcli.local.common.runtime_template.INIT_RUNTIMES") @@ -2854,6 +2918,7 @@ def test_init_cli_generate_app_template_with_custom_runtime( 2 N N +N test-project """ @@ -2871,6 +2936,7 @@ def test_init_cli_generate_app_template_with_custom_runtime( {"project_name": "test-project", "runtime": "provided.al2", "architectures": {"value": ["x86_64"]}}, False, False, + False, ) @patch("samcli.commands.init.init_templates.InitTemplates._get_manifest") @@ -2931,6 +2997,7 @@ def test_init_cli_generate_app_template_with_custom_runtime_using_options( 1 N N +N test-project """ args = [ @@ -2952,6 +3019,7 @@ def test_init_cli_generate_app_template_with_custom_runtime_using_options( {"project_name": "test-project", "runtime": "provided.al2", "architectures": {"value": ["x86_64"]}}, False, False, + False, ) @patch("samcli.commands.init.init_templates.InitTemplates.get_preprocessed_manifest") @@ -3020,6 +3088,7 @@ def test_init_cli_generate_app_template_provide_via_tracing_options( N 1 N +N test-project """ @@ -3037,6 +3106,7 @@ def test_init_cli_generate_app_template_provide_via_tracing_options( {"project_name": "test-project", "runtime": "java11", "architectures": {"value": ["x86_64"]}}, True, False, + False, ) @patch("samcli.commands.init.init_templates.InitTemplates.get_preprocessed_manifest") @@ -3105,6 +3175,7 @@ def test_init_cli_generate_app_template_provide_via_application_insights_options N 1 N +N test-project """ @@ -3122,4 +3193,5 @@ def test_init_cli_generate_app_template_provide_via_application_insights_options {"project_name": "test-project", "runtime": "java11", "architectures": {"value": ["x86_64"]}}, False, True, + False, ) diff --git a/tests/unit/commands/local/lib/test_local_lambda.py b/tests/unit/commands/local/lib/test_local_lambda.py index dc5f4384bd..384771f753 100644 --- a/tests/unit/commands/local/lib/test_local_lambda.py +++ b/tests/unit/commands/local/lib/test_local_lambda.py @@ -253,6 +253,7 @@ def test_must_work_with_override_values( function_url_config=None, runtime_management_config=None, function_build_info=FunctionBuildInfo.BuildableZip, + logging_config={"LogFormat": "JSON"}, ) self.local_lambda.env_vars_values = env_vars_values @@ -264,6 +265,7 @@ def test_must_work_with_override_values( function.memory, function.timeout, function.handler, + function.logging_config, variables={"var1": "value1"}, shell_env_values=os_environ, override_values=expected_override_value, @@ -362,6 +364,7 @@ def test_must_work_with_invalid_environment_variable(self, environment_variable, function.memory, function.timeout, function.handler, + None, variables=None, shell_env_values=os_environ, override_values={}, diff --git a/tests/unit/commands/samconfig/test_samconfig.py b/tests/unit/commands/samconfig/test_samconfig.py index b2e0822c78..d0c373d18f 100644 --- a/tests/unit/commands/samconfig/test_samconfig.py +++ b/tests/unit/commands/samconfig/test_samconfig.py @@ -81,6 +81,7 @@ def test_init(self, do_cli_mock): '{"key": "value", "key2": "value2"}', None, ANY, + None, ) @patch("samcli.commands.validate.validate.do_cli") diff --git a/tests/unit/lib/observability/cw_logs/test_cw_log_group_provider.py b/tests/unit/lib/observability/cw_logs/test_cw_log_group_provider.py index 19c4746f37..ac7cd0843c 100644 --- a/tests/unit/lib/observability/cw_logs/test_cw_log_group_provider.py +++ b/tests/unit/lib/observability/cw_logs/test_cw_log_group_provider.py @@ -7,9 +7,32 @@ class TestLogGroupProvider_for_lambda_function(TestCase): - def test_must_return_log_group_name(self): + def test_must_return_default_log_group_name(self): expected = "/aws/lambda/my_function_name" - result = LogGroupProvider.for_lambda_function("my_function_name") + given_client_provider = Mock() + given_client_provider("Lambda").get_function_configuration.return_value = {} + + result = LogGroupProvider.for_lambda_function(given_client_provider, "my_function_name") + + self.assertEqual(expected, result) + + def test_must_return_custom_log_group_name(self): + expected = "my_log_group" + given_client_provider = Mock() + given_client_provider("Lambda").get_function_configuration.return_value = { + "LoggingConfig": {"LogGroup": "my_log_group"} + } + + result = LogGroupProvider.for_lambda_function(given_client_provider, "my_function_name") + + self.assertEqual(expected, result) + + def test_must_return_default_log_group_name_with_exception_raised(self): + expected = "/aws/lambda/my_function_name" + given_client_provider = Mock() + given_client_provider("Lambda").get_function_configuration.side_effect = Exception() + + result = LogGroupProvider.for_lambda_function(given_client_provider, "my_function_name") self.assertEqual(expected, result) diff --git a/tests/unit/local/docker/test_lambda_container.py b/tests/unit/local/docker/test_lambda_container.py index 8f3e43d31e..cf589ee65f 100644 --- a/tests/unit/local/docker/test_lambda_container.py +++ b/tests/unit/local/docker/test_lambda_container.py @@ -25,10 +25,12 @@ Runtime.python39.value, Runtime.python310.value, Runtime.python311.value, + Runtime.python312.value, Runtime.dotnet6.value, ] RUNTIMES_WITH_DEBUG_ENV_VARS_ONLY = [ + Runtime.java21.value, Runtime.java17.value, Runtime.java11.value, Runtime.java8.value, diff --git a/tests/unit/local/docker/test_lambda_debug_settings.py b/tests/unit/local/docker/test_lambda_debug_settings.py index e1fff17664..c05b8cd04e 100644 --- a/tests/unit/local/docker/test_lambda_debug_settings.py +++ b/tests/unit/local/docker/test_lambda_debug_settings.py @@ -10,6 +10,7 @@ Runtime.java8al2, Runtime.java11, Runtime.java17, + Runtime.java21, Runtime.dotnet6, Runtime.go1x, Runtime.nodejs12x, @@ -22,6 +23,7 @@ Runtime.python39, Runtime.python310, Runtime.python311, + Runtime.python312, ] diff --git a/tests/unit/local/docker/test_lambda_image.py b/tests/unit/local/docker/test_lambda_image.py index fa64833ab3..b56c13798c 100644 --- a/tests/unit/local/docker/test_lambda_image.py +++ b/tests/unit/local/docker/test_lambda_image.py @@ -31,6 +31,7 @@ class TestRuntime(TestCase): ("java8.al2", "java:8.al2-x86_64"), ("java11", "java:11-x86_64"), ("java17", "java:17-x86_64"), + ("java21", "java:21-x86_64"), ("go1.x", "go:1"), ("dotnet6", "dotnet:6-x86_64"), ("provided", "provided:alami"), diff --git a/tests/unit/local/lambdafn/test_env_vars.py b/tests/unit/local/lambdafn/test_env_vars.py index c0babe5fe5..f831bfe61a 100644 --- a/tests/unit/local/lambdafn/test_env_vars.py +++ b/tests/unit/local/lambdafn/test_env_vars.py @@ -13,15 +13,18 @@ def test_must_initialize_with_empty_values(self): memory = 123 timeout = 10 handler = "handler" + logging_config = {"logFormat": "JSON"} environ = EnvironmentVariables() environ.memory = memory environ.timeout = timeout environ.handler = handler + environ.logging_config = logging_config self.assertEqual(environ.memory, memory) self.assertEqual(environ.timeout, timeout) self.assertEqual(environ.handler, handler) + self.assertEqual(environ.logging_config, logging_config) def test_must_initialize_values_with_required_values(self): memory = 123 @@ -332,6 +335,101 @@ def test_must_work_with_partial_aws_creds(self): environ = EnvironmentVariables(self.name, self.memory, self.timeout, self.handler, aws_creds=creds) self.assertEqual(expected, environ._get_aws_variables()) + def test_must_work_with_text_logformat(self): + expected = { + "AWS_SAM_LOCAL": "true", + "AWS_LAMBDA_FUNCTION_MEMORY_SIZE": "1024", + "AWS_LAMBDA_FUNCTION_TIMEOUT": "123", + "AWS_LAMBDA_FUNCTION_HANDLER": "handler", + "AWS_LAMBDA_FUNCTION_NAME": self.name, + "AWS_LAMBDA_FUNCTION_VERSION": "$LATEST", + "AWS_LAMBDA_LOG_GROUP_NAME": f"aws/lambda/{self.name}", + "AWS_LAMBDA_LOG_STREAM_NAME": "$LATEST", + "AWS_ACCOUNT_ID": "123456789012", + # Default values assigned to these variables + "AWS_REGION": "us-east-1", + "AWS_DEFAULT_REGION": "us-east-1", + "AWS_ACCESS_KEY_ID": "defaultkey", + "AWS_SECRET_ACCESS_KEY": "defaultsecret", + "AWS_LAMBDA_LOG_FORMAT": "Text", + } + + logging_config = {"LogFormat": "Text"} + environ = EnvironmentVariables(self.name, self.memory, self.timeout, self.handler, logging_config) + self.assertEqual(expected, environ._get_aws_variables()) + + def test_must_work_with_default_json_logging_config(self): + expected = { + "AWS_SAM_LOCAL": "true", + "AWS_LAMBDA_FUNCTION_MEMORY_SIZE": "1024", + "AWS_LAMBDA_FUNCTION_TIMEOUT": "123", + "AWS_LAMBDA_FUNCTION_HANDLER": "handler", + "AWS_LAMBDA_FUNCTION_NAME": self.name, + "AWS_LAMBDA_FUNCTION_VERSION": "$LATEST", + "AWS_LAMBDA_LOG_GROUP_NAME": f"aws/lambda/{self.name}", + "AWS_LAMBDA_LOG_STREAM_NAME": "$LATEST", + "AWS_ACCOUNT_ID": "123456789012", + # Default values assigned to these variables + "AWS_REGION": "us-east-1", + "AWS_DEFAULT_REGION": "us-east-1", + "AWS_ACCESS_KEY_ID": "defaultkey", + "AWS_SECRET_ACCESS_KEY": "defaultsecret", + "AWS_LAMBDA_LOG_LEVEL": "INFO", + "AWS_LAMBDA_LOG_FORMAT": "JSON", + } + + logging_config = {"LogFormat": "JSON"} + environ = EnvironmentVariables(self.name, self.memory, self.timeout, self.handler, logging_config) + self.assertEqual(expected, environ._get_aws_variables()) + + def test_must_work_with_set_application_log_level(self): + expected = { + "AWS_SAM_LOCAL": "true", + "AWS_LAMBDA_FUNCTION_MEMORY_SIZE": "1024", + "AWS_LAMBDA_FUNCTION_TIMEOUT": "123", + "AWS_LAMBDA_FUNCTION_HANDLER": "handler", + "AWS_LAMBDA_FUNCTION_NAME": self.name, + "AWS_LAMBDA_FUNCTION_VERSION": "$LATEST", + "AWS_LAMBDA_LOG_GROUP_NAME": f"aws/lambda/{self.name}", + "AWS_LAMBDA_LOG_STREAM_NAME": "$LATEST", + "AWS_ACCOUNT_ID": "123456789012", + # Default values assigned to these variables + "AWS_REGION": "us-east-1", + "AWS_DEFAULT_REGION": "us-east-1", + "AWS_ACCESS_KEY_ID": "defaultkey", + "AWS_SECRET_ACCESS_KEY": "defaultsecret", + "AWS_LAMBDA_LOG_LEVEL": "TRACE", + "AWS_LAMBDA_LOG_FORMAT": "JSON", + } + + logging_config = {"LogFormat": "JSON", "ApplicationLogLevel": "TRACE"} + environ = EnvironmentVariables(self.name, self.memory, self.timeout, self.handler, logging_config) + self.assertEqual(expected, environ._get_aws_variables()) + + def test_must_work_with_custom_log_group_name(self): + expected = { + "AWS_SAM_LOCAL": "true", + "AWS_LAMBDA_FUNCTION_MEMORY_SIZE": "1024", + "AWS_LAMBDA_FUNCTION_TIMEOUT": "123", + "AWS_LAMBDA_FUNCTION_HANDLER": "handler", + "AWS_LAMBDA_FUNCTION_NAME": self.name, + "AWS_LAMBDA_FUNCTION_VERSION": "$LATEST", + "AWS_LAMBDA_LOG_GROUP_NAME": "myCustomLogGroup", + "AWS_LAMBDA_LOG_STREAM_NAME": "$LATEST", + "AWS_ACCOUNT_ID": "123456789012", + # Default values assigned to these variables + "AWS_REGION": "us-east-1", + "AWS_DEFAULT_REGION": "us-east-1", + "AWS_ACCESS_KEY_ID": "defaultkey", + "AWS_SECRET_ACCESS_KEY": "defaultsecret", + "AWS_LAMBDA_LOG_LEVEL": "TRACE", + "AWS_LAMBDA_LOG_FORMAT": "JSON", + } + + logging_config = {"LogFormat": "JSON", "ApplicationLogLevel": "TRACE", "LogGroup": "myCustomLogGroup"} + environ = EnvironmentVariables(self.name, self.memory, self.timeout, self.handler, logging_config) + self.assertEqual(expected, environ._get_aws_variables()) + class TestEnvironmentVariables_stringify_value(TestCase): def setUp(self):