From e2c5cf481b7c7e803ed2147e03a9c3823ea10f6d Mon Sep 17 00:00:00 2001 From: Matt Muller <53055821+mullermp@users.noreply.github.com> Date: Wed, 5 Mar 2025 04:37:06 -0500 Subject: [PATCH 1/4] Update README for ENTRYPOINT (#41) --- README.md | 49 ++++++++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index ac5a9c1..2ff43af 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,16 @@ ## AWS Lambda Ruby Runtime Interface Client -We have open-sourced a set of software packages, Runtime Interface Clients (RIC), that implement the Lambda - [Runtime API](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-api.html), allowing you to seamlessly extend your preferred - base images to be Lambda compatible. -The Lambda Runtime Interface Client is a lightweight interface that allows your runtime to receive requests from and send requests to the Lambda service. +We have open-sourced a set of software packages, Runtime Interface Clients (RIC), that implements the Lambda +[Runtime API](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-api.html), allowing you to seamlessly extend +your preferred base images to be Lambda compatible. +The Lambda Runtime Interface Client is a lightweight interface that allows your runtime to +receive requests from and send requests to the Lambda service. The Lambda Ruby Runtime Interface Client is vended through [rubygems](https://rubygems.org/gems/aws_lambda_ric). You can include this package in your preferred base image to make that base image Lambda compatible. ## Requirements -The Ruby Runtime Interface Client package currently supports Ruby versions: - - 3.2 and 3.3 +The Ruby Runtime Interface Client package currently supports ruby 3.0 and above. ## Usage @@ -37,17 +37,9 @@ Or install it manually as: $ gem install aws_lambda_ric - -Next step would be to copy your Lambda function code into the image's working directory. -```dockerfile -# Copy function code -RUN mkdir -p ${FUNCTION_DIR} -COPY app.rb ${FUNCTION_DIR} - -WORKDIR ${FUNCTION_DIR} -``` - -The next step would be to set the `ENTRYPOINT` property of the Docker image to invoke the Runtime Interface Client and then set the `CMD` argument to specify the desired handler. +The next step would be to copy your Lambda function code into the image's working directory. +You will need to set the `ENTRYPOINT` property of the Docker image to invoke the Runtime Interface Client and +then set the `CMD` argument to specify the desired handler. Example Dockerfile: ```dockerfile @@ -84,7 +76,18 @@ ENTRYPOINT ["/usr/local/bin/aws_lambda_ric"] CMD ["app.App::Handler.process"] ``` -Example Ruby handler `app.rb`: +Note that the `ENTRYPOINT` may differ based on the base image used. You can find the correct path by running an +interactive shell in the container and checking the installed location of the gem. + +```shell script +docker run -it --rm amazonlinux:latest bash +yum install -y which ruby +gem install aws_lambda_ric +which aws_lambda_ric +``` + +Finally, create a Ruby handler. This is an example `app.rb`: + ```ruby module App class Handler @@ -97,7 +100,10 @@ end ### Local Testing -To make it easy to locally test Lambda functions packaged as container images we open-sourced a lightweight web-server, Lambda Runtime Interface Emulator (RIE), which allows your function packaged as a container image to accept HTTP requests. You can install the [AWS Lambda Runtime Interface Emulator](https://github.com/aws/aws-lambda-runtime-interface-emulator) on your local machine to test your function. Then when you run the image function, you set the entrypoint to be the emulator. +To make it easy to locally test Lambda functions packaged as container images we open-sourced a lightweight web-server, +Lambda Runtime Interface Emulator (RIE), which allows your function packaged as a container image to accept HTTP requests. +You can install the [AWS Lambda Runtime Interface Emulator](https://github.com/aws/aws-lambda-runtime-interface-emulator) on your local machine to test your function. +Thenm when you run the image function, you set the entrypoint to be the emulator. *To install the emulator and test your Lambda function* @@ -108,7 +114,8 @@ mkdir -p ~/.aws-lambda-rie && \ curl -Lo ~/.aws-lambda-rie/aws-lambda-rie https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie && \ chmod +x ~/.aws-lambda-rie/aws-lambda-rie ``` -2) Run your Lambda image function using the docker run command. + +1) Run your Lambda image function using the docker run command. ```shell script docker run -d -v ~/.aws-lambda-rie:/aws-lambda -p 9000:8080 \ @@ -119,7 +126,7 @@ docker run -d -v ~/.aws-lambda-rie:/aws-lambda -p 9000:8080 \ This runs the image as a container and starts up an endpoint locally at `http://localhost:9000/2015-03-31/functions/function/invocations`. -3) Post an event to the following endpoint using a curl command: +1) Post an event to the following endpoint using a curl command: ```shell script curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}' From 26a442f3f3ec309434b757e0c3586559287558ab Mon Sep 17 00:00:00 2001 From: Piotr Wasiak Date: Wed, 5 Mar 2025 10:37:37 +0100 Subject: [PATCH 2/4] Add missing level_override instance variable to logger #initialize (#32) * Add missing level_override instance variable from logger 1.6.0 compatibility for most recent, included in ruby 3.3.3 logger. https://github.com/ruby/logger/commit/7aabb0b4aaabea3e3a226092bdf92b60bf1c9d60 * Simpified changes with manipulating only required params * Update logger_patch.rb Add annotation what's going on --- lib/aws_lambda_ric/logger_patch.rb | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/lib/aws_lambda_ric/logger_patch.rb b/lib/aws_lambda_ric/logger_patch.rb index ced8ee1..82f2963 100644 --- a/lib/aws_lambda_ric/logger_patch.rb +++ b/lib/aws_lambda_ric/logger_patch.rb @@ -4,19 +4,15 @@ module LoggerPatch def initialize(logdev, shift_age = 0, shift_size = 1048576, level: 'debug', progname: nil, formatter: nil, datetime_format: nil, binmode: false, shift_period_suffix: '%Y%m%d') - # 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) - else - self.level = level - self.progname = progname + logdev_lambda_overwrite = logdev + # use unpatched constructor if logdev is a filename or an IO Object other than $stdout or $stderr + if !logdev || logdev == $stdout || logdev == $stderr + logdev_lambda_overwrite = AwsLambdaRIC::TelemetryLogger.telemetry_log_sink @default_formatter = LogFormatter.new - self.datetime_format = datetime_format - self.formatter = formatter - @logdev = AwsLambdaRIC::TelemetryLogger.telemetry_log_sink - @level_override = {} end + + super(logdev_lambda_overwrite, shift_age, shift_size, level: level, progname: progname, + formatter: formatter, datetime_format: datetime_format, + binmode: binmode, shift_period_suffix: shift_period_suffix) end end From bc5c6cadbb98c2d0306867f8da1e7d0d7b674c58 Mon Sep 17 00:00:00 2001 From: Ramisa Alam Date: Tue, 22 Apr 2025 15:44:35 +0000 Subject: [PATCH 3/4] feat: add tenant-id to lambda context --- lib/aws_lambda_ric/lambda_context.rb | 3 +- test/unit/lambda_server_test.rb | 58 +++++++++++++++++++++ test/unit/resources/runtime_handlers/ctx.rb | 3 +- 3 files changed, 62 insertions(+), 2 deletions(-) diff --git a/lib/aws_lambda_ric/lambda_context.rb b/lib/aws_lambda_ric/lambda_context.rb index 52758a8..259ba16 100644 --- a/lib/aws_lambda_ric/lambda_context.rb +++ b/lib/aws_lambda_ric/lambda_context.rb @@ -3,7 +3,7 @@ class LambdaContext attr_reader :aws_request_id, :invoked_function_arn, :log_group_name, :log_stream_name, :function_name, :memory_limit_in_mb, :function_version, - :identity, :client_context, :deadline_ms + :identity, :tenant_id, :client_context, :deadline_ms def initialize(request) @clock_diff = Process.clock_gettime(Process::CLOCK_REALTIME, :millisecond) - Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond) @@ -16,6 +16,7 @@ def initialize(request) @memory_limit_in_mb = ENV['AWS_LAMBDA_FUNCTION_MEMORY_SIZE'] @function_version = ENV['AWS_LAMBDA_FUNCTION_VERSION'] @identity = JSON.parse(request['Lambda-Runtime-Cognito-Identity']) unless request['Lambda-Runtime-Cognito-Identity'].to_s.empty? + @tenant_id = request['Lambda-Runtime-Aws-Tenant-Id'] unless request['Lambda-Runtime-Aws-Tenant-Id'].to_s.empty? @client_context = JSON.parse(request['Lambda-Runtime-Client-Context']) unless request['Lambda-Runtime-Client-Context'].to_s.empty? end diff --git a/test/unit/lambda_server_test.rb b/test/unit/lambda_server_test.rb index 40d09db..fb2e248 100644 --- a/test/unit/lambda_server_test.rb +++ b/test/unit/lambda_server_test.rb @@ -53,4 +53,62 @@ def test_post_invocation_error_with_too_large_xray_cause assert_mock post_mock end + + def mock_next_invocation_response() + mock_response = Net::HTTPSuccess.new(1.0, '200', 'OK') + mock_response['Lambda-Runtime-Aws-Request-Id'] = @request_id + mock_response + end + + def mock_next_invocation_request(mock_response) + get_mock = Minitest::Mock.new + get_mock.expect(:read_timeout=, nil, [RapidClient::LONG_TIMEOUT_MS]) + get_mock.expect(:start, mock_response) do |&block| + block.call(get_mock) + end + get_mock.expect(:get, mock_response, ['/2018-06-01/runtime/invocation/next', {'User-Agent' => @mock_user_agent}]) + get_mock + end + + def assert_next_invocation(get_mock, expected_tenant_id) + Net::HTTP.stub(:new, get_mock, ['127.0.0.1', 9001]) do + request_id, response = @under_test.next_invocation + assert_equal @request_id, request_id + assert_equal expected_tenant_id, response['Lambda-Runtime-Aws-Tenant-Id'] + end + end + + def test_next_invocation_without_tenant_id_header + mock_response = mock_next_invocation_response() + get_mock = mock_next_invocation_request(mock_response) + assert_next_invocation(get_mock, nil) + assert_mock get_mock + end + + def test_next_invocation_with_tenant_id_header + mock_response = mock_next_invocation_response() + mock_response['Lambda-Runtime-Aws-Tenant-Id'] = 'blue' + + get_mock = mock_next_invocation_request(mock_response) + assert_next_invocation(get_mock, 'blue') + assert_mock get_mock + end + + def test_next_invocation_with_empty_tenant_id_header + mock_response = mock_next_invocation_response() + mock_response['Lambda-Runtime-Aws-Tenant-Id'] = '' + + get_mock = mock_next_invocation_request(mock_response) + assert_next_invocation(get_mock, '') + assert_mock get_mock + end + + def test_next_invocation_with_null_tenant_id_header + mock_response = mock_next_invocation_response() + mock_response['Lambda-Runtime-Aws-Tenant-Id'] = nil + + get_mock = mock_next_invocation_request(mock_response) + assert_next_invocation(get_mock, nil) + assert_mock get_mock + end end diff --git a/test/unit/resources/runtime_handlers/ctx.rb b/test/unit/resources/runtime_handlers/ctx.rb index d577572..6517a8d 100644 --- a/test/unit/resources/runtime_handlers/ctx.rb +++ b/test/unit/resources/runtime_handlers/ctx.rb @@ -9,7 +9,8 @@ def get_context(event:,context:) log_group_name: context.log_group_name, log_stream_name: context.log_stream_name, memory_limit_in_mb: context.memory_limit_in_mb, - function_version: context.function_version + function_version: context.function_version, + tenant_id: context.tenant_id } end From 2c38b727c0af243e16c7f2baefc466f5e1e3a872 Mon Sep 17 00:00:00 2001 From: Ramisa Alam Date: Wed, 21 May 2025 14:53:35 +0000 Subject: [PATCH 4/4] Bump version to 3.1.0 --- RELEASE.CHANGELOG.md | 35 +++++++++++++++++++++++++++++++++++ lib/aws_lambda_ric/version.rb | 2 +- 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 RELEASE.CHANGELOG.md diff --git a/RELEASE.CHANGELOG.md b/RELEASE.CHANGELOG.md new file mode 100644 index 0000000..a0a79ad --- /dev/null +++ b/RELEASE.CHANGELOG.md @@ -0,0 +1,35 @@ +### May 21, 2025 +`3.1.0` +- Add support for multi tenancy ([#43](https://github.com/aws/aws-lambda-ruby-runtime-interface-client/pull/43)) + +### Feb 19, 2025 +`3.0.0` +- Fix send_error_response method signature ([#16](https://github.com/aws/aws-lambda-ruby-runtime-interface-client/pull/16)) +- Add "require 'stringio'" ([#20](https://github.com/aws/aws-lambda-ruby-runtime-interface-client/pull/20)) +- CentOS 8 is EOL, stop testing on centOS 8 ([#21](https://github.com/aws/aws-lambda-ruby-runtime-interface-client/pull/21)) +- Update rbenv & ruby-build github URLs ([#22](https://github.com/aws/aws-lambda-ruby-runtime-interface-client/pull/22)) +- Create pull request template ([#29](https://github.com/aws/aws-lambda-ruby-runtime-interface-client/pull/29)) +- Version 3 ([#38](https://github.com/aws/aws-lambda-ruby-runtime-interface-client/pull/38)) +- V3 Readme Update ([#39](https://github.com/aws/aws-lambda-ruby-runtime-interface-client/pull/39)) +- V3 Readme Update ([#40](https://github.com/aws/aws-lambda-ruby-runtime-interface-client/pull/40)) + +### Sep 29, 2021 +`2.0.0` +- AWS Lambda Runtime Interface Client for Ruby with ARM64 support + +### Dec 18, 2020 +`1.0.2` +- Fix Logger issue +- Add User-Agent header for the requests RIC makes +- Small fix in the README file + +### Dec 01, 2020 +`1.0.1` +- Improve the examples in the README file +- Update the rake requirement from ~> 10.0 to ~> 13.0 +- Add license and required_ruby_version attributes + +### Dec 01, 2020 +`1.0.0` +- Initial release of AWS Lambda Ruby Runtime Interface Client + diff --git a/lib/aws_lambda_ric/version.rb b/lib/aws_lambda_ric/version.rb index f932e8c..e643c8c 100644 --- a/lib/aws_lambda_ric/version.rb +++ b/lib/aws_lambda_ric/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module AwsLambdaRIC - VERSION = '3.0.0' + VERSION = '3.1.0' end