diff --git a/.github/workflows/test-on-push-and-pr.yml b/.github/workflows/test-on-push-and-pr.yml index 735d33a..0e1a15c 100644 --- a/.github/workflows/test-on-push-and-pr.yml +++ b/.github/workflows/test-on-push-and-pr.yml @@ -27,10 +27,10 @@ jobs: # The tests in this job drive the compiled extension against a stub RAPID, # so unlike the unit tests they need the native code built first. - - name: Install aws-lambda-cpp build dependencies + - name: Install build dependencies run: | sudo apt-get update - sudo apt-get install -y g++ make cmake libcurl4-openssl-dev + sudo apt-get install -y g++ make curl gnupg libcurl4-openssl-dev - name: Install requirements run: make init diff --git a/.gitignore b/.gitignore index 0899fc1..bfeba38 100644 --- a/.gitignore +++ b/.gitignore @@ -153,5 +153,4 @@ tmp*.py # dependencies deps/artifacts/ -deps/aws-lambda-cpp-*/ deps/curl-*/ diff --git a/README.md b/README.md index 305df08..b1cddd8 100644 --- a/README.md +++ b/README.md @@ -31,12 +31,13 @@ Also, your Lambda function code needs to be copied into the image. # Include global arg in this stage of the build ARG FUNCTION_DIR -# Install aws-lambda-cpp build dependencies +# Install build dependencies RUN apt-get update && \ apt-get install -y \ g++ \ make \ - cmake \ + curl \ + gnupg \ unzip \ libcurl4-openssl-dev @@ -62,12 +63,13 @@ FROM public.ecr.aws/docker/library/python:buster as build-image # Include global arg in this stage of the build ARG FUNCTION_DIR -# Install aws-lambda-cpp build dependencies +# Install build dependencies RUN apt-get update && \ apt-get install -y \ g++ \ make \ - cmake \ + curl \ + gnupg \ unzip \ libcurl4-openssl-dev diff --git a/deps/aws-lambda-cpp-0.2.6.tar.gz b/deps/aws-lambda-cpp-0.2.6.tar.gz deleted file mode 100644 index c087a17..0000000 Binary files a/deps/aws-lambda-cpp-0.2.6.tar.gz and /dev/null differ diff --git a/deps/patches/aws-lambda-cpp-add-content-type.patch b/deps/patches/aws-lambda-cpp-add-content-type.patch deleted file mode 100644 index 2e045ff..0000000 --- a/deps/patches/aws-lambda-cpp-add-content-type.patch +++ /dev/null @@ -1,53 +0,0 @@ -diff --git a/include/aws/lambda-runtime/runtime.h b/include/aws/lambda-runtime/runtime.h -index e14b804..cc1a789 100644 ---- a/include/aws/lambda-runtime/runtime.h -+++ b/include/aws/lambda-runtime/runtime.h -@@ -56,6 +56,11 @@ struct invocation_request { - */ - std::string function_arn; - -+ /** -+ * The Content-type of the current invocation. -+ */ -+ std::string content_type; -+ - /** - * Function execution deadline counted in milliseconds since the Unix epoch. - */ -diff --git a/include/aws/http/response.h b/include/aws/http/response.h -index 9b8cbda..be184c1 100644 ---- a/include/aws/http/response.h -+++ b/include/aws/http/response.h -@@ -36,6 +36,7 @@ public: - inline void set_response_code(aws::http::response_code c); - inline void set_content_type(char const* ct); - inline std::string const& get_body() const; -+ inline std::string const& get_content_type() const; - - private: - response_code m_response_code; -@@ -137,6 +138,12 @@ inline std::string const& response::get_body() const - { - return m_body; - } -+ -+inline std::string const& response::get_content_type() const -+{ -+ return m_content_type; -+} -+ - inline void response::add_header(std::string name, std::string const& value) - { - std::transform(name.begin(), name.end(), name.begin(), ::tolower); -diff --git a/src/runtime.cpp b/src/runtime.cpp -index 08d7014..1cbd6bb 100644 ---- a/src/runtime.cpp -+++ b/src/runtime.cpp -@@ -275,6 +275,7 @@ runtime::next_outcome runtime::get_next() - invocation_request req; - req.payload = resp.get_body(); - req.request_id = resp.get_header(REQUEST_ID_HEADER); -+ req.content_type = resp.get_content_type(); - - if (resp.has_header(TRACE_ID_HEADER)) { - req.xray_trace_id = resp.get_header(TRACE_ID_HEADER); diff --git a/deps/patches/aws-lambda-cpp-add-invocation-id.patch b/deps/patches/aws-lambda-cpp-add-invocation-id.patch deleted file mode 100644 index bde825f..0000000 --- a/deps/patches/aws-lambda-cpp-add-invocation-id.patch +++ /dev/null @@ -1,137 +0,0 @@ -diff --git a/include/aws/lambda-runtime/runtime.h b/include/aws/lambda-runtime/runtime.h ---- a/include/aws/lambda-runtime/runtime.h -+++ b/include/aws/lambda-runtime/runtime.h -@@ -67,6 +67,11 @@ - std::string tenant_id; - - /** -+ * The unique invocation ID for cross-wiring protection. -+ */ -+ std::string invocation_id; -+ -+ /** - * Function execution deadline counted in milliseconds since the Unix epoch. - */ - std::chrono::time_point deadline; -@@ -184,11 +189,15 @@ - /** - * Tells lambda that the function has succeeded. - */ -+ post_outcome post_success(std::string const& request_id, invocation_response const& handler_response, std::string const& invocation_id); -+ - post_outcome post_success(std::string const& request_id, invocation_response const& handler_response); - - /** - * Tells lambda that the function has failed. - */ -+ post_outcome post_failure(std::string const& request_id, invocation_response const& handler_response, std::string const& invocation_id); -+ - post_outcome post_failure(std::string const& request_id, invocation_response const& handler_response); - - /** -@@ -203,7 +212,8 @@ - std::string const& url, - std::string const& content_type, - std::string const& payload, -- std::string const& xray_response); -+ std::string const& xray_response, -+ std::string const& invocation_id); - - private: - std::string const m_user_agent_header; -diff --git a/src/runtime.cpp b/src/runtime.cpp ---- a/src/runtime.cpp -+++ b/src/runtime.cpp -@@ -41,6 +41,7 @@ - static constexpr auto DEADLINE_MS_HEADER = "lambda-runtime-deadline-ms"; - static constexpr auto FUNCTION_ARN_HEADER = "lambda-runtime-invoked-function-arn"; - static constexpr auto TENANT_ID_HEADER = "lambda-runtime-aws-tenant-id"; -+static constexpr auto INVOCATION_ID_HEADER = "lambda-runtime-invocation-id"; - - enum Endpoints { - INIT, -@@ -294,6 +295,10 @@ - req.tenant_id = resp.get_header(TENANT_ID_HEADER); - } - -+ if (resp.has_header(INVOCATION_ID_HEADER)) { -+ req.invocation_id = resp.get_header(INVOCATION_ID_HEADER); -+ } -+ - if (resp.has_header(DEADLINE_MS_HEADER)) { - auto const& deadline_string = resp.get_header(DEADLINE_MS_HEADER); - constexpr int base = 10; -@@ -310,29 +315,40 @@ - return next_outcome(req); - } - --runtime::post_outcome runtime::post_success(std::string const& request_id, invocation_response const& handler_response) -+runtime::post_outcome runtime::post_success(std::string const& request_id, invocation_response const& handler_response, std::string const& invocation_id) - { - std::string const url = m_endpoints[Endpoints::RESULT] + request_id + "/response"; -- return do_post(url, handler_response.get_content_type(), handler_response.get_payload(), handler_response.get_xray_response()); -+ return do_post(url, handler_response.get_content_type(), handler_response.get_payload(), handler_response.get_xray_response(), invocation_id); - } - --runtime::post_outcome runtime::post_failure(std::string const& request_id, invocation_response const& handler_response) -+runtime::post_outcome runtime::post_success(std::string const& request_id, invocation_response const& handler_response) -+{ -+ return post_success(request_id, handler_response, ""); -+} -+ -+runtime::post_outcome runtime::post_failure(std::string const& request_id, invocation_response const& handler_response, std::string const& invocation_id) - { - std::string const url = m_endpoints[Endpoints::RESULT] + request_id + "/error"; -- return do_post(url, handler_response.get_content_type(), handler_response.get_payload(), handler_response.get_xray_response()); -+ return do_post(url, handler_response.get_content_type(), handler_response.get_payload(), handler_response.get_xray_response(), invocation_id); -+} -+ -+runtime::post_outcome runtime::post_failure(std::string const& request_id, invocation_response const& handler_response) -+{ -+ return post_failure(request_id, handler_response, ""); - } - - runtime::post_outcome runtime::post_init_error(runtime_response const& init_error_response) - { - std::string const url = m_endpoints[Endpoints::INIT]; -- return do_post(url, init_error_response.get_content_type(), init_error_response.get_payload(), init_error_response.get_xray_response()); -+ return do_post(url, init_error_response.get_content_type(), init_error_response.get_payload(), init_error_response.get_xray_response(), ""); - } - - runtime::post_outcome runtime::do_post( - std::string const& url, - std::string const& content_type, - std::string const& payload, -- std::string const& xray_response) -+ std::string const& xray_response, -+ std::string const& invocation_id) - { - set_curl_post_result_options(); - curl_easy_setopt(m_curl_handle, CURLOPT_URL, url.c_str()); -@@ -351,6 +366,10 @@ - headers = curl_slist_append(headers, "transfer-encoding:"); - headers = curl_slist_append(headers, m_user_agent_header.c_str()); - -+ if (!invocation_id.empty()) { -+ headers = curl_slist_append(headers, (std::string(INVOCATION_ID_HEADER) + ": " + invocation_id).c_str()); -+ } -+ - logging::log_debug( - LOG_TAG, "calculating content length... %s", ("content-length: " + std::to_string(payload.length())).c_str()); - headers = curl_slist_append(headers, ("content-length: " + std::to_string(payload.length())).c_str()); -@@ -448,13 +467,13 @@ - logging::log_info(LOG_TAG, "Invoking user handler completed."); - - if (res.is_success()) { -- const auto post_outcome = rt.post_success(req.request_id, res); -+ const auto post_outcome = rt.post_success(req.request_id, res, req.invocation_id); - if (!handle_post_outcome(post_outcome, req.request_id)) { - return; // TODO: implement a better retry strategy - } - } - else { -- const auto post_outcome = rt.post_failure(req.request_id, res); -+ const auto post_outcome = rt.post_failure(req.request_id, res, req.invocation_id); - if (!handle_post_outcome(post_outcome, req.request_id)) { - return; // TODO: implement a better retry strategy - } diff --git a/deps/patches/aws-lambda-cpp-add-tenant-id.patch b/deps/patches/aws-lambda-cpp-add-tenant-id.patch deleted file mode 100644 index a7b7172..0000000 --- a/deps/patches/aws-lambda-cpp-add-tenant-id.patch +++ /dev/null @@ -1,39 +0,0 @@ -diff --git a/include/aws/lambda-runtime/runtime.h b/include/aws/lambda-runtime/runtime.h -index 7812ff6..96be869 100644 ---- a/include/aws/lambda-runtime/runtime.h -+++ b/include/aws/lambda-runtime/runtime.h -@@ -61,6 +61,11 @@ struct invocation_request { - */ - std::string content_type; - -+ /** -+ * The Tenant ID of the current invocation. -+ */ -+ std::string tenant_id; -+ - /** - * Function execution deadline counted in milliseconds since the Unix epoch. - */ -diff --git a/src/runtime.cpp b/src/runtime.cpp -index e53b2b8..9763282 100644 ---- a/src/runtime.cpp -+++ b/src/runtime.cpp -@@ -40,6 +40,7 @@ static constexpr auto CLIENT_CONTEXT_HEADER = "lambda-runtime-client-context"; - static constexpr auto COGNITO_IDENTITY_HEADER = "lambda-runtime-cognito-identity"; - static constexpr auto DEADLINE_MS_HEADER = "lambda-runtime-deadline-ms"; - static constexpr auto FUNCTION_ARN_HEADER = "lambda-runtime-invoked-function-arn"; -+static constexpr auto TENANT_ID_HEADER = "lambda-runtime-aws-tenant-id"; - - enum Endpoints { - INIT, -@@ -289,6 +290,10 @@ runtime::next_outcome runtime::get_next() - req.function_arn = resp.get_header(FUNCTION_ARN_HEADER); - } - -+ if (resp.has_header(TENANT_ID_HEADER)) { -+ req.tenant_id = resp.get_header(TENANT_ID_HEADER); -+ } -+ - if (resp.has_header(DEADLINE_MS_HEADER)) { - auto const& deadline_string = resp.get_header(DEADLINE_MS_HEADER); - constexpr int base = 10; diff --git a/deps/patches/aws-lambda-cpp-add-xray-response.patch b/deps/patches/aws-lambda-cpp-add-xray-response.patch deleted file mode 100644 index 253e468..0000000 --- a/deps/patches/aws-lambda-cpp-add-xray-response.patch +++ /dev/null @@ -1,82 +0,0 @@ -diff --git a/include/aws/lambda-runtime/runtime.h b/include/aws/lambda-runtime/runtime.h -index 0dc292c..be77d93 100644 ---- a/include/aws/lambda-runtime/runtime.h -+++ b/include/aws/lambda-runtime/runtime.h -@@ -85,6 +85,11 @@ private: - */ - bool m_success; - -+ /** -+ * The serialized XRay response header. -+ */ -+ std::string m_xray_response; -+ - /** - * Instantiate an empty response. Used by the static functions 'success' and 'failure' to create a populated - * invocation_response -@@ -97,10 +102,12 @@ public: - // To support clients that need to control the entire error response body (e.g. adding a stack trace), this - // constructor should be used instead. - // Note: adding an overload to invocation_response::failure is not feasible since the parameter types are the same. -- invocation_response(std::string const& payload, std::string const& content_type, bool success) -- : m_payload(payload), m_content_type(content_type), m_success(success) -- { -- } -+ invocation_response(std::string const& payload, std::string const& content_type, bool success, std::string const& xray_response): -+ m_payload(payload), -+ m_content_type(content_type), -+ m_success(success), -+ m_xray_response(xray_response) -+ {} - - /** - * Create a successful invocation response with the given payload and content-type. -@@ -111,7 +118,7 @@ public: - * Create a failure response with the given error message and error type. - * The content-type is always set to application/json in this case. - */ -- static invocation_response failure(std::string const& error_message, std::string const& error_type); -+ static invocation_response failure(std::string const& error_message, std::string const& error_type, std::string const& xray_response); - - /** - * Get the MIME type of the payload. -@@ -127,6 +134,11 @@ public: - * Returns true if the payload and content-type are set. Returns false if the error message and error types are set. - */ - bool is_success() const { return m_success; } -+ -+ /** -+ * Get the XRay response string. The string isassumed to be UTF-8 encoded. -+ */ -+ std::string const& get_xray_response() const { return m_xray_response; } - }; - - struct no_result { -diff --git a/src/runtime.cpp b/src/runtime.cpp -index e2ee7cd..d895c4b 100644 ---- a/src/runtime.cpp -+++ b/src/runtime.cpp -@@ -337,6 +337,7 @@ runtime::post_outcome runtime::do_post( - headers = curl_slist_append(headers, ("content-type: " + handler_response.get_content_type()).c_str()); - } - -+ headers = curl_slist_append(headers, ("lambda-runtime-function-xray-error-cause: " + handler_response.get_xray_response()).c_str()); - headers = curl_slist_append(headers, "Expect:"); - headers = curl_slist_append(headers, "transfer-encoding:"); - headers = curl_slist_append(headers, get_user_agent_header().c_str()); -@@ -511,13 +512,15 @@ invocation_response invocation_response::success(std::string const& payload, std - } - - AWS_LAMBDA_RUNTIME_API --invocation_response invocation_response::failure(std::string const& error_message, std::string const& error_type) -+invocation_response invocation_response::failure(std::string const& error_message, std::string const& error_type, std::string const& xray_response) - { - invocation_response r; - r.m_success = false; - r.m_content_type = "application/json"; - r.m_payload = R"({"errorMessage":")" + json_escape(error_message) + R"(","errorType":")" + json_escape(error_type) + - R"(", "stackTrace":[]})"; -+ r.m_xray_response = xray_response; -+ - return r; - } diff --git a/deps/patches/aws-lambda-cpp-logging-error.patch b/deps/patches/aws-lambda-cpp-logging-error.patch deleted file mode 100644 index ac9dc1b..0000000 --- a/deps/patches/aws-lambda-cpp-logging-error.patch +++ /dev/null @@ -1,16 +0,0 @@ -diff --git a/src/runtime.cpp b/src/runtime.cpp -index 9763282..9fe78d8 100644 ---- a/src/runtime.cpp -+++ b/src/runtime.cpp -@@ -379,7 +379,10 @@ runtime::post_outcome runtime::do_post( - - if (!is_success(aws::http::response_code(http_response_code))) { - logging::log_error( -- LOG_TAG, "Failed to post handler success response. Http response code: %ld.", http_response_code); -+ LOG_TAG, -+ "Failed to post handler success response. Http response code: %ld. %s", -+ http_response_code, -+ resp.get_body().c_str()); - return aws::http::response_code(http_response_code); - } - diff --git a/deps/patches/aws-lambda-cpp-make-lto-optional.patch b/deps/patches/aws-lambda-cpp-make-lto-optional.patch deleted file mode 100644 index 54f78d2..0000000 --- a/deps/patches/aws-lambda-cpp-make-lto-optional.patch +++ /dev/null @@ -1,36 +0,0 @@ -diff --git a/CMakeLists.txt b/CMakeLists.txt -index eb8327f..e6eeda5 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -4,10 +4,9 @@ project(aws-lambda-runtime - VERSION 0.2.6 - LANGUAGES CXX) - -+option(ENABLE_LTO "Enables link-time optimization, requires compiler support." ON) - option(ENABLE_TESTS "Enables building the test project, requires AWS C++ SDK." OFF) - --include(CheckIPOSupported) -- - add_library(${PROJECT_NAME} - "src/logging.cpp" - "src/runtime.cpp" -@@ -23,11 +22,14 @@ target_include_directories(${PROJECT_NAME} PUBLIC - $ - $) - --check_ipo_supported(RESULT has_lto OUTPUT lto_check_output) --if(has_lto) -- set_property(TARGET ${PROJECT_NAME} PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) --else() -- message(WARNING "Link-time optimization (LTO) is not supported: ${lto_check_output}") -+if (ENABLE_LTO) -+ include(CheckIPOSupported) -+ check_ipo_supported(RESULT has_lto OUTPUT lto_check_output) -+ if(has_lto) -+ set_property(TARGET ${PROJECT_NAME} PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) -+ else() -+ message(WARNING "Link-time optimization (LTO) is not supported: ${lto_check_output}") -+ endif() - endif() - - find_package(CURL REQUIRED) diff --git a/deps/patches/aws-lambda-cpp-make-the-runtime-client-user-agent-overrideable.patch b/deps/patches/aws-lambda-cpp-make-the-runtime-client-user-agent-overrideable.patch deleted file mode 100644 index 8be3552..0000000 --- a/deps/patches/aws-lambda-cpp-make-the-runtime-client-user-agent-overrideable.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 846392515b2b0215902aaf7368651af196835f10 Mon Sep 17 00:00:00 2001 -From: Bryan Moffatt -Date: Wed, 21 Oct 2020 12:42:37 -0700 -Subject: [PATCH] make the Runtime Interface Client's user agent overrideable (#106) - -* make the Runtime Interface Client's user agent overrideable - -* remove extra empty string - -* clang-format -i src/* ---- - include/aws/lambda-runtime/runtime.h | 2 ++ - src/runtime.cpp | 20 ++++++++------------ - 2 files changed, 10 insertions(+), 12 deletions(-) - -diff --git a/include/aws/lambda-runtime/runtime.h b/include/aws/lambda-runtime/runtime.h -index 0dc292c..94e1e22 100644 ---- a/include/aws/lambda-runtime/runtime.h -+++ b/include/aws/lambda-runtime/runtime.h -@@ -137,6 +137,7 @@ public: - using next_outcome = aws::lambda_runtime::outcome; - using post_outcome = aws::lambda_runtime::outcome; - -+ runtime(std::string const& endpoint, std::string const& user_agent); - runtime(std::string const& endpoint); - ~runtime(); - -@@ -164,6 +165,7 @@ private: - invocation_response const& handler_response); - - private: -+ std::string const m_user_agent_header; - std::array const m_endpoints; - CURL* const m_curl_handle; - }; -diff --git a/src/runtime.cpp b/src/runtime.cpp -index e2ee7cd..f6131a4 100644 ---- a/src/runtime.cpp -+++ b/src/runtime.cpp -@@ -124,12 +124,6 @@ static size_t write_header(char* ptr, size_t size, size_t nmemb, void* userdata) - return size * nmemb; - } - --static std::string const& get_user_agent_header() --{ -- static std::string user_agent = std::string("User-Agent: AWS_Lambda_Cpp/") + get_version(); -- return user_agent; --} -- - static size_t read_data(char* buffer, size_t size, size_t nitems, void* userdata) - { - auto const limit = size * nitems; -@@ -163,10 +157,12 @@ static int rt_curl_debug_callback(CURL* handle, curl_infotype type, char* data, - } - #endif - --runtime::runtime(std::string const& endpoint) -- : m_endpoints{{endpoint + "/2018-06-01/runtime/init/error", -- endpoint + "/2018-06-01/runtime/invocation/next", -- endpoint + "/2018-06-01/runtime/invocation/"}}, -+runtime::runtime(std::string const& endpoint) : runtime(endpoint, "AWS_Lambda_Cpp/" + std::string(get_version())) {} -+ -+runtime::runtime(std::string const& endpoint, std::string const& user_agent) -+ : m_user_agent_header("User-Agent: " + user_agent), m_endpoints{{endpoint + "/2018-06-01/runtime/init/error", -+ endpoint + "/2018-06-01/runtime/invocation/next", -+ endpoint + "/2018-06-01/runtime/invocation/"}}, - m_curl_handle(curl_easy_init()) - { - if (!m_curl_handle) { -@@ -234,7 +230,7 @@ runtime::next_outcome runtime::get_next() - curl_easy_setopt(m_curl_handle, CURLOPT_HEADERDATA, &resp); - - curl_slist* headers = nullptr; -- headers = curl_slist_append(headers, get_user_agent_header().c_str()); -+ headers = curl_slist_append(headers, m_user_agent_header.c_str()); - curl_easy_setopt(m_curl_handle, CURLOPT_HTTPHEADER, headers); - - logging::log_debug(LOG_TAG, "Making request to %s", m_endpoints[Endpoints::NEXT].c_str()); -@@ -343,7 +343,7 @@ runtime::post_outcome runtime::do_post( - headers = curl_slist_append(headers, ("lambda-runtime-function-xray-error-cause: " + xray_response).c_str()); - headers = curl_slist_append(headers, "Expect:"); - headers = curl_slist_append(headers, "transfer-encoding:"); -- headers = curl_slist_append(headers, get_user_agent_header().c_str()); -+ headers = curl_slist_append(headers, m_user_agent_header.c_str()); - - logging::log_debug( - LOG_TAG, "calculating content length... %s", ("content-length: " + std::to_string(payload.length())).c_str()); --- -2.25.2 - diff --git a/deps/patches/aws-lambda-cpp-musl-no-execinfo.patch b/deps/patches/aws-lambda-cpp-musl-no-execinfo.patch deleted file mode 100644 index b5cec23..0000000 --- a/deps/patches/aws-lambda-cpp-musl-no-execinfo.patch +++ /dev/null @@ -1,21 +0,0 @@ ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -11,10 +11,17 @@ - add_library(${PROJECT_NAME} - "src/logging.cpp" - "src/runtime.cpp" -- "src/backward.cpp" - "${CMAKE_CURRENT_BINARY_DIR}/version.cpp" - ) - -+include(CheckIncludeFileCXX) -+check_include_file_cxx("execinfo.h" HAVE_EXECINFO_H) -+if (HAVE_EXECINFO_H) -+ target_sources(${PROJECT_NAME} PRIVATE "src/backward.cpp") -+else() -+ message("-- execinfo.h not found, stack traces disabled (musl/Alpine Linux)") -+endif() -+ - set_target_properties(${PROJECT_NAME} PROPERTIES - SOVERSION 0 - VERSION ${PROJECT_VERSION}) diff --git a/deps/patches/aws-lambda-cpp-posting-init-errors.patch b/deps/patches/aws-lambda-cpp-posting-init-errors.patch deleted file mode 100644 index 7635443..0000000 --- a/deps/patches/aws-lambda-cpp-posting-init-errors.patch +++ /dev/null @@ -1,206 +0,0 @@ -diff --git a/include/aws/lambda-runtime/runtime.h b/include/aws/lambda-runtime/runtime.h -index be77d93..9597272 100644 ---- a/include/aws/lambda-runtime/runtime.h -+++ b/include/aws/lambda-runtime/runtime.h -@@ -67,28 +67,58 @@ struct invocation_request { - inline std::chrono::milliseconds get_time_remaining() const; - }; - --class invocation_response { --private: -+class runtime_response { -+protected: - /** -- * The output of the function which is sent to the lambda caller. -+ * The response payload from the runtime. - */ - std::string m_payload; - - /** - * The MIME type of the payload. -- * This is always set to 'application/json' in unsuccessful invocations. - */ - std::string m_content_type; - - /** -- * Flag to distinguish if the contents are for successful or unsuccessful invocations. -+ * The serialized XRay response header. - */ -- bool m_success; -+ std::string m_xray_response; - - /** -- * The serialized XRay response header. -+ * Instantiate an empty response. - */ -- std::string m_xray_response; -+ runtime_response() = default; -+public: -+ /* Create a runtime response with the given payload, content type and xray response. This can be used for constructing an -+ * initialization error response. For invocation success and failure response, see invocation_response. -+ */ -+ runtime_response(std::string const& payload, std::string const& content_type, std::string const& xray_response) -+ : m_payload(payload), m_content_type(content_type), m_xray_response(xray_response) -+ { -+ } -+ -+ /** -+ * Get the payload string. The string is assumed to be UTF-8 encoded. -+ */ -+ std::string const& get_payload() const { return m_payload; } -+ -+ /** -+ * Get the MIME type of the payload. -+ */ -+ std::string const& get_content_type() const { return m_content_type; } -+ -+ /** -+ * Get the XRay response string. The string is assumed to be UTF-8 encoded. -+ */ -+ std::string const& get_xray_response() const { return m_xray_response; } -+}; -+ -+class invocation_response: public runtime_response { -+private: -+ /** -+ * Flag to distinguish if the contents are for successful or unsuccessful invocations. -+ */ -+ bool m_success; - - /** - * Instantiate an empty response. Used by the static functions 'success' and 'failure' to create a populated -@@ -102,12 +132,10 @@ public: - // To support clients that need to control the entire error response body (e.g. adding a stack trace), this - // constructor should be used instead. - // Note: adding an overload to invocation_response::failure is not feasible since the parameter types are the same. -- invocation_response(std::string const& payload, std::string const& content_type, bool success, std::string const& xray_response): -- m_payload(payload), -- m_content_type(content_type), -- m_success(success), -- m_xray_response(xray_response) -- {} -+ invocation_response(std::string const& payload, std::string const& content_type, bool success, std::string const& xray_response) -+ : runtime_response(payload, content_type, xray_response), m_success(success) -+ { -+ } - - /** - * Create a successful invocation response with the given payload and content-type. -@@ -120,25 +148,10 @@ public: - */ - static invocation_response failure(std::string const& error_message, std::string const& error_type, std::string const& xray_response); - -- /** -- * Get the MIME type of the payload. -- */ -- std::string const& get_content_type() const { return m_content_type; } -- -- /** -- * Get the payload string. The string is assumed to be UTF-8 encoded. -- */ -- std::string const& get_payload() const { return m_payload; } -- - /** - * Returns true if the payload and content-type are set. Returns false if the error message and error types are set. - */ - bool is_success() const { return m_success; } -- -- /** -- * Get the XRay response string. The string isassumed to be UTF-8 encoded. -- */ -- std::string const& get_xray_response() const { return m_xray_response; } - }; - - struct no_result { -@@ -167,13 +180,19 @@ public: - */ - post_outcome post_failure(std::string const& request_id, invocation_response const& handler_response); - -+ /** -+ * Tells lambda that the runtime has failed during initialization. -+ */ -+ post_outcome post_init_error(runtime_response const& init_error_response); -+ - private: - void set_curl_next_options(); - void set_curl_post_result_options(); - post_outcome do_post( - std::string const& url, -- std::string const& request_id, -- invocation_response const& handler_response); -+ std::string const& content_type, -+ std::string const& payload, -+ std::string const& xray_response); - - private: - std::array const m_endpoints; -diff --git a/src/runtime.cpp b/src/runtime.cpp -index d895c4b..659666e 100644 ---- a/src/runtime.cpp -+++ b/src/runtime.cpp -@@ -311,37 +311,44 @@ runtime::next_outcome runtime::get_next() - runtime::post_outcome runtime::post_success(std::string const& request_id, invocation_response const& handler_response) - { - std::string const url = m_endpoints[Endpoints::RESULT] + request_id + "/response"; -- return do_post(url, request_id, handler_response); -+ return do_post(url, handler_response.get_content_type(), handler_response.get_payload(), handler_response.get_xray_response()); - } - - runtime::post_outcome runtime::post_failure(std::string const& request_id, invocation_response const& handler_response) - { - std::string const url = m_endpoints[Endpoints::RESULT] + request_id + "/error"; -- return do_post(url, request_id, handler_response); -+ return do_post(url, handler_response.get_content_type(), handler_response.get_payload(), handler_response.get_xray_response()); -+} -+ -+runtime::post_outcome runtime::post_init_error(runtime_response const& init_error_response) -+{ -+ std::string const url = m_endpoints[Endpoints::INIT]; -+ return do_post(url, init_error_response.get_content_type(), init_error_response.get_payload(), init_error_response.get_xray_response()); - } - - runtime::post_outcome runtime::do_post( - std::string const& url, -- std::string const& request_id, -- invocation_response const& handler_response) -+ std::string const& content_type, -+ std::string const& payload, -+ std::string const& xray_response) - { - set_curl_post_result_options(); - curl_easy_setopt(m_curl_handle, CURLOPT_URL, url.c_str()); - logging::log_info(LOG_TAG, "Making request to %s", url.c_str()); - - curl_slist* headers = nullptr; -- if (handler_response.get_content_type().empty()) { -+ if (content_type.empty()) { - headers = curl_slist_append(headers, "content-type: text/html"); - } - else { -- headers = curl_slist_append(headers, ("content-type: " + handler_response.get_content_type()).c_str()); -+ headers = curl_slist_append(headers, ("content-type: " + content_type).c_str()); - } - -- headers = curl_slist_append(headers, ("lambda-runtime-function-xray-error-cause: " + handler_response.get_xray_response()).c_str()); -+ headers = curl_slist_append(headers, ("lambda-runtime-function-xray-error-cause: " + xray_response).c_str()); - headers = curl_slist_append(headers, "Expect:"); - headers = curl_slist_append(headers, "transfer-encoding:"); - headers = curl_slist_append(headers, get_user_agent_header().c_str()); -- auto const& payload = handler_response.get_payload(); -+ - logging::log_debug( - LOG_TAG, "calculating content length... %s", ("content-length: " + std::to_string(payload.length())).c_str()); - headers = curl_slist_append(headers, ("content-length: " + std::to_string(payload.length())).c_str()); -@@ -358,10 +365,10 @@ runtime::post_outcome runtime::do_post( - if (curl_code != CURLE_OK) { - logging::log_debug( - LOG_TAG, -- "CURL returned error code %d - %s, for invocation %s", -+ "CURL returned error code %d - %s, when calling %s", - curl_code, - curl_easy_strerror(curl_code), -- request_id.c_str()); -+ url.c_str()); - return aws::http::response_code::REQUEST_NOT_MADE; - } - diff --git a/deps/versions b/deps/versions index 63b0efc..94e06e7 100644 --- a/deps/versions +++ b/deps/versions @@ -1,4 +1,4 @@ -AWS_LAMBDA_CPP_RELEASE=0.2.6 +AWS_LAMBDA_CPP_RELEASE=1.0.1 CURL_MAJOR_VERSION=7 CURL_MINOR_VERSION=83 CURL_PATCH_VERSION=1 diff --git a/scripts/preinstall.sh b/scripts/preinstall.sh index fdc436c..a5316c8 100755 --- a/scripts/preinstall.sh +++ b/scripts/preinstall.sh @@ -6,54 +6,92 @@ ARTIFACTS_DIR=$(pwd)/deps/artifacts if [ "$(uname)" = "Darwin" ]; then echo "aws-lambda-cpp does not build on OS X. Skipping the preinstall step." -else - if [ -x "$(command -v cmake3)" ]; then - CMAKE=cmake3 - elif [ -x "$(command -v cmake)" ]; then - CMAKE=cmake + exit 0 +fi + +download() { + if command -v curl >/dev/null 2>&1; then + curl -fsSL -o "$2" "$1" + elif command -v wget >/dev/null 2>&1; then + wget -q -O "$2" "$1" else - echo 'Error: cmake is not installed.' >&2 + echo 'Error: need curl or wget to fetch dependencies.' >&2 exit 1 fi +} + +cd deps +. ./versions + +CURL_VERSION="${CURL_MAJOR_VERSION}.${CURL_MINOR_VERSION}.${CURL_PATCH_VERSION}" + +rm -rf "./curl-$CURL_VERSION" + +# unpack and build curl from the vendored source tarball +tar xzf "./curl-$CURL_VERSION.tar.gz" --no-same-owner + +( + # Build Curl + cd "curl-$CURL_VERSION" && \ + ./buildconf && \ + ./configure \ + --prefix "$ARTIFACTS_DIR" \ + --disable-shared \ + --without-ssl \ + --with-pic \ + --without-zlib \ + --without-ngtcp2 \ + --without-nghttp3 && \ + make && \ + make install +) + + +if ! command -v gpg >/dev/null 2>&1; then + echo 'Error: gpg is required to verify the aws-lambda-cpp release artifact.' >&2 + exit 1 +fi + +case "$(uname -m)" in + x86_64) RELEASE_ARCH="x86_64" ;; + aarch64|arm64) RELEASE_ARCH="aarch64" ;; + *) + echo "Error: unsupported architecture '$(uname -m)' for aws-lambda-cpp." >&2 + exit 1 + ;; +esac + +ALC_VERSION="$AWS_LAMBDA_CPP_RELEASE" +ALC_TAG="v${ALC_VERSION}" +ALC_REPO_URL="https://github.com/awslabs/aws-lambda-cpp" +ALC_RELEASE_URL="${ALC_REPO_URL}/releases/download/${ALC_TAG}" +ALC_SIGNING_KEY_URL="https://raw.githubusercontent.com/awslabs/aws-lambda-cpp/${ALC_TAG}/signing-public-key.asc" +LIB_ASSET="libaws-lambda-runtime-${RELEASE_ARCH}.a" + +echo "Fetching prebuilt aws-lambda-cpp ${ALC_VERSION} for ${RELEASE_ARCH}" + +WORKDIR=$(mktemp -d) + +download "${ALC_RELEASE_URL}/${LIB_ASSET}" "${WORKDIR}/${LIB_ASSET}" +download "${ALC_RELEASE_URL}/${LIB_ASSET}.asc" "${WORKDIR}/${LIB_ASSET}.asc" +download "${ALC_RELEASE_URL}/SHA256SUMS" "${WORKDIR}/SHA256SUMS" +download "${ALC_RELEASE_URL}/SHA256SUMS.asc" "${WORKDIR}/SHA256SUMS.asc" +download "${ALC_SIGNING_KEY_URL}" "${WORKDIR}/signing-key.asc" + +GNUPGHOME_DIR=$(mktemp -d) +gpg --homedir "$GNUPGHOME_DIR" --batch --quiet --import "${WORKDIR}/signing-key.asc" +gpg --homedir "$GNUPGHOME_DIR" --batch --verify "${WORKDIR}/${LIB_ASSET}.asc" "${WORKDIR}/${LIB_ASSET}" +gpg --homedir "$GNUPGHOME_DIR" --batch --verify "${WORKDIR}/SHA256SUMS.asc" "${WORKDIR}/SHA256SUMS" +rm -rf "$GNUPGHOME_DIR" + +# Cross-check the checksum too (defence in depth; SHA256SUMS is itself signed). +(cd "$WORKDIR" && grep "${LIB_ASSET}\$" SHA256SUMS | sha256sum -c -) + +mkdir -p "$ARTIFACTS_DIR/lib" "$ARTIFACTS_DIR/include" +cp "${WORKDIR}/${LIB_ASSET}" "$ARTIFACTS_DIR/lib/libaws-lambda-runtime.a" + +download "${ALC_REPO_URL}/archive/refs/tags/${ALC_TAG}.tar.gz" "${WORKDIR}/src.tar.gz" +tar -xzf "${WORKDIR}/src.tar.gz" -C "$WORKDIR" "aws-lambda-cpp-${ALC_VERSION}/include" +cp -R "${WORKDIR}/aws-lambda-cpp-${ALC_VERSION}/include/." "$ARTIFACTS_DIR/include/" - cd deps - . ./versions - - CURL_VERSION="${CURL_MAJOR_VERSION}.${CURL_MINOR_VERSION}.${CURL_PATCH_VERSION}" - - rm -rf ./curl-$CURL_VERSION - rm -rf ./aws-lambda-cpp-$AWS_LAMBDA_CPP_RELEASE - - # unpack dependencies - tar xzf ./curl-$CURL_VERSION.tar.gz --no-same-owner && \ - tar xzf ./aws-lambda-cpp-$AWS_LAMBDA_CPP_RELEASE.tar.gz --no-same-owner - - ( - # Build Curl - cd curl-$CURL_VERSION && \ - ./buildconf && \ - ./configure \ - --prefix "$ARTIFACTS_DIR" \ - --disable-shared \ - --without-ssl \ - --with-pic \ - --without-zlib \ - --without-ngtcp2 \ - --without-nghttp3 && \ - make && \ - make install - ) - - ( - # Build aws-lambda-cpp - mkdir -p ./aws-lambda-cpp-$AWS_LAMBDA_CPP_RELEASE/build && \ - cd ./aws-lambda-cpp-$AWS_LAMBDA_CPP_RELEASE/build - - $CMAKE .. \ - -DCMAKE_CXX_FLAGS="-fPIC" \ - -DCMAKE_INSTALL_PREFIX="$ARTIFACTS_DIR" \ - -DENABLE_LTO=$ENABLE_LTO \ - -DCMAKE_MODULE_PATH="$ARTIFACTS_DIR"/lib/pkgconfig && \ - make && make install - ) -fi \ No newline at end of file +rm -rf "$WORKDIR" diff --git a/scripts/update_deps.sh b/scripts/update_deps.sh index f1e71d3..364ea0c 100755 --- a/scripts/update_deps.sh +++ b/scripts/update_deps.sh @@ -6,7 +6,7 @@ cd deps source versions # Clean up old files -rm -f aws-lambda-cpp-*.tar.gz && rm -f curl-*.tar.gz +rm -f curl-*.tar.gz LIBCURL="curl-${CURL_MAJOR_VERSION}.${CURL_MINOR_VERSION}.${CURL_PATCH_VERSION}" @@ -20,23 +20,4 @@ wget -c "https://github.com/curl/curl/releases/download/curl-${CURL_MAJOR_VERSIO tar -czf $LIBCURL.tar.gz $LIBCURL --no-same-owner && rm -rf $LIBCURL -# Grab aws-lambda-cpp -wget -c https://github.com/awslabs/aws-lambda-cpp/archive/v$AWS_LAMBDA_CPP_RELEASE.tar.gz -O - | tar -xz -## Apply patches to aws-lambda-cpp -( - cd aws-lambda-cpp-$AWS_LAMBDA_CPP_RELEASE && \ - patch -p1 < ../patches/aws-lambda-cpp-add-xray-response.patch && \ - patch -p1 < ../patches/aws-lambda-cpp-posting-init-errors.patch && \ - patch -p1 < ../patches/aws-lambda-cpp-make-the-runtime-client-user-agent-overrideable.patch && \ - patch -p1 < ../patches/aws-lambda-cpp-musl-no-execinfo.patch && \ - patch -p1 < ../patches/aws-lambda-cpp-make-lto-optional.patch && \ - patch -p1 < ../patches/aws-lambda-cpp-add-content-type.patch && \ - patch -p1 < ../patches/aws-lambda-cpp-add-tenant-id.patch && \ - patch -p1 < ../patches/aws-lambda-cpp-logging-error.patch && \ - patch -p1 < ../patches/aws-lambda-cpp-add-invocation-id.patch -) - -## Pack again and remove the folder -tar -czf aws-lambda-cpp-$AWS_LAMBDA_CPP_RELEASE.tar.gz aws-lambda-cpp-$AWS_LAMBDA_CPP_RELEASE --no-same-owner && \ - rm -rf aws-lambda-cpp-$AWS_LAMBDA_CPP_RELEASE diff --git a/tests/integration/docker/Dockerfile.echo.alpine b/tests/integration/docker/Dockerfile.echo.alpine index bcd52e6..6e0a39d 100644 --- a/tests/integration/docker/Dockerfile.echo.alpine +++ b/tests/integration/docker/Dockerfile.echo.alpine @@ -13,20 +13,18 @@ RUN apk add --no-cache \ # Stage 2 - build function and dependencies FROM python-alpine AS build-image -# Install aws-lambda-cpp build dependencies. +# Install build dependencies. # NOTE: this is the minimal toolchain a customer needs to build awslambdaric -# from source on Alpine. We intentionally do NOT install elfutils-dev: with -# libdw present, the bundled backward-cpp uses the DWARF backend and never -# includes execinfo.h, which would mask the musl/Alpine build issue (#128). -# Without it, backward-cpp falls back to the execinfo.h path - exactly what -# customers hit - so this test genuinely exercises the fix. +# from source on Alpine. It builds curl from the vendored source tarball and +# fetches + GPG-verifies the prebuilt aws-lambda-cpp static library (gnupg). +# busybox provides the wget used to download the release artifact. RUN apk add --no-cache \ build-base \ libtool \ autoconf \ automake \ make \ - cmake \ + gnupg \ libcurl # Include global args in this stage of the build diff --git a/tests/integration/docker/Dockerfile.echo.amazonlinux2 b/tests/integration/docker/Dockerfile.echo.amazonlinux2 index be05aa1..6295af1 100644 --- a/tests/integration/docker/Dockerfile.echo.amazonlinux2 +++ b/tests/integration/docker/Dockerfile.echo.amazonlinux2 @@ -53,7 +53,8 @@ FROM python-amazonlinux-builder AS build-image ARG RUNTIME_VERSION ARG ARCHITECTURE -# Install aws-lambda-cpp build dependencies +# Install build dependencies (curl built from source; prebuilt aws-lambda-cpp +# fetched with wget and GPG-verified with gnupg2) RUN yum install -y \ tar \ gzip \ @@ -63,12 +64,11 @@ RUN yum install -y \ libtool \ libcurl-devel \ gcc-c++ \ + gnupg2 \ wget -# Install a modern CMake -RUN wget --quiet -O cmake-install https://github.com/Kitware/CMake/releases/download/v3.20.0/cmake-3.20.0-linux-${ARCHITECTURE}.sh && \ - sh cmake-install --skip-license --prefix=/usr --exclude-subdirectory; - +# The stage-1 Python is built with --enable-shared into /usr/local, so the +# loader needs /usr/local/lib to run it. ENV PATH=/usr/local/bin:$PATH ENV LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH diff --git a/tests/integration/docker/Dockerfile.echo.amazonlinux2023 b/tests/integration/docker/Dockerfile.echo.amazonlinux2023 index 16bbc79..458039a 100644 --- a/tests/integration/docker/Dockerfile.echo.amazonlinux2023 +++ b/tests/integration/docker/Dockerfile.echo.amazonlinux2023 @@ -53,8 +53,7 @@ FROM python-amazonlinux-builder AS build-image ARG RUNTIME_VERSION ARG ARCHITECTURE -# Install aws-lambda-cpp build dependencies -RUN dnf install -y \ +RUN dnf install -y --allowerasing \ tar \ gzip \ make \ @@ -63,13 +62,12 @@ RUN dnf install -y \ libtool \ libcurl-devel \ gcc-c++ \ + gnupg2 \ wget \ sqlite-devel -# Install a modern CMake -RUN wget --quiet -O cmake-install https://github.com/Kitware/CMake/releases/download/v3.20.0/cmake-3.20.0-linux-${ARCHITECTURE}.sh && \ - sh cmake-install --skip-license --prefix=/usr --exclude-subdirectory; - +# The stage-1 Python is built with --enable-shared into /usr/local, so the +# loader needs /usr/local/lib to run it. ENV PATH=/usr/local/bin:$PATH ENV LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH diff --git a/tests/integration/docker/Dockerfile.echo.debian b/tests/integration/docker/Dockerfile.echo.debian index 5c14eb9..a59551a 100644 --- a/tests/integration/docker/Dockerfile.echo.debian +++ b/tests/integration/docker/Dockerfile.echo.debian @@ -4,12 +4,14 @@ ARG DISTRO_VERSION # Stage 1 - build function and dependencies FROM public.ecr.aws/docker/library/python:${RUNTIME_VERSION}-${DISTRO_VERSION} AS python-debian-builder -# Install aws-lambda-cpp build dependencies +# Install build dependencies (curl built from source; prebuilt aws-lambda-cpp +# fetched with curl and GPG-verified with gnupg) RUN apt-get update && \ apt-get install -y \ g++ \ make \ - cmake \ + curl \ + gnupg \ libcurl4-openssl-dev # Include global args in this stage of the build diff --git a/tests/integration/docker/Dockerfile.echo.ubuntu b/tests/integration/docker/Dockerfile.echo.ubuntu index 0ce3000..40cb91a 100644 --- a/tests/integration/docker/Dockerfile.echo.ubuntu +++ b/tests/integration/docker/Dockerfile.echo.ubuntu @@ -31,14 +31,16 @@ FROM python-image AS python-ubuntu-builder ARG RUNTIME_VERSION -# Install aws-lambda-cpp build dependencies +# Install build dependencies (curl built from source; prebuilt aws-lambda-cpp +# fetched with curl and GPG-verified with gnupg) RUN apt-get install -y \ g++ \ gcc \ tar \ gzip \ make \ - cmake \ + curl \ + gnupg \ autoconf \ automake \ libtool \ diff --git a/tests/test_runtime_client_headers.py b/tests/test_runtime_client_headers.py index d853f46..79810c5 100644 --- a/tests/test_runtime_client_headers.py +++ b/tests/test_runtime_client_headers.py @@ -76,9 +76,9 @@ class TestInvocationIdOnTheWire(unittest.TestCase): These tests drive the compiled extension against a real socket, so they cover the header-emitting C++ code in aws-lambda-cpp that the mocked unit - tests in test_lambda_runtime_client.py cannot reach. If - aws-lambda-cpp-add-invocation-id.patch is ever dropped from the vendored - tarball, these are the tests that fail. + tests in test_lambda_runtime_client.py cannot reach. If a future + aws-lambda-cpp release ever drops the invocation-id support these rely on, + these are the tests that fail. """ def _run_client(self, invocation_id, mode="response"):