From d20506beef28954bce5428b4658edd276a461003 Mon Sep 17 00:00:00 2001 From: Matt Muller Date: Sun, 26 Jan 2025 11:26:48 -0500 Subject: [PATCH 1/2] Version 3 --- .idea/.gitignore | 8 + .idea/misc.xml | 4 + .idea/modules.xml | 8 + .idea/vcs.xml | 6 + LICENSE | 372 +++++++-------- Makefile | 2 +- README.md | 1 - aws_lambda_ric.gemspec | 9 +- bin/aws_lambda_ric | 9 +- buildspec.yml | 23 + lib/aws_lambda_ric.rb | 69 ++- lib/aws_lambda_ric/aws_lambda_marshaller.rb | 2 - lib/aws_lambda_ric/bootstrap.rb | 45 -- lib/aws_lambda_ric/lambda_context.rb | 2 - lib/aws_lambda_ric/lambda_errors.rb | 11 +- lib/aws_lambda_ric/lambda_handler.rb | 6 +- lib/aws_lambda_ric/lambda_log_formatter.rb | 6 +- lib/aws_lambda_ric/lambda_logger.rb | 2 +- lib/aws_lambda_ric/lambda_server.rb | 24 +- lib/aws_lambda_ric/logger_patch.rb | 9 +- lib/aws_lambda_ric/telemetry_log_sink.rb | 27 +- lib/aws_lambda_ric/version.rb | 6 +- lib/aws_lambda_ric/xray_cause.rb | 8 +- .../codebuild-local/Dockerfile.agent | 2 +- .../codebuild-local/codebuild_build.sh | 2 +- test/integration/codebuild-local/test_all.sh | 3 +- test/integration/codebuild-local/test_one.sh | 3 +- .../codebuild/buildspec.os.alpine.1.yml | 45 +- .../codebuild/buildspec.os.alpine.2.yml | 44 +- .../codebuild/buildspec.os.amazonlinux.yml | 43 +- .../codebuild/buildspec.os.centos.yml | 110 ----- .../codebuild/buildspec.os.debian.yml | 44 +- .../codebuild/buildspec.os.ubuntu.yml | 46 +- test/integration/docker-compose.template.yml | 16 +- .../integration/docker/Dockerfile.echo.alpine | 1 - .../docker/Dockerfile.echo.amazonlinux | 1 - .../integration/docker/Dockerfile.echo.centos | 64 --- .../integration/docker/Dockerfile.echo.debian | 1 - .../integration/docker/Dockerfile.echo.ubuntu | 1 - test/run_tests.rb | 2 +- test/unit/harness-suite.json | 434 ------------------ test/unit/harness_test.rb | 115 ----- test/unit/lambda_log_formatter_test.rb | 6 +- test/unit/lambda_server_test.rb | 22 +- test/unit/resources/fd/test_fd | Bin 147 -> 123 bytes test/unit/resources/fd/test_file.txt | 13 + test/unit/telemetry_log_sink_test.rb | 30 +- test/unit/xray_cause_test.rb | 2 - 48 files changed, 487 insertions(+), 1222 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 buildspec.yml delete mode 100644 lib/aws_lambda_ric/bootstrap.rb delete mode 100644 test/integration/codebuild/buildspec.os.centos.yml delete mode 100644 test/integration/docker/Dockerfile.echo.centos delete mode 100644 test/unit/harness-suite.json delete mode 100644 test/unit/harness_test.rb create mode 100644 test/unit/resources/fd/test_file.txt diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..a98e134 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..828d50f --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/LICENSE b/LICENSE index e11442c..67db858 100644 --- a/LICENSE +++ b/LICENSE @@ -1,229 +1,175 @@ -Apache License -Version 2.0, January 2004 + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -http://www.apache.org/licenses/ TERMS -AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. - + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. - "License" shall mean the terms and conditions for use, reproduction, and -distribution as defined by Sections 1 through 9 of this document. - - - - -"Licensor" shall mean the copyright owner or entity authorized by the copyright -owner that is granting the License. - - - - "Legal Entity" shall mean the -union of the acting entity and all other entities that control, are controlled -by, or are under common control with that entity. For the purposes of this -definition, "control" means (i) the power, direct or indirect, to cause the -direction or management of such entity, whether by contract or otherwise, or (ii) -ownership of fifty percent (50%) or more of the outstanding shares, or (iii) -beneficial ownership of such entity. - - - - "You" (or "Your") shall mean -an individual or Legal Entity exercising permissions granted by this License. - - + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, -including but not limited to software source code, documentation source, and -configuration files. - - - - "Object" form shall mean any form resulting -from mechanical transformation or translation of a Source form, including but not -limited to compiled object code, generated documentation, and conversions to -other media types. - - - - "Work" shall mean the work of authorship, -whether in Source or Object form, made available under the License, as indicated -by a copyright notice that is included in or attached to the work (an example is -provided in the Appendix below). - - - - "Derivative Works" shall mean any -work, whether in Source or Object form, that is based on (or derived from) the -Work and for which the editorial revisions, annotations, elaborations, or other -modifications represent, as a whole, an original work of authorship. For the -purposes of this License, Derivative Works shall not include works that remain -separable from, or merely link (or bind by name) to the interfaces of, the Work -and Derivative Works thereof. - - - - "Contribution" shall mean any work -of authorship, including the original version of the Work and any modifications -or additions to that Work or Derivative Works thereof, that is intentionally -submitted to Licensor for inclusion in the Work by the copyright owner or by an -individual or Legal Entity authorized to submit on behalf of the copyright owner. -For the purposes of this definition, "submitted" means any form of electronic, -verbal, or written communication sent to the Licensor or its representatives, -including but not limited to communication on electronic mailing lists, source -code control systems, and issue tracking systems that are managed by, or on -behalf of, the Licensor for the purpose of discussing and improving the Work, but -excluding communication that is conspicuously marked or otherwise designated in -writing by the copyright owner as "Not a Contribution." - - - - -"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of -whom a Contribution has been received by Licensor and subsequently incorporated -within the Work. - - 2. Grant of Copyright License. Subject to the terms and -conditions of this License, each Contributor hereby grants to You a perpetual, -worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license -to reproduce, prepare Derivative Works of, publicly display, publicly perform, -sublicense, and distribute the Work and such Derivative Works in Source or Object -form. - - 3. Grant of Patent License. Subject to the terms and conditions of this -License, each Contributor hereby grants to You a perpetual, worldwide, -non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this -section) patent license to make, have made, use, offer to sell, sell, import, and -otherwise transfer the Work, where such license applies only to those patent -claims licensable by such Contributor that are necessarily infringed by their -Contribution(s) alone or by combination of their Contribution(s) with the Work to -which such Contribution(s) was submitted. If You institute patent litigation -against any entity (including a cross-claim or counterclaim in a lawsuit) -alleging that the Work or a Contribution incorporated within the Work constitutes -direct or contributory patent infringement, then any patent licenses granted to -You under this License for that Work shall terminate as of the date such -litigation is filed. - - 4. Redistribution. You may reproduce and distribute -copies of the Work or Derivative Works thereof in any medium, with or without -modifications, and in Source or Object form, provided that You meet the following -conditions: + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: (a) You must give any other recipients of the Work or -Derivative Works a copy of this License; and - - (b) You must cause any -modified files to carry prominent notices stating that You changed the files; -and - - (c) You must retain, in the Source form of any Derivative Works that -You distribute, all copyright, patent, trademark, and attribution notices from -the Source form of the Work, excluding those notices that do not pertain to any -part of the Derivative Works; and - - (d) If the Work includes a "NOTICE" text -file as part of its distribution, then any Derivative Works that You distribute -must include a readable copy of the attribution notices contained within such -NOTICE file, excluding those notices that do not pertain to any part of the -Derivative Works, in at least one of the following places: within a NOTICE text -file distributed as part of the Derivative Works; within the Source form or -documentation, if provided along with the Derivative Works; or, within a display -generated by the Derivative Works, if and wherever such third-party notices -normally appear. The contents of the NOTICE file are for informational purposes -only and do not modify the License. You may add Your own attribution notices -within Derivative Works that You distribute, alongside or as an addendum to the -NOTICE text from the Work, provided that such additional attribution notices -cannot be construed as modifying the License. - - You may add Your own -copyright statement to Your modifications and may provide additional or different -license terms and conditions for use, reproduction, or distribution of Your -modifications, or for any such Derivative Works as a whole, provided Your use, -reproduction, and distribution of the Work otherwise complies with the conditions -stated in this License. - - 5. Submission of Contributions. Unless You explicitly -state otherwise, any Contribution intentionally submitted for inclusion in the -Work by You to the Licensor shall be under the terms and conditions of this -License, without any additional terms or conditions. Notwithstanding the above, -nothing herein shall supersede or modify the terms of any separate license -agreement you may have executed with Licensor regarding such Contributions. - - -6. Trademarks. This License does not grant permission to use the trade names, -trademarks, service marks, or product names of the Licensor, except as required -for reasonable and customary use in describing the origin of the Work and -reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless -required by applicable law or agreed to in writing, Licensor provides the Work -(and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT -WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, -without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, -MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible -for determining the appropriateness of using or redistributing the Work and -assume any risks associated with Your exercise of permissions under this -License. + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, -whether in tort (including negligence), contract, or otherwise, unless required -by applicable law (such as deliberate and grossly negligent acts) or agreed to in -writing, shall any Contributor be liable to You for damages, including any -direct, indirect, special, incidental, or consequential damages of any character -arising as a result of this License or out of the use or inability to use the -Work (including but not limited to damages for loss of goodwill, work stoppage, -computer failure or malfunction, or any and all other commercial damages or -losses), even if such Contributor has been advised of the possibility of such -damages. + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing -the Work or Derivative Works thereof, You may choose to offer, and charge a fee -for, acceptance of support, warranty, indemnity, or other liability obligations -and/or rights consistent with this License. However, in accepting such -obligations, You may act only on Your own behalf and on Your sole responsibility, -not on behalf of any other Contributor, and only if You agree to indemnify, -defend, and hold each Contributor harmless for any liability incurred by, or -claims asserted against, such Contributor by reason of your accepting any such -warranty or additional liability. END OF TERMS AND CONDITIONS - -APPENDIX: How to -apply the Apache License to your work. - -To apply the Apache License to your work, -attach the following boilerplate notice, with the fields enclosed by brackets -"[]" replaced with your own identifying information. (Don't include the -brackets!) The text should be enclosed in the appropriate comment syntax for the -file format. We also recommend that a file or class name and description of -purpose be included on the same "printed page" as the copyright notice for easier -identification within third-party archives. - -Copyright [yyyy] Edgar -Hernandez - -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 - -http://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. \ No newline at end of file + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. diff --git a/Makefile b/Makefile index 83ab852..e1c94f3 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ setup-codebuild-agent: .PHONY: test-smoke test-smoke: setup-codebuild-agent - CODEBUILD_IMAGE_TAG=codebuild-agent test/integration/codebuild-local/test_one.sh test/integration/codebuild/buildspec.os.alpine.1.yml alpine 3.12 2.7 + CODEBUILD_IMAGE_TAG=codebuild-agent test/integration/codebuild-local/test_one.sh test/integration/codebuild/buildspec.os.alpine.1.yml alpine 3.16 3.1 .PHONY: test-unit test-unit: diff --git a/README.md b/README.md index dfb5348..3d299c5 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,6 @@ First step is to choose the base image to be used. The supported Linux OS distri - Amazon Linux 2 - Alpine - - CentOS - Debian - Ubuntu diff --git a/aws_lambda_ric.gemspec b/aws_lambda_ric.gemspec index ac356a1..6fd0fb1 100644 --- a/aws_lambda_ric.gemspec +++ b/aws_lambda_ric.gemspec @@ -1,5 +1,3 @@ -# Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - # frozen_string_literal: true lib = File.expand_path('lib', __dir__) @@ -8,7 +6,7 @@ require './lib/aws_lambda_ric/version' Gem::Specification.new do |spec| spec.name = 'aws_lambda_ric' - spec.version = AwsLambdaRuntimeInterfaceClient::VERSION + spec.version = AwsLambdaRIC::VERSION spec.authors = ['AWS Lambda'] spec.summary = 'AWS Lambda Runtime Interface Client for Ruby' @@ -16,7 +14,7 @@ Gem::Specification.new do |spec| spec.homepage = 'https://github.com/aws/aws-lambda-ruby-runtime-interface-client' spec.license = 'Apache-2.0' - spec.required_ruby_version = '>= 2.5' + spec.required_ruby_version = '>= 3.0' # Specify which files should be added to the gem when it is released. spec.files = %w[ @@ -33,8 +31,9 @@ Gem::Specification.new do |spec| spec.executables = 'aws_lambda_ric' spec.require_paths = ['lib'] - spec.add_development_dependency 'bundler', '>= 2.0' + spec.add_development_dependency 'bundler', '~> 2.0' spec.add_development_dependency 'minitest', '~> 5.0' spec.add_development_dependency 'rake', '~> 13.0' spec.add_development_dependency 'activesupport', '~> 6.0.1' + spec.add_development_dependency 'test-unit', '~> 3.5.5' end diff --git a/bin/aws_lambda_ric b/bin/aws_lambda_ric index e2e5e65..92f4981 100755 --- a/bin/aws_lambda_ric +++ b/bin/aws_lambda_ric @@ -1,10 +1,9 @@ #! /usr/bin/env ruby - -# Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - # frozen_string_literal: true require 'bundler/setup' -require_relative '../lib/aws_lambda_ric/bootstrap' +require_relative '../lib/aws_lambda_ric' + +lambda_ric = AwsLambdaRIC::Bootstrap.new -Bootstrap.start +lambda_ric.start diff --git a/buildspec.yml b/buildspec.yml new file mode 100644 index 0000000..21e18eb --- /dev/null +++ b/buildspec.yml @@ -0,0 +1,23 @@ + +version: 0.2 + +env: + shell: bash + +phases: + install: + commands: + - docker logout public.ecr.aws + - docker pull public.ecr.aws/amazonlinux/amazonlinux:2 + + pre_build: + commands: + - mkdir -p "${OUT_DIR:-build-artifacts}" + + build: + commands: + - make build-all OUT_DIR="${OUT_DIR:-build-artifacts}" + +artifacts: + files: + - "build-artifacts/**" \ No newline at end of file diff --git a/lib/aws_lambda_ric.rb b/lib/aws_lambda_ric.rb index 1e30c6c..418ad3d 100755 --- a/lib/aws_lambda_ric.rb +++ b/lib/aws_lambda_ric.rb @@ -1,5 +1,3 @@ -# Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - # frozen_string_literal: true require_relative 'aws_lambda_ric/lambda_errors' @@ -17,17 +15,24 @@ $stdout.sync = true # Ensures that logs are flushed promptly. -module AwsLambdaRuntimeInterfaceClient +module AwsLambdaRIC class Error < StandardError; end + def self.get_user_agent + ruby_version = RUBY_VERSION.to_s + version = AwsLambdaRIC::VERSION + + "aws-lambda-ruby/#{ruby_version}-#{version}" + end + # Loads the user code and runs it upon invocation class LambdaRunner ENV_VAR_RUNTIME_API = 'AWS_LAMBDA_RUNTIME_API' def initialize(runtime_server_addr, user_agent) - @lambda_server = LambdaServer.new(runtime_server_addr, user_agent) + @lambda_server = RapidClient.new(runtime_server_addr, user_agent) @runtime_loop_active = true # if false, we will exit the program @exit_code = 0 end @@ -45,7 +50,7 @@ def run(app_root, handler) @exit_code = -4 send_init_error_to_server(e) ensure - TelemetryLoggingHelper.close + TelemetryLogger.close end exit(@exit_code) @@ -121,7 +126,7 @@ def send_error_response(lambda_invocation, err, exit_code = nil, runtime_loop_ac end # Helper class to for mutating std logger with TelemetryLog - class TelemetryLoggingHelper + class TelemetryLogger ENV_VAR_TELEMETRY_LOG_FD = '_LAMBDA_TELEMETRY_LOG_FD' @@ -133,19 +138,27 @@ def close end end - def initialize(telemetry_log_fd, path_to_fd='/proc/self/fd/') - fd = "#{path_to_fd}#{telemetry_log_fd}" - AwsLambdaRuntimeInterfaceClient::TelemetryLoggingHelper.telemetry_log_fd_file = File.open(fd, 'wb') - AwsLambdaRuntimeInterfaceClient::TelemetryLoggingHelper.telemetry_log_fd_file.sync = true + def initialize(telemetry_log_fd) + fd = telemetry_log_fd.to_i + AwsLambdaRIC::TelemetryLogger.telemetry_log_fd_file = IO.new(fd, 'wb') + AwsLambdaRIC::TelemetryLogger.telemetry_log_fd_file.sync = true - AwsLambdaRuntimeInterfaceClient::TelemetryLoggingHelper.telemetry_log_sink = TelemetryLogSink.new(file: AwsLambdaRuntimeInterfaceClient::TelemetryLoggingHelper.telemetry_log_fd_file) + AwsLambdaRIC::TelemetryLogger.telemetry_log_sink = TelemetryLogSink.new(file: AwsLambdaRIC::TelemetryLogger.telemetry_log_fd_file) mutate_std_logger mutate_kernel_puts - rescue Errno::ENOENT + rescue Errno::ENOENT, Errno::EBADF # If File.open() fails, then the mutation won't happen and the default behaviour (print to stdout) will prevail end + def self.from_env() + if ENV.key?(ENV_VAR_TELEMETRY_LOG_FD) + fd = ENV.fetch(AwsLambdaRIC::TelemetryLogger::ENV_VAR_TELEMETRY_LOG_FD) + ENV.delete(AwsLambdaRIC::TelemetryLogger::ENV_VAR_TELEMETRY_LOG_FD) + AwsLambdaRIC::TelemetryLogger.new(fd) + end + end + private def mutate_std_logger @@ -158,7 +171,11 @@ def mutate_kernel_puts Kernel.module_eval do def puts(*arg) msg = arg.flatten.collect { |a| a.to_s.encode('UTF-8') }.join("\n") - AwsLambdaRuntimeInterfaceClient::TelemetryLoggingHelper.telemetry_log_sink.write(msg) + if msg[-1] != "\n" + msg += "\n" + end + AwsLambdaRIC::TelemetryLogger.telemetry_log_sink.write(msg) + return nil end end end @@ -176,4 +193,30 @@ def initialize(request_id, raw_request, request, trace_id) @trace_id = trace_id end end + + class Bootstrap + + def start + AwsLambdaRIC::TelemetryLogger::from_env() + bootstrap_handler + end + + def fetch_runtime_server + ENV.fetch(AwsLambdaRIC::LambdaRunner::ENV_VAR_RUNTIME_API) + rescue KeyError + puts 'Failed to get runtime server address from AWS_LAMBDA_RUNTIME_API env variable' + exit(-2) + end + + def bootstrap_handler + if ENV['_HANDLER'] == nil + puts 'No handler specified, exiting Runtime Interface Client.' + exit + end + app_root = Dir.pwd + handler = ENV['_HANDLER'] + lambda_runner = AwsLambdaRIC::LambdaRunner.new(fetch_runtime_server, AwsLambdaRIC::get_user_agent) + lambda_runner.run(app_root, handler) + end + end end diff --git a/lib/aws_lambda_ric/aws_lambda_marshaller.rb b/lib/aws_lambda_ric/aws_lambda_marshaller.rb index 877229b..858de1d 100644 --- a/lib/aws_lambda_ric/aws_lambda_marshaller.rb +++ b/lib/aws_lambda_ric/aws_lambda_marshaller.rb @@ -1,5 +1,3 @@ -# Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - # frozen_string_literal: true require 'stringio' diff --git a/lib/aws_lambda_ric/bootstrap.rb b/lib/aws_lambda_ric/bootstrap.rb deleted file mode 100644 index 70d0bcd..0000000 --- a/lib/aws_lambda_ric/bootstrap.rb +++ /dev/null @@ -1,45 +0,0 @@ -require_relative '../aws_lambda_ric' - -# Bootstrap runtime -module Bootstrap - - def self.start - bootstrap_telemetry_log_sink - bootstrap_handler - end - - def self.fetch_runtime_server - ENV.fetch(AwsLambdaRuntimeInterfaceClient::LambdaRunner::ENV_VAR_RUNTIME_API) - rescue KeyError - puts 'Failed to get runtime server address from AWS_LAMBDA_RUNTIME_API env variable' - exit(-2) - end - - def self.bootstrap_telemetry_log_sink(path_to_fd='/proc/self/fd/') - fd = ENV.fetch(AwsLambdaRuntimeInterfaceClient::TelemetryLoggingHelper::ENV_VAR_TELEMETRY_LOG_FD) - ENV.delete(AwsLambdaRuntimeInterfaceClient::TelemetryLoggingHelper::ENV_VAR_TELEMETRY_LOG_FD) - AwsLambdaRuntimeInterfaceClient::TelemetryLoggingHelper.new(fd, path_to_fd) - rescue KeyError - puts 'Skipped bootstraping TelemetryLog' - end - - def self.bootstrap_handler - if ARGV.empty? - puts 'No handler specified, exiting Runtime Interface Client.' - exit - end - app_root = Dir.pwd - handler = ARGV[0] - lambda_runner = AwsLambdaRuntimeInterfaceClient::LambdaRunner.new(fetch_runtime_server, get_user_agent) - puts "Executing '#{handler}' in function directory '#{app_root}'" - lambda_runner.run(app_root, handler) - end - - def self.get_user_agent - ruby_version = RUBY_VERSION.to_s - version = AwsLambdaRuntimeInterfaceClient::VERSION - - "aws-lambda-ruby/#{ruby_version}-#{version}" - end - -end \ No newline at end of file diff --git a/lib/aws_lambda_ric/lambda_context.rb b/lib/aws_lambda_ric/lambda_context.rb index 635d6d1..52758a8 100644 --- a/lib/aws_lambda_ric/lambda_context.rb +++ b/lib/aws_lambda_ric/lambda_context.rb @@ -1,5 +1,3 @@ -# Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - # frozen_string_literal: true class LambdaContext diff --git a/lib/aws_lambda_ric/lambda_errors.rb b/lib/aws_lambda_ric/lambda_errors.rb index b0b40d4..97e4328 100644 --- a/lib/aws_lambda_ric/lambda_errors.rb +++ b/lib/aws_lambda_ric/lambda_errors.rb @@ -1,6 +1,5 @@ -# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. - # frozen_string_literal: true + module LambdaErrors class LambdaErrors::InvocationError < StandardError; @@ -25,9 +24,9 @@ def runtime_error_type def to_lambda_response { - :errorMessage => @error_message, - :errorType => @error_type, - :stackTrace => @stack_trace + :errorMessage => @error_message, + :errorType => @error_type, + :stackTrace => @stack_trace } end @@ -39,7 +38,7 @@ def _sanitize_stacktrace(stacktrace) if stacktrace stacktrace.first(100).each do |line| if safe_trace - if line.to_s.match(%r{^lib}) + if line.to_s.match(%r{^/var/runtime/lib}) safe_trace = false else ret << line diff --git a/lib/aws_lambda_ric/lambda_handler.rb b/lib/aws_lambda_ric/lambda_handler.rb index c834f08..f316a27 100644 --- a/lib/aws_lambda_ric/lambda_handler.rb +++ b/lib/aws_lambda_ric/lambda_handler.rb @@ -1,4 +1,4 @@ -# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# frozen_string_literal: true require_relative 'aws_lambda_marshaller' @@ -19,8 +19,8 @@ def initialize(env_handler:) def call_handler(request:, context:) opts = { - event: request, - context: context + event: request, + context: context } if @handler_class response = Kernel.const_get(@handler_class).send(@handler_method_name, **opts) diff --git a/lib/aws_lambda_ric/lambda_log_formatter.rb b/lib/aws_lambda_ric/lambda_log_formatter.rb index dfedc4e..c9fa62c 100644 --- a/lib/aws_lambda_ric/lambda_log_formatter.rb +++ b/lib/aws_lambda_ric/lambda_log_formatter.rb @@ -1,11 +1,9 @@ -# Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - # frozen_string_literal: true require 'logger' -class LambdaLogFormatter < Logger::Formatter - FORMAT = '%s, [%s#%d] %5s %s -- %s: %s' +class LogFormatter < Logger::Formatter + FORMAT = '%s, [%s #%d] %5s %s -- %s: %s' def call(severity, time, progname, msg) (FORMAT % {sev: severity[0..0], datetime: format_datetime(time), process: $$, severity: severity, diff --git a/lib/aws_lambda_ric/lambda_logger.rb b/lib/aws_lambda_ric/lambda_logger.rb index 9afaea2..8d98e37 100644 --- a/lib/aws_lambda_ric/lambda_logger.rb +++ b/lib/aws_lambda_ric/lambda_logger.rb @@ -1,4 +1,4 @@ -# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# frozen_string_literal: true class LambdaLogger class << self diff --git a/lib/aws_lambda_ric/lambda_server.rb b/lib/aws_lambda_ric/lambda_server.rb index 5b3c14c..c5850ed 100644 --- a/lib/aws_lambda_ric/lambda_server.rb +++ b/lib/aws_lambda_ric/lambda_server.rb @@ -1,12 +1,10 @@ -# Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - # frozen_string_literal: true require 'net/http' require 'json' require_relative 'lambda_errors' -class LambdaServer +class RapidClient LAMBDA_DEFAULT_SERVER_ADDRESS = '127.0.0.1:9001' LAMBDA_RUNTIME_API_VERSION = '2018-06-01' @@ -32,7 +30,7 @@ def next_invocation [request_id, resp] else raise LambdaErrors::InvocationError.new( - "Received #{resp.code} when waiting for next invocation." + "Received #{resp.code} when waiting for next invocation." ) end rescue LambdaErrors::InvocationError => e @@ -50,9 +48,9 @@ def send_response(request_id:, response_object:, content_type: 'application/json response_object = response_object.read end Net::HTTP.post( - response_uri, - response_object, - { 'Content-Type' => content_type, 'User-Agent' => @user_agent } + response_uri, + response_object, + { 'Content-Type' => content_type, 'User-Agent' => @user_agent } ) rescue StandardError => e raise LambdaErrors::LambdaRuntimeError.new(e) @@ -65,9 +63,9 @@ def send_error_response(request_id:, error_object:, error:, xray_cause:) headers = { 'Lambda-Runtime-Function-Error-Type' => error.runtime_error_type, 'User-Agent' => @user_agent } headers['Lambda-Runtime-Function-XRay-Error-Cause'] = xray_cause if xray_cause.bytesize < MAX_HEADER_SIZE_BYTES Net::HTTP.post( - response_uri, - error_object.to_json, - headers + response_uri, + error_object.to_json, + headers ) rescue StandardError => e raise LambdaErrors::LambdaRuntimeError.new(e) @@ -78,9 +76,9 @@ def send_init_error(error_object:, error:) uri = URI("#{@server_address}/runtime/init/error") begin Net::HTTP.post( - uri, - error_object.to_json, - { 'Lambda-Runtime-Function-Error-Type' => error.runtime_error_type, 'User-Agent' => @user_agent } + uri, + error_object.to_json, + { 'Lambda-Runtime-Function-Error-Type' => error.runtime_error_type, 'User-Agent' => @user_agent } ) rescue StandardError => e raise LambdaErrors::LambdaRuntimeInitError.new(e) diff --git a/lib/aws_lambda_ric/logger_patch.rb b/lib/aws_lambda_ric/logger_patch.rb index 35c78f0..ced8ee1 100644 --- a/lib/aws_lambda_ric/logger_patch.rb +++ b/lib/aws_lambda_ric/logger_patch.rb @@ -7,15 +7,16 @@ def initialize(logdev, shift_age = 0, shift_size = 1048576, level: 'debug', # use unpatched constructor if logdev is a filename or an IO Object other than $stdout or $stderr if logdev && logdev != $stdout && logdev != $stderr super(logdev, shift_age, shift_size, level: level, progname: progname, - formatter: formatter, datetime_format: datetime_format, - binmode: binmode, shift_period_suffix: shift_period_suffix) + formatter: formatter, datetime_format: datetime_format, + binmode: binmode, shift_period_suffix: shift_period_suffix) else self.level = level self.progname = progname - @default_formatter = LambdaLogFormatter.new + @default_formatter = LogFormatter.new self.datetime_format = datetime_format self.formatter = formatter - @logdev = AwsLambdaRuntimeInterfaceClient::TelemetryLoggingHelper.telemetry_log_sink + @logdev = AwsLambdaRIC::TelemetryLogger.telemetry_log_sink + @level_override = {} end end end diff --git a/lib/aws_lambda_ric/telemetry_log_sink.rb b/lib/aws_lambda_ric/telemetry_log_sink.rb index cbd20b2..57e85ed 100644 --- a/lib/aws_lambda_ric/telemetry_log_sink.rb +++ b/lib/aws_lambda_ric/telemetry_log_sink.rb @@ -1,35 +1,38 @@ -# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. - # frozen_string_literal: true require 'logger' +require 'time' class TelemetryLogSink < Logger::LogDevice # TelemetryLogSink implements the logging contract between runtimes and the platform. It implements a simple # framing protocol so message boundaries can be determined. Each frame can be visualized as follows: # - # +----------------------+------------------------+-----------------------+ - # | Frame Type - 4 bytes | Length (len) - 4 bytes | Message - \'len\' bytes | - # +----------------------+------------------------+-----------------------+ + # +----------------------+------------------------+---------------------+-------------------------+ + # | Frame Type - 4 bytes | Length (len) - 4 bytes | Timestamp - 8 bytes | Message - \'len\' bytes | + # +----------------------+------------------------+---------------------+-------------------------+ # - # The first 4 bytes indicate the type of the frame - log frames have a type defined as the hex value 0xa55a0001. The - # second 4 bytes should indicate the message\'s length. The next \'len\' bytes contain the message. The byte order is - # big-endian. + # The first 4 bytes indicate the type of the frame - log frames have a type defined as the hex value 0xa55a0003. The + # second 4 bytes should indicate the message\'s length. Next, the timestamp in microsecond precision, and finally + # \'len\' bytes contain the message. The byte order is big-endian. def initialize(file:) @file = file end - FRAME_BYTES = [0xa55a0001].pack('L>') + FRAME_BYTES = [0xa55a0003].pack('L>') def write(msg) + @semaphore ||= Mutex.new if @file.nil? || @file.closed? $stdout.write(msg) else - @file.write(FRAME_BYTES) - @file.write([msg.bytesize].pack('L>')) - @file.write(msg) + @semaphore.synchronize do + @file.write(FRAME_BYTES) + @file.write([msg.bytesize].pack('L>')) + @file.write([(Time.new.to_f*1000000).to_i].pack('Q>')) + @file.write(msg) + end end end diff --git a/lib/aws_lambda_ric/version.rb b/lib/aws_lambda_ric/version.rb index fc0d761..f932e8c 100644 --- a/lib/aws_lambda_ric/version.rb +++ b/lib/aws_lambda_ric/version.rb @@ -1,7 +1,5 @@ -# Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - # frozen_string_literal: true -module AwsLambdaRuntimeInterfaceClient - VERSION = '2.0.0' +module AwsLambdaRIC + VERSION = '3.0.0' end diff --git a/lib/aws_lambda_ric/xray_cause.rb b/lib/aws_lambda_ric/xray_cause.rb index 8d14e95..26e4161 100644 --- a/lib/aws_lambda_ric/xray_cause.rb +++ b/lib/aws_lambda_ric/xray_cause.rb @@ -1,4 +1,4 @@ -# Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# frozen_string_literal: true require_relative 'lambda_errors' @@ -15,8 +15,8 @@ def initialize(lambda_error) def as_json @as_json ||= begin - JSON.dump(@cause) - end + JSON.dump(@cause) + end end private @@ -39,4 +39,4 @@ def normalize(err:) end [exception] end -end +end \ No newline at end of file diff --git a/test/integration/codebuild-local/Dockerfile.agent b/test/integration/codebuild-local/Dockerfile.agent index e9a9ffe..de9eada 100644 --- a/test/integration/codebuild-local/Dockerfile.agent +++ b/test/integration/codebuild-local/Dockerfile.agent @@ -2,4 +2,4 @@ FROM amazonlinux:2 RUN amazon-linux-extras enable docker && \ yum clean metadata && \ - yum install -y docker tar + yum install -y docker tar \ No newline at end of file diff --git a/test/integration/codebuild-local/codebuild_build.sh b/test/integration/codebuild-local/codebuild_build.sh index ffadfa3..049a304 100755 --- a/test/integration/codebuild-local/codebuild_build.sh +++ b/test/integration/codebuild-local/codebuild_build.sh @@ -191,4 +191,4 @@ echo "" echo $exposed_command echo "" -eval $docker_command +eval $docker_command \ No newline at end of file diff --git a/test/integration/codebuild-local/test_all.sh b/test/integration/codebuild-local/test_all.sh index 0c5168c..b184186 100755 --- a/test/integration/codebuild-local/test_all.sh +++ b/test/integration/codebuild-local/test_all.sh @@ -1,5 +1,4 @@ #!/bin/bash -# Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. set -euo pipefail @@ -66,4 +65,4 @@ main() { fi } -main "$@" +main "$@" \ No newline at end of file diff --git a/test/integration/codebuild-local/test_one.sh b/test/integration/codebuild-local/test_one.sh index 8a5029d..14acaaf 100755 --- a/test/integration/codebuild-local/test_one.sh +++ b/test/integration/codebuild-local/test_one.sh @@ -1,5 +1,4 @@ #!/bin/bash -# Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. set -euo pipefail @@ -56,4 +55,4 @@ main() { -b "$BUILDSPEC_YML" } -main "$@" +main "$@" \ No newline at end of file diff --git a/test/integration/codebuild/buildspec.os.alpine.1.yml b/test/integration/codebuild/buildspec.os.alpine.1.yml index 361def0..88e41e2 100644 --- a/test/integration/codebuild/buildspec.os.alpine.1.yml +++ b/test/integration/codebuild/buildspec.os.alpine.1.yml @@ -15,12 +15,9 @@ batch: env: variables: DISTRO_VERSION: - - "3.12" + - "3.16" RUNTIME_VERSION: - - "2.5" - - "2.6" - - "2.7" - - "3.0" + - "3.1" phases: pre_build: commands: @@ -30,14 +27,14 @@ phases: - mkdir "${SCRATCH_DIR}" - ARCHITECTURE=$(arch) - > - if [[ "$ARCHITECTURE" == "x86_64" ]]; then - RIE="aws-lambda-rie" - elif [[ "$ARCHITECTURE" == "aarch64" ]]; then - RIE="aws-lambda-rie-arm64" - else - echo "Architecture $ARCHITECTURE is not currently supported." - exit 1 - fi + if [[ "$ARCHITECTURE" == "x86_64" ]]; then + RIE="aws-lambda-rie" + elif [[ "$ARCHITECTURE" == "aarch64" ]]; then + RIE="aws-lambda-rie-arm64" + else + echo "Architecture $ARCHITECTURE is not currently supported." + exit 1 + fi - tar -xvf test/integration/resources/${RIE}.tar.gz --directory "${SCRATCH_DIR}" - > cp "test/integration/docker/Dockerfile.echo.${OS_DISTRIBUTION}" \ @@ -95,19 +92,19 @@ phases: fi finally: - | - echo "---------Container Logs: ${TEST_NAME}-app----------" - echo - docker logs "${TEST_NAME}-app" || true - echo - echo "---------------------------------------------------" - echo "--------Container Logs: ${TEST_NAME}-tester--------" - echo - docker logs "${TEST_NAME}-tester" || true - echo - echo "---------------------------------------------------" + echo "---------Container Logs: ${TEST_NAME}-app----------" + echo + docker logs "${TEST_NAME}-app" || true + echo + echo "---------------------------------------------------" + echo "--------Container Logs: ${TEST_NAME}-tester--------" + echo + docker logs "${TEST_NAME}-tester" || true + echo + echo "---------------------------------------------------" - echo "Cleaning up..." - docker stop "${TEST_NAME}-app" || true - docker rm --force "${TEST_NAME}-app" || true - docker stop "${TEST_NAME}-tester" || true - docker rm --force "${TEST_NAME}-tester" || true - - docker network rm "${TEST_NAME}-network" || true + - docker network rm "${TEST_NAME}-network" || true \ No newline at end of file diff --git a/test/integration/codebuild/buildspec.os.alpine.2.yml b/test/integration/codebuild/buildspec.os.alpine.2.yml index 9c9a9d3..88e41e2 100644 --- a/test/integration/codebuild/buildspec.os.alpine.2.yml +++ b/test/integration/codebuild/buildspec.os.alpine.2.yml @@ -15,11 +15,9 @@ batch: env: variables: DISTRO_VERSION: - - "3.11" + - "3.16" RUNTIME_VERSION: - - "2.5" - - "2.6" - - "2.7" + - "3.1" phases: pre_build: commands: @@ -29,14 +27,14 @@ phases: - mkdir "${SCRATCH_DIR}" - ARCHITECTURE=$(arch) - > - if [[ "$ARCHITECTURE" == "x86_64" ]]; then - RIE="aws-lambda-rie" - elif [[ "$ARCHITECTURE" == "aarch64" ]]; then - RIE="aws-lambda-rie-arm64" - else - echo "Architecture $ARCHITECTURE is not currently supported." - exit 1 - fi + if [[ "$ARCHITECTURE" == "x86_64" ]]; then + RIE="aws-lambda-rie" + elif [[ "$ARCHITECTURE" == "aarch64" ]]; then + RIE="aws-lambda-rie-arm64" + else + echo "Architecture $ARCHITECTURE is not currently supported." + exit 1 + fi - tar -xvf test/integration/resources/${RIE}.tar.gz --directory "${SCRATCH_DIR}" - > cp "test/integration/docker/Dockerfile.echo.${OS_DISTRIBUTION}" \ @@ -94,19 +92,19 @@ phases: fi finally: - | - echo "---------Container Logs: ${TEST_NAME}-app----------" - echo - docker logs "${TEST_NAME}-app" || true - echo - echo "---------------------------------------------------" - echo "--------Container Logs: ${TEST_NAME}-tester--------" - echo - docker logs "${TEST_NAME}-tester" || true - echo - echo "---------------------------------------------------" + echo "---------Container Logs: ${TEST_NAME}-app----------" + echo + docker logs "${TEST_NAME}-app" || true + echo + echo "---------------------------------------------------" + echo "--------Container Logs: ${TEST_NAME}-tester--------" + echo + docker logs "${TEST_NAME}-tester" || true + echo + echo "---------------------------------------------------" - echo "Cleaning up..." - docker stop "${TEST_NAME}-app" || true - docker rm --force "${TEST_NAME}-app" || true - docker stop "${TEST_NAME}-tester" || true - docker rm --force "${TEST_NAME}-tester" || true - - docker network rm "${TEST_NAME}-network" || true + - docker network rm "${TEST_NAME}-network" || true \ No newline at end of file diff --git a/test/integration/codebuild/buildspec.os.amazonlinux.yml b/test/integration/codebuild/buildspec.os.amazonlinux.yml index 08176ce..9d2433c 100644 --- a/test/integration/codebuild/buildspec.os.amazonlinux.yml +++ b/test/integration/codebuild/buildspec.os.amazonlinux.yml @@ -17,10 +17,7 @@ batch: DISTRO_VERSION: - "2" RUNTIME_VERSION: - - "2.5" - - "2.6" - - "2.7" - - "3.0" + - "3.1" phases: pre_build: commands: @@ -30,14 +27,14 @@ phases: - mkdir "${SCRATCH_DIR}" - ARCHITECTURE=$(arch) - > - if [[ "$ARCHITECTURE" == "x86_64" ]]; then - RIE="aws-lambda-rie" - elif [[ "$ARCHITECTURE" == "aarch64" ]]; then - RIE="aws-lambda-rie-arm64" - else - echo "Architecture $ARCHITECTURE is not currently supported." - exit 1 - fi + if [[ "$ARCHITECTURE" == "x86_64" ]]; then + RIE="aws-lambda-rie" + elif [[ "$ARCHITECTURE" == "aarch64" ]]; then + RIE="aws-lambda-rie-arm64" + else + echo "Architecture $ARCHITECTURE is not currently supported." + exit 1 + fi - tar -xvf test/integration/resources/${RIE}.tar.gz --directory "${SCRATCH_DIR}" - > cp "test/integration/docker/Dockerfile.echo.${OS_DISTRIBUTION}" \ @@ -92,19 +89,19 @@ phases: fi finally: - | - echo "---------Container Logs: ${TEST_NAME}-app----------" - echo - docker logs "${TEST_NAME}-app" || true - echo - echo "---------------------------------------------------" - echo "--------Container Logs: ${TEST_NAME}-tester--------" - echo - docker logs "${TEST_NAME}-tester" || true - echo - echo "---------------------------------------------------" + echo "---------Container Logs: ${TEST_NAME}-app----------" + echo + docker logs "${TEST_NAME}-app" || true + echo + echo "---------------------------------------------------" + echo "--------Container Logs: ${TEST_NAME}-tester--------" + echo + docker logs "${TEST_NAME}-tester" || true + echo + echo "---------------------------------------------------" - echo "Cleaning up..." - docker stop "${TEST_NAME}-app" || true - docker rm --force "${TEST_NAME}-app" || true - docker stop "${TEST_NAME}-tester" || true - docker rm --force "${TEST_NAME}-tester" || true - - docker network rm "${TEST_NAME}-network" || true + - docker network rm "${TEST_NAME}-network" || true \ No newline at end of file diff --git a/test/integration/codebuild/buildspec.os.centos.yml b/test/integration/codebuild/buildspec.os.centos.yml deleted file mode 100644 index 74338a6..0000000 --- a/test/integration/codebuild/buildspec.os.centos.yml +++ /dev/null @@ -1,110 +0,0 @@ -version: 0.2 - -env: - variables: - OS_DISTRIBUTION: centos - EXECUTABLE: "/usr/local/bin/aws_lambda_ric" - TEST_NAME: "aws-lambda-ruby-ric-centos-test" -batch: - build-matrix: - static: - ignore-failure: false - env: - privileged-mode: true - dynamic: - env: - variables: - DISTRO_VERSION: - - "7" - RUNTIME_VERSION: - - "2.7" - - "2.6" - - "2.5" - - "3.0" -phases: - pre_build: - commands: - - export IMAGE_TAG="ruby-${OS_DISTRIBUTION}-${DISTRO_VERSION}:${RUNTIME_VERSION}" - - echo "Extracting and including the Runtime Interface Emulator" - - SCRATCH_DIR=".scratch" - - mkdir "${SCRATCH_DIR}" - - ARCHITECTURE=$(arch) - - > - if [[ "$ARCHITECTURE" == "x86_64" ]]; then - RIE="aws-lambda-rie" - elif [[ "$ARCHITECTURE" == "aarch64" ]]; then - RIE="aws-lambda-rie-arm64" - else - echo "Architecture $ARCHITECTURE is not currently supported." - exit 1 - fi - - tar -xvf test/integration/resources/${RIE}.tar.gz --directory "${SCRATCH_DIR}" - - > - cp "test/integration/docker/Dockerfile.echo.${OS_DISTRIBUTION}" \ - "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" - - > - echo "COPY ${SCRATCH_DIR}/${RIE} /usr/bin/${RIE}" >> \ - "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" - - > - if [[ -z "${DOCKERHUB_USERNAME}" && -z "${DOCKERHUB_PASSWORD}" ]]; - then - echo "DockerHub credentials not set as CodeBuild environment variables. Continuing without docker login." - else - echo "Performing DockerHub login . . ." - docker login -u $DOCKERHUB_USERNAME -p $DOCKERHUB_PASSWORD - fi - - echo "Building image ${IMAGE_TAG}" - - > - docker build . \ - -f "${SCRATCH_DIR}/Dockerfile.echo.${OS_DISTRIBUTION}.tmp" \ - -t "${IMAGE_TAG}" \ - --build-arg RUNTIME_VERSION="${RUNTIME_VERSION}" \ - --build-arg DISTRO_VERSION="${DISTRO_VERSION}" - build: - commands: - - set -x - - echo "Running Image ${IMAGE_TAG}" - - docker network create "${TEST_NAME}-network" - - > - docker run \ - --detach \ - --name "${TEST_NAME}-app" \ - --network "${TEST_NAME}-network" \ - --entrypoint="" \ - "${IMAGE_TAG}" \ - sh -c "/usr/bin/${RIE} "${EXECUTABLE}" "app.App::Handler.process"" - - sleep 2 - - > - docker run \ - --name "${TEST_NAME}-tester" \ - --env "TARGET=${TEST_NAME}-app" \ - --network "${TEST_NAME}-network" \ - --entrypoint="" \ - "${IMAGE_TAG}" \ - sh -c 'curl -X POST "http://${TARGET}:8080/2015-03-31/functions/function/invocations" -d "{}" --max-time 10' - - actual="$(docker logs --tail 1 "${TEST_NAME}-tester" | xargs)" - - expected='success' - - | - echo "Response: ${actual}" - if [[ "$actual" != "$expected" ]]; then - echo "fail! runtime: $RUNTIME - expected output $expected - got $actual" - exit -1 - fi - finally: - - | - echo "---------Container Logs: ${TEST_NAME}-app----------" - echo - docker logs "${TEST_NAME}-app" || true - echo - echo "---------------------------------------------------" - echo "--------Container Logs: ${TEST_NAME}-tester--------" - echo - docker logs "${TEST_NAME}-tester" || true - echo - echo "---------------------------------------------------" - - echo "Cleaning up..." - - docker stop "${TEST_NAME}-app" || true - - docker rm --force "${TEST_NAME}-app" || true - - docker stop "${TEST_NAME}-tester" || true - - docker rm --force "${TEST_NAME}-tester" || true - - docker network rm "${TEST_NAME}-network" || true diff --git a/test/integration/codebuild/buildspec.os.debian.yml b/test/integration/codebuild/buildspec.os.debian.yml index 8140558..75f6566 100644 --- a/test/integration/codebuild/buildspec.os.debian.yml +++ b/test/integration/codebuild/buildspec.os.debian.yml @@ -16,11 +16,9 @@ batch: variables: DISTRO_VERSION: - "buster" + - "bullseye" RUNTIME_VERSION: - - "2.5" - - "2.6" - - "2.7" - - "3.0" + - "3.1" phases: pre_build: commands: @@ -30,14 +28,14 @@ phases: - mkdir "${SCRATCH_DIR}" - ARCHITECTURE=$(arch) - > - if [[ "$ARCHITECTURE" == "x86_64" ]]; then - RIE="aws-lambda-rie" - elif [[ "$ARCHITECTURE" == "aarch64" ]]; then - RIE="aws-lambda-rie-arm64" - else - echo "Architecture $ARCHITECTURE is not currently supported." - exit 1 - fi + if [[ "$ARCHITECTURE" == "x86_64" ]]; then + RIE="aws-lambda-rie" + elif [[ "$ARCHITECTURE" == "aarch64" ]]; then + RIE="aws-lambda-rie-arm64" + else + echo "Architecture $ARCHITECTURE is not currently supported." + exit 1 + fi - tar -xvf test/integration/resources/${RIE}.tar.gz --directory "${SCRATCH_DIR}" - > cp "test/integration/docker/Dockerfile.echo.${OS_DISTRIBUTION}" \ @@ -92,19 +90,19 @@ phases: fi finally: - | - echo "---------Container Logs: ${TEST_NAME}-app----------" - echo - docker logs "${TEST_NAME}-app" || true - echo - echo "---------------------------------------------------" - echo "--------Container Logs: ${TEST_NAME}-tester--------" - echo - docker logs "${TEST_NAME}-tester" || true - echo - echo "---------------------------------------------------" + echo "---------Container Logs: ${TEST_NAME}-app----------" + echo + docker logs "${TEST_NAME}-app" || true + echo + echo "---------------------------------------------------" + echo "--------Container Logs: ${TEST_NAME}-tester--------" + echo + docker logs "${TEST_NAME}-tester" || true + echo + echo "---------------------------------------------------" - echo "Cleaning up..." - docker stop "${TEST_NAME}-app" || true - docker rm --force "${TEST_NAME}-app" || true - docker stop "${TEST_NAME}-tester" || true - docker rm --force "${TEST_NAME}-tester" || true - - docker network rm "${TEST_NAME}-network" || true + - docker network rm "${TEST_NAME}-network" || true \ No newline at end of file diff --git a/test/integration/codebuild/buildspec.os.ubuntu.yml b/test/integration/codebuild/buildspec.os.ubuntu.yml index 2335ec4..cc132f4 100644 --- a/test/integration/codebuild/buildspec.os.ubuntu.yml +++ b/test/integration/codebuild/buildspec.os.ubuntu.yml @@ -15,13 +15,9 @@ batch: env: variables: DISTRO_VERSION: - - "20.04" - - "18.04" + - "22.04" RUNTIME_VERSION: - - "2.7" - - "2.6" - - "2.5" - - "3.0" + - "3.1" phases: pre_build: commands: @@ -31,14 +27,14 @@ phases: - mkdir "${SCRATCH_DIR}" - ARCHITECTURE=$(arch) - > - if [[ "$ARCHITECTURE" == "x86_64" ]]; then - RIE="aws-lambda-rie" - elif [[ "$ARCHITECTURE" == "aarch64" ]]; then - RIE="aws-lambda-rie-arm64" - else - echo "Architecture $ARCHITECTURE is not currently supported." - exit 1 - fi + if [[ "$ARCHITECTURE" == "x86_64" ]]; then + RIE="aws-lambda-rie" + elif [[ "$ARCHITECTURE" == "aarch64" ]]; then + RIE="aws-lambda-rie-arm64" + else + echo "Architecture $ARCHITECTURE is not currently supported." + exit 1 + fi - tar -xvf test/integration/resources/${RIE}.tar.gz --directory "${SCRATCH_DIR}" - > cp "test/integration/docker/Dockerfile.echo.${OS_DISTRIBUTION}" \ @@ -96,19 +92,19 @@ phases: fi finally: - | - echo "---------Container Logs: ${TEST_NAME}-app----------" - echo - docker logs "${TEST_NAME}-app" || true - echo - echo "---------------------------------------------------" - echo "--------Container Logs: ${TEST_NAME}-tester--------" - echo - docker logs "${TEST_NAME}-tester" || true - echo - echo "---------------------------------------------------" + echo "---------Container Logs: ${TEST_NAME}-app----------" + echo + docker logs "${TEST_NAME}-app" || true + echo + echo "---------------------------------------------------" + echo "--------Container Logs: ${TEST_NAME}-tester--------" + echo + docker logs "${TEST_NAME}-tester" || true + echo + echo "---------------------------------------------------" - echo "Cleaning up..." - docker stop "${TEST_NAME}-app" || true - docker rm --force "${TEST_NAME}-app" || true - docker stop "${TEST_NAME}-tester" || true - docker rm --force "${TEST_NAME}-tester" || true - - docker network rm "${TEST_NAME}-network" || true + - docker network rm "${TEST_NAME}-network" || true \ No newline at end of file diff --git a/test/integration/docker-compose.template.yml b/test/integration/docker-compose.template.yml index 38db376..6247ff2 100644 --- a/test/integration/docker-compose.template.yml +++ b/test/integration/docker-compose.template.yml @@ -20,11 +20,11 @@ services: context: . dockerfile: ../docker-helpers/Dockerfile.aws-cli entrypoint: [ - aws, lambda, invoke, - --endpoint, http://runtime:9001, - --no-sign-request, - --region, us-west-2, - --function-name, ignored, - --payload, '{ "name": "Lambda" }', - /dev/stdout - ] + aws, lambda, invoke, + --endpoint, http://runtime:9001, + --no-sign-request, + --region, us-west-2, + --function-name, ignored, + --payload, '{ "name": "Lambda" }', + /dev/stdout + ] \ No newline at end of file diff --git a/test/integration/docker/Dockerfile.echo.alpine b/test/integration/docker/Dockerfile.echo.alpine index 2ec437f..cb4ebab 100644 --- a/test/integration/docker/Dockerfile.echo.alpine +++ b/test/integration/docker/Dockerfile.echo.alpine @@ -36,4 +36,3 @@ WORKDIR ${FUNCTION_DIR} ENTRYPOINT ["aws_lambda_ric"] CMD ["app.App::Handler.process"] - diff --git a/test/integration/docker/Dockerfile.echo.amazonlinux b/test/integration/docker/Dockerfile.echo.amazonlinux index 36b2614..8ee0c4a 100644 --- a/test/integration/docker/Dockerfile.echo.amazonlinux +++ b/test/integration/docker/Dockerfile.echo.amazonlinux @@ -61,4 +61,3 @@ WORKDIR ${FUNCTION_DIR} ENTRYPOINT ["aws_lambda_ric"] CMD ["app.App::Handler.process"] - diff --git a/test/integration/docker/Dockerfile.echo.centos b/test/integration/docker/Dockerfile.echo.centos deleted file mode 100644 index afc5194..0000000 --- a/test/integration/docker/Dockerfile.echo.centos +++ /dev/null @@ -1,64 +0,0 @@ -# Define global args -ARG DISTRO_VERSION - -# Grab a fresh copy of the image and install ruby and build the runtime interface client gem -FROM centos:${DISTRO_VERSION} AS build-image - -ARG RUNTIME_VERSION - -RUN yum update -y && \ - yum install -y git-core zlib zlib-devel gcc-c++ patch readline readline-devel libffi-devel openssl-devel make bzip2 autoconf automake libtool bison curl sqlite-devel - -RUN rm -rf /root/.rbenv/ -RUN git clone https://github.com/rbenv/rbenv.git /root/.rbenv -ENV PATH="/root/.rbenv/bin:$PATH" -RUN echo 'eval "$(rbenv init -)"' >> /root/.bashrc -RUN git clone https://github.com/rbenv/ruby-build.git /root/.rbenv/plugins/ruby-build -RUN source /root/.bashrc -RUN RUNTIME_VERSIONS=($(rbenv install -L | grep -oE $(echo "^${RUNTIME_VERSION}\.[0-9]+"))) && \ - RUNTIME_LATEST_VERSION=${RUNTIME_VERSIONS[-1]} && \ - rbenv install -v ${RUNTIME_LATEST_VERSION} && \ - rbenv global ${RUNTIME_LATEST_VERSION} && \ - cp /root/.rbenv/versions/${RUNTIME_LATEST_VERSION}/bin/gem /usr/local/bin/gem && \ - cp /root/.rbenv/versions/${RUNTIME_LATEST_VERSION}/bin/rake /usr/local/bin/rake && \ - gem install bundler - -ARG RIC_BUILD_DIR="/build" -# Create directory to build the Runtime Interface Client gem -RUN mkdir -p ${RIC_BUILD_DIR} - -WORKDIR ${RIC_BUILD_DIR} -COPY . . -RUN rake build - - -# Grab a fresh copy of the Ruby image -FROM centos:${DISTRO_VERSION} - -ARG RUNTIME_VERSION - -# Copy ruby from the build-image -COPY --from=build-image /root/.rbenv /root/.rbenv - -ENV PATH="/root/.rbenv/bin:$PATH" - -# Copy the Runtime Interface Client gem and install it -ARG RIC_BUILD_DIR="/build" -COPY --from=build-image ${RIC_BUILD_DIR}/pkg/aws_lambda_ric*.gem aws_lambda_ric.gem -RUN RUNTIME_VERSIONS=($(rbenv install -L | grep -oE $(echo "^${RUNTIME_VERSION}\.[0-9]+"))) && \ - RUNTIME_LATEST_VERSION=${RUNTIME_VERSIONS[-1]} && \ - cp /root/.rbenv/versions/${RUNTIME_LATEST_VERSION}/bin/gem /usr/local/bin/gem && \ - gem install aws_lambda_ric.gem && \ - cp /root/.rbenv/versions/${RUNTIME_LATEST_VERSION}/bin/aws_lambda_ric /usr/local/bin/aws_lambda_ric - -ARG FUNCTION_DIR="/function" - -RUN mkdir -p ${FUNCTION_DIR} -# Copy function code -COPY test/integration/test-handlers/echo/* ${FUNCTION_DIR} -# Set working directory to function root directory -WORKDIR ${FUNCTION_DIR} - -ENTRYPOINT ["aws_lambda_ric"] -CMD ["app.App::Handler.process"] - diff --git a/test/integration/docker/Dockerfile.echo.debian b/test/integration/docker/Dockerfile.echo.debian index 40bfed4..ffdadba 100644 --- a/test/integration/docker/Dockerfile.echo.debian +++ b/test/integration/docker/Dockerfile.echo.debian @@ -37,4 +37,3 @@ WORKDIR ${FUNCTION_DIR} ENTRYPOINT ["aws_lambda_ric"] CMD ["app.App::Handler.process"] - diff --git a/test/integration/docker/Dockerfile.echo.ubuntu b/test/integration/docker/Dockerfile.echo.ubuntu index 92cb5b6..6bce61b 100644 --- a/test/integration/docker/Dockerfile.echo.ubuntu +++ b/test/integration/docker/Dockerfile.echo.ubuntu @@ -71,4 +71,3 @@ WORKDIR ${FUNCTION_DIR} ENTRYPOINT ["aws_lambda_ric"] CMD ["app.App::Handler.process"] - diff --git a/test/run_tests.rb b/test/run_tests.rb index 0a1fb3d..3bf6f35 100644 --- a/test/run_tests.rb +++ b/test/run_tests.rb @@ -1,4 +1,4 @@ -# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# frozen_string_literal: true # run tests in specified directory and its sub-directories if ARGV.length != 1 diff --git a/test/unit/harness-suite.json b/test/unit/harness-suite.json deleted file mode 100644 index 7c1e4b7..0000000 --- a/test/unit/harness-suite.json +++ /dev/null @@ -1,434 +0,0 @@ -{ - "tests": [ - { - "name": "test_echo", - "handler": "core.ping", - "request": { - "msg": "message" - }, - "assertion": - { - "response": { "msg": "pong[message]" } - } - }, - { - "name": "test_string_payload", - "handler": "core.str_ping", - "request": "message", - "assertion": - { - "response": { "msg": "pong[message]" } - } - }, - { - "name": "test_module_echo", - "handler": "core.HandlerClass.ping", - "request": { - "msg": "MyMessage" - }, - "assertion": - { - "response": "Module Message: 'MyMessage'" - } - }, - { - "name": "test_deep_module_echo", - "handler": "core.DeepModule::Handler.ping", - "request": { - "msg": "MyMessage" - }, - "assertion": - { - "response": "Deep Module Message: 'MyMessage'" - } - }, - { - "name": "test_error", - "handler": "core.broken", - "request": { - "msg": "message" - }, - "assertion": - { - "errorType": "Function" - } - }, - { - "name": "test_string", - "handler": "core.string", - "request": { - "msg": "MyMessage" - }, - "assertion": - { - "response": "Message: 'MyMessage'" - } - }, - { - "name": "test_unicode", - "handler": "unicode.hello", - "request": "", - "assertion": - { - "response": { "hello": "今日はラムダ!" } - } - }, - { - "name": "test_underscore_handler", - "handler": "underscore_file.underscore_method", - "request": "", - "assertion": - { - "response": "Success!" - } - }, - { - "name": "test_dependencies", - "handler": "dependencies.get_tomorrow", - "request": { - "input_time": "2018-10-08 11:34:20 +0100" - }, - "assertion": - { - "response": {"tomorrow": "2018-10-09T11:34:20.000+01:00" } - } - }, - { - "name": "test_dynamic_libs_are_available", - "handler": "dependencies.find_dynamic_libs", - "request": "", - "assertion": - { - "response": "ok" - } - }, - { - "name": "test_echo_env_variable", - "handler": "environment.echo", - "environmentVariables": { - "TEST_ENV_VARIABLE": "Golden Tate made that catch." - }, - "request": { - "varname": "TEST_ENV_VARIABLE" - }, - "assertion": - { - "response": "Golden Tate made that catch." - } - }, - { - "name": "test_env_runtime_api_is_not_deleted", - "handler": "environment.env_var_is_present", - "environmentVariables": { - "AWS_LAMBDA_RUNTIME_API": "127.0.0.1:9001" - }, - "request": { - "varname": "AWS_LAMBDA_RUNTIME_API" - }, - "assertion": - { - "response": "true" - } - }, - { - "name": "test_env_telmetry_log_fd_deleted", - "handler": "environment.env_var_is_present", - "environmentVariables": { - "_LAMBDA_TELEMETRY_LOG_FD": "test/unit/resources/fd/test_fd" - }, - "request": { - "varname": "_LAMBDA_TELEMETRY_LOG_FD" - }, - "assertion": - { - "response": "false" - } - }, - { - "name": "test_put_uses_telemetry_log_fd", - "handler": "log.put_messages_and_read_fd", - "environmentVariables": { - "_LAMBDA_TELEMETRY_LOG_FD": "test/unit/resources/fd/test_fd" - }, - "request": { - "messages": ["Single frame\n even if there are multiple lines\nthird line"], - "fd_path": "test/unit/resources/fd/test_fd" - }, - "assertion": - { - "response": "277413888157Single frame\n even if there are multiple lines\nthird line" - } - }, - { - "name": "test_put_frozen_string", - "handler": "log.put_frozen_string", - "environmentVariables": { - "_LAMBDA_TELEMETRY_LOG_FD": "test/unit/resources/fd/test_fd" - }, - "request": { - "messages": ["ELSA"], - "fd_path": "test/unit/resources/fd/test_fd" - }, - "assertion": - { - "response": "ok" - } - }, - { - "name": "test_put_uses_telemetry_log_fd_multiple_frames", - "handler": "log.put_messages_and_read_fd", - "environmentVariables": { - "_LAMBDA_TELEMETRY_LOG_FD": "test/unit/resources/fd/test_fd" - }, - "request": { - "messages": ["First message first line\n second line", "Second message first line\n second line"], - "fd_path": "test/unit/resources/fd/test_fd" - }, - "assertion": - { - "response": "277413888137First message first line\n second line277413888138Second message first line\n second line" - } - }, - { - "name": "test_logger_uses_telemetry_log_fd_when_logdev_is_stdout", - "handler": "log.log_to_stdout_and_read_fd", - "environmentVariables": { - "_LAMBDA_TELEMETRY_LOG_FD": "test/unit/resources/fd/test_fd" - }, - "request": { - "messages": ["Single frame\n even if there are multiple lines\nthird line"], - "fd_path": "test/unit/resources/fd/test_fd" - }, - "assertion": - { - "transform": "\"277413888114[0-9]I, \\[[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])T(2[0-3]|[01][0-9]):[0-5][0-9]:[0-9]{2}.[0-9]{6} #[0-9]*\\] INFO ({){0,1}[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}(}){0,1} -- : Single frame\\\\n even if there are multiple lines\\\\nthird line\"", - "response": true - } - }, - { - "name": "test_logger_logs_to_a_file_when_logdev_is_a_file", - "handler": "log.log_to_file_and_read_back", - "environmentVariables": { - "_LAMBDA_TELEMETRY_LOG_FD": "test/unit/resources/fd/test_fd" - }, - "request": { - "messages": ["Single frame written to a file\n even if there are multiple lines\nthird line"], - "fd_path": "test/unit/resources/fd/test_fd", - "file_path": "test/unit/resources/fd/test_file.txt" - }, - "assertion": - { - "transform": "I, \\[[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])T(2[0-3]|[01][0-9]):[0-5][0-9]:[0-9]{2}.[0-9]{6} #[0-9]*\\] INFO -- : Single frame written to a file\\\\n even if there are multiple lines\\\\nthird line", - "response": true - } - }, - { - "name": "test_logger_uses_telemetry_log_fd_when_logdev_is_stderr", - "handler": "log.log_to_stderr_and_read_fd", - "environmentVariables": { - "_LAMBDA_TELEMETRY_LOG_FD": "test/unit/resources/fd/test_fd" - }, - "request": { - "messages": ["Single frame\n even if there are multiple lines\nthird line"], - "fd_path": "test/unit/resources/fd/test_fd" - }, - "assertion": - { - "transform": "\"277413888114[0-9]E, \\[[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])T(2[0-3]|[01][0-9]):[0-5][0-9]:[0-9]{2}.[0-9]{6} #[0-9]*\\] ERROR ({){0,1}[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}(}){0,1} -- : Single frame\\\\n even if there are multiple lines\\\\nthird line\"", - "response": true - } - }, - { - "name": "test_arguments_are_flattened_and_separated_by_newline_when_logging", - "handler": "log.put_messages_and_read_fd", - "environmentVariables": { - "_LAMBDA_TELEMETRY_LOG_FD": "test/unit/resources/fd/test_fd" - }, - "request": { - "messages": [["first_level","an_other_first_level", ["second_level"]]], - "fd_path": "test/unit/resources/fd/test_fd" - }, - "assertion": - { - "response": "277413888145first_level\nan_other_first_level\nsecond_level" - } - }, - { - "name": "test_fallback_to_stdout_silently_when_can_not_open_telemetry_log_fd", - "handler": "log.put_message", - "environmentVariables": { - "_LAMBDA_TELEMETRY_LOG_FD": "/unreachable/test_fd" - }, - "request": { - "messages": ["It should fall back silently"] - }, - "assertion": - { - "response": "ok" - } - }, - { - "name": "test_invalid_handler_definition_short", - "handler": "invalid", - "request": {}, - "assertion": - { - "errorType": "Init" - } - }, - { - "name": "test_invalid_handler_definition_long", - "handler": "invalid.because.too.long", - "request": {}, - "assertion": - { - "errorType": "Init" - } - }, - { - "name": "test_invalid_handler_file", - "handler": "doesnt_exist.doesnt_matter", - "request": {}, - "assertion": - { - "errorType": "Init" - } - }, - { - "name": "test_invalid_handler_method", - "handler": "pandoras_box.sir_not_appearing_in_this_file", - "request": {}, - "assertion": - { - "errorType": "Function" - } - }, - { - "name": "test_invalid_handler_class", - "handler": "pandoras_box.Does::Not::Exist.handler", - "request": {}, - "assertion": - { - "errorType": "Function" - } - }, - { - "name": "test_invalid_handler_method_in_class", - "handler": "pandoras_box.PandoraTest.handler", - "request": {}, - "assertion": - { - "errorType": "Function" - } - }, - { - "name": "test_invalid_dependency", - "handler": "bad_dependency.handler", - "request": {}, - "assertion": - { - "errorType": "Init" - } - }, - { - "name": "test_stack_overflow", - "handler": "pandoras_box.stack_overflow", - "request": {}, - "assertion": - { - "errorType": "Function" - } - }, - { - "name": "test_process_exit", - "handler": "pandoras_box.hard_exit", - "request": {}, - "assertion": - { - "errorType": "Function" - } - }, - { - "name": "test_curl", - "handler": "core.curl", - "request": - { - "url": "http://example.org" - }, - "assertion": - { - "response": { "success": true } - } - }, - { - "name": "test_ctx_cognito_pool_id", - "handler": "ctx.get_cognito_pool_id", - "cognitoIdentity": { - "cognitoIdentityId": "4ab95ea510c14353a7f6da04489c43b8", - "cognitoIdentityPoolId": "35ab4794a79a4f23947d3e851d3d6578" - }, - "request": {}, - "assertion": - { - "response": { "cognito_pool_id": "35ab4794a79a4f23947d3e851d3d6578"} - } - }, - { - "name": "test_ctx_cognito_identity_id", - "handler": "ctx.get_cognito_identity_id", - "cognitoIdentity": { - "cognitoIdentityId": "4ab95ea510c14353a7f6da04489c43b8", - "cognitoIdentityPoolId": "35ab4794a79a4f23947d3e851d3d6578" - }, - "request": {}, - "assertion": - { - "response": { "cognito_identity_id": "4ab95ea510c14353a7f6da04489c43b8"} - } - }, - { - "name": "echo_client_context", - "handler": "ctx.echo_context", - "clientContext": - { - "custom": { - "a": "1", - "b": "1" - }, - "env": { - "make": "samsung", - "platform": "android" - }, - "client": { - "installation_id": "id1234", - "app_title": "title", - "app_version_name": "alpha", - "app_version_code": "9.9", - "app_package_name": "pname" - } - }, - "request": "yo", - "assertion": - { - "response": - { - "custom": { - "a": "1", - "b": "1" - }, - "env": { - "make": "samsung", - "platform": "android" - }, - "client": { - "installation_id": "id1234", - "app_title": "title", - "app_version_name": "alpha", - "app_version_code": "9.9", - "app_package_name": "pname" - } - } - } - } - ] -} diff --git a/test/unit/harness_test.rb b/test/unit/harness_test.rb deleted file mode 100644 index 1e61a68..0000000 --- a/test/unit/harness_test.rb +++ /dev/null @@ -1,115 +0,0 @@ -require './lib/aws_lambda_ric/lambda_handler' -require './lib/aws_lambda_ric/lambda_context' -require './lib/aws_lambda_ric/aws_lambda_marshaller' -require './lib/aws_lambda_ric/telemetry_log_sink' -require './lib/aws_lambda_ric/bootstrap' -require 'securerandom' -require 'minitest/autorun' -require 'logger' - - -class HarnessTests < Minitest::Test - test_suite = open('test/unit/harness-suite.json') - json = test_suite.read - - parsed_json = JSON.parse(json) - parsed_json['tests'].each do |test| - test_name = test["name"] - if !test_name.start_with?('test') - test_name = "test_#{test_name}" - end - - handler = test['handler'] - - event = test['request'] - - assertion = test['assertion'] - - env_vars = test['environmentVariables'] - - context = {} - if test.key?('cognitoIdentity') - context['Lambda-Runtime-Cognito-Identity'] = test['cognitoIdentity'].to_json - end - if test.key?('clientContext') - context['Lambda-Runtime-Client-Context'] = test['clientContext'].to_json - end - if test.key?('xray') - context['Lambda-Runtime-Trace-Id'] = test['xray']['traceId'] - end - - - - define_method(test_name) do - # Logger uses request id - $_global_aws_request_id = SecureRandom.uuid - - # Set up env variables for the test - if env_vars - env_vars.each do |env_var, value| - ENV[env_var] = value - end - end - - # Set up Telemetry Log fd - Bootstrap::bootstrap_telemetry_log_sink('') - - context = LambdaContext.new(context) - - # If the test is expecting an error - if assertion.key?('errorType') - begin - lambda_handler = LambdaHandler.new(env_handler: "resources/runtime_handlers/#{handler}") - require_relative lambda_handler.handler_file_name - handler_response, content_type = lambda_handler.call_handler( - request: event, - context: context - ) - rescue LambdaErrors::LambdaError => e - assert_equal(assertion['errorType'], e.runtime_error_type) - rescue StandardError => e - assert_equal e.class.to_s, assertion['errorType'][/<(.*?)>/, 1] - rescue ScriptError => e - assert_equal e.class.to_s, assertion['errorType'][/<(.*?)>/, 1] - end - # If the test is expecting an assertion - else - lambda_handler = LambdaHandler.new(env_handler: "resources/runtime_handlers/#{handler}") - require_relative lambda_handler.handler_file_name - handler_response, content_type = lambda_handler.call_handler( - request: event, - context: context - ) - - if assertion.key?('transform') - transform = assertion['transform'] - assert_equal assertion['response'], handler_response.to_s.match?(/#{transform}/) - else - assert_equal assertion['response'].to_json, handler_response - end - end - - # Revert changes made for tests that use Telemetry Log fd - if ENV.key?('_LAMBDA_TELEMETRY_LOG_FD') - Logger.class_eval do - alias_method :initialize, :orig_initialize - end - - Kernel.module_eval do - def puts(*args) - $stdout.puts(*args) - end - end - - File.open('test/unit/resources/fd/test_fd', 'w') {|file| file.truncate(0) } - end - - # Delete env vars set for the test - if env_vars - env_vars.each do |env_var, value| - ENV.delete(env_var) - end - end - end - end -end \ No newline at end of file diff --git a/test/unit/lambda_log_formatter_test.rb b/test/unit/lambda_log_formatter_test.rb index 0af92d2..777b92f 100644 --- a/test/unit/lambda_log_formatter_test.rb +++ b/test/unit/lambda_log_formatter_test.rb @@ -1,4 +1,4 @@ -# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# frozen_string_literal: true require_relative '../../lib/aws_lambda_ric/lambda_log_formatter' require 'logger' @@ -12,10 +12,10 @@ def test_formatter time = Time.now progname = 'test_progname' msg = 'log_message' - under_test = LambdaLogFormatter.new + under_test = LogFormatter.new actual = under_test.call('INFO', time, progname, msg) assert_equal "I, [#{time.strftime("%Y-%m-%dT%H:%M:%S.%6N")} ##{$$}] INFO #{$_global_aws_request_id} -- #{progname}: #{msg}", actual end -end +end \ No newline at end of file diff --git a/test/unit/lambda_server_test.rb b/test/unit/lambda_server_test.rb index 2edbf43..40d09db 100644 --- a/test/unit/lambda_server_test.rb +++ b/test/unit/lambda_server_test.rb @@ -1,4 +1,4 @@ -# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# frozen_string_literal: true require_relative '../../lib/aws_lambda_ric/lambda_errors' require_relative '../../lib/aws_lambda_ric/lambda_server' @@ -12,7 +12,7 @@ def setup @error = LambdaErrors::LambdaRuntimeError.new(StandardError.new('User error, replace user')) @error_uri = URI("http://#{@server_address}/2018-06-01/runtime/invocation/#{@request_id}/error") @mock_user_agent = 'mock-user-agent' - @under_test = LambdaServer.new(@server_address, @mock_user_agent) + @under_test = RapidClient.new(@server_address, @mock_user_agent) end def test_post_invocation_error_with_large_xray_cause @@ -25,10 +25,10 @@ def test_post_invocation_error_with_large_xray_cause Net::HTTP.stub(:post, post_mock) do @under_test.send_error_response( - request_id: @request_id, - error_object: @error.to_lambda_response, - error: @error, - xray_cause: large_xray_cause + request_id: @request_id, + error_object: @error.to_lambda_response, + error: @error, + xray_cause: large_xray_cause ) end @@ -38,16 +38,16 @@ def test_post_invocation_error_with_large_xray_cause def test_post_invocation_error_with_too_large_xray_cause too_large_xray_cause = 'a' * 1024 * 1024 headers = {'Lambda-Runtime-Function-Error-Type' => @error.runtime_error_type, - 'User-Agent' => @mock_user_agent} + 'User-Agent' => @mock_user_agent} post_mock = Minitest::Mock.new post_mock.expect :call, nil, [@error_uri, @error.to_lambda_response.to_json, headers] Net::HTTP.stub(:post, post_mock) do @under_test.send_error_response( - request_id: @request_id, - error_object: @error.to_lambda_response, - error: @error, - xray_cause: too_large_xray_cause + request_id: @request_id, + error_object: @error.to_lambda_response, + error: @error, + xray_cause: too_large_xray_cause ) end diff --git a/test/unit/resources/fd/test_fd b/test/unit/resources/fd/test_fd index cc8c7392bc5eb1fec235697c21c1cdc3e658c4db..067672d2e9e3ce34b6e85179b51d0652ba67f7c1 100644 GIT binary patch delta 12 OcmbQtSUoXI6M_I99Rz#; delta 71 zcmb=P%;>l@ih+@Vfx$93GcP?SRUxe?F*lV') - assert_equal 0xa55a0001, frame + frame = file.read(4).unpack('L>')[0] + assert_equal 0xa55a0003, frame - length = file.read(4).unpack1('L>') + length = file.read(4).unpack('L>')[0] assert_equal log.bytesize, length + timestamp = file.read(8).unpack('Q>')[0] + assert timestamp >= start, "Timestamp smaller than start time" + assert timestamp <= finish, "Timestamp greater than finish time" + content = file.read(length) assert_equal log, content end @@ -35,18 +41,26 @@ def test_single_frame def test_multiple_frames log_messages = ["First message first line\n second line", "Second message first line\n second line"] Tempfile.create do |file| + start = (Time.new.to_f*1000000).to_i + under_test = TelemetryLogSink.new(file: file) log_messages.each { |log| under_test.write(log) } file.rewind + finish = (Time.new.to_f*1000000).to_i + log_messages.each do |log| - frame = file.read(4).unpack1('L>') - assert_equal 0xa55a0001, frame + frame = file.read(4).unpack('L>')[0] + assert_equal 0xa55a0003, frame - length = file.read(4).unpack1('L>') + length = file.read(4).unpack('L>')[0] assert_equal log.bytesize, length + timestamp = file.read(8).unpack('Q>')[0] + assert timestamp >= start, "Timestamp smaller than start time" + assert timestamp <= finish, "Timestamp greater than finish time" + content = file.read(length) assert_equal log, content end diff --git a/test/unit/xray_cause_test.rb b/test/unit/xray_cause_test.rb index d0d7082..1e2fafb 100644 --- a/test/unit/xray_cause_test.rb +++ b/test/unit/xray_cause_test.rb @@ -1,5 +1,3 @@ -# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. - # frozen_string_literal: true require_relative '../../lib/aws_lambda_ric/xray_cause' From 09d15e802e027cfb9b3c8d85ca7e1373f0f17519 Mon Sep 17 00:00:00 2001 From: Matt Muller Date: Sun, 26 Jan 2025 11:31:15 -0500 Subject: [PATCH 2/2] Update ruby version in CI --- .github/workflows/test-on-push-and-pr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-on-push-and-pr.yml b/.github/workflows/test-on-push-and-pr.yml index 14412ce..b72af18 100644 --- a/.github/workflows/test-on-push-and-pr.yml +++ b/.github/workflows/test-on-push-and-pr.yml @@ -15,6 +15,6 @@ jobs: - name: Set up ruby uses: ruby/setup-ruby@v1 with: - ruby-version: 2.7 + ruby-version: 3.1 - name: Run 'pr' target run: make pr