Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Alpine Linux environment throws error on S3 getObject #3158

Closed
itseramin opened this issue Oct 22, 2024 · 4 comments
Closed

Alpine Linux environment throws error on S3 getObject #3158

itseramin opened this issue Oct 22, 2024 · 4 comments
Labels
build-problem problems with building this sdk response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 10 days.

Comments

@itseramin
Copy link

Describe the bug

When calling the S3 getObject function the following error is shown: Error: getObject: CoreErrors::ENDPOINT_RESOLUTION_FAILURE: Unexpected nullptr: m_endpointProvider.

Expected Behavior

For it to work properly like the same way in works in my development MacOS environment that has the aws-sdk-cpp library installed with Homebrew.

Current Behavior

When calling the S3 getObject function the following error is shown: Error: getObject: CoreErrors::ENDPOINT_RESOLUTION_FAILURE: Unexpected nullptr: m_endpointProvider.

Reproduction Steps

I have the following Dockerfile:

FROM alpine:latest

RUN apk add -U --no-cache \
    build-base=0.5-r3 \
    cmake=3.29.3-r0 \
    openssl-dev=3.3.2-r1 \
    git=2.45.2-r0 \
    linux-headers=6.6-r0 \
    libpq-dev=16.3-r0 \
    libsrt-dev=1.5.3-r0 \
    aws-sdk-cpp-dev=1.11.205-r1 \
    aws-crt-cpp-dev=0.26.1-r0 \
    tzdata=2024b-r0

WORKDIR /home

WORKDIR /

COPY / /app

RUN cmake -DCMAKE_BUILD_TYPE:STRING=Release --no-warn-unused-cli -S/app -B/app/build -G "Unix Makefiles"

RUN cmake --build /app/build --config Release --target StreamServer -j 12 --

ENTRYPOINT [ "/app/build/StreamServer" ]

EXPOSE 1234/UDP

And a code snippet for how I setup my AWS SDK:

    Aws::SDKOptions options;

    Aws::InitAPI(options);
    {

        Aws::Auth::AWSCredentials awsCredentials(Aws::String(config.getAWSAccessKey()), Aws::String(config.getAWSSecretKey()));

        Aws::Client::ClientConfiguration clientConfig;
        clientConfig.endpointOverride = Aws::String(config.getAWSEndpoint());
        clientConfig.region = Aws::String(config.getAWSRegion());
        clientConfig.scheme = Aws::Http::Scheme::HTTPS;

        Aws::S3::S3Client s3Client(awsCredentials, nullptr, clientConfig);

        AwsMediaStore awsMediaStore(config.getAWSBucket(), config.getAWSRootPath(), s3Client);
    }
    Aws::ShutdownAPI(options);

Possible Solution

I saw that the Aws::S3::S3Client class's constructor takes a std::shared_ptr<S3EndpointProviderBase> as a second parameter which is defaulted to nullptr, should I create this object pointer, but then why isn't it needed for my MacOS environment?

Setting the clientConfig's endpointOverride property works fine:

Aws::Client::ClientConfiguration clientConfig;
clientConfig.endpointOverride = Aws::String(config.getAWSEndpoint());
...

I also tried setting:

clientConfig.enableEndpointDiscovery = true;

but had no effect.

Additional Information/Context

We are trying to deploy our audio streaming application to a Kubernetes cluster, hence the Dockerfile. Testing the Docker image locally produces the same error in the K8 cluster too.

AWS CPP SDK version used

1.11.205-r1

Compiler and Version used

GNU 13.2.1

Operating System and version

Alpine Linux 3.20.3

@itseramin itseramin added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Oct 22, 2024
@sbiscigl
Copy link
Contributor

sbiscigl commented Oct 23, 2024

Hey @itseramin thanks for the detailed issue, we really appreciate reproducible docker files. That being said for this case we cannot reproduce the issue. for my workspace and test:

~/sdk-usage-workspace ❯❯❯ tree -L 1
.
├── CMakeLists.txt
├── Dockerfile
├── main.cpp
└── replicate.sh

CMakeLists.txt

cmake_minimum_required(VERSION 3.13)
project(sdk_usage_workspace)
set(CMAKE_CXX_STANDARD 20)
find_package(AWSSDK REQUIRED COMPONENTS s3)
add_executable(${PROJECT_NAME} "main.cpp")
target_link_libraries(${PROJECT_NAME} PRIVATE ${AWSSDK_LINK_LIBRARIES})

Dockerfile

FROM alpine:latest

RUN apk add -U --no-cache \
    build-base=0.5-r3 \
    cmake=3.29.3-r0 \
    openssl-dev=3.3.2-r1 \
    git=2.45.2-r0 \
    aws-sdk-cpp-dev=1.11.205-r1 \
    aws-crt-cpp-dev=0.26.1-r0

## Copy over and build
RUN mkdir sdk-example
COPY CMakeLists.txt /sdk-example/CMakeLists.txt
COPY main.cpp /sdk-example/main.cpp
RUN cd sdk-example &&\
    mkdir build &&\
    cd build &&\
    cmake .. && \
    cmake --build .

main.cpp

#include <aws/core/Aws.h>
#include <aws/s3/S3Client.h>

using namespace Aws;
using namespace Aws::S3;

auto main() -> int {
  SDKOptions options;
  InitAPI(options);
  {
    S3Client client{};
    const auto buckets_result = client.ListBuckets();
    assert(buckets_result.IsSuccess());
    for (const auto& bucket : buckets_result.GetResult().GetBuckets()) {
      std::cout << bucket.GetName() << "\n";
    }
  }
  ShutdownAPI(options);
  return 0;
}

replicate.sh

#!/bin/zsh

set -u

# build image
docker build -t test-image .

# run example
docker run \
    -e AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} \
    -e AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} \
    -e AWS_SESSION_TOKEN=${AWS_SESSION_TOKEN} \
    --name test-image test-image /sdk-example/build/sdk_usage_workspace

when i run ./replicate.sh given that i have AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY/AWS_SESSION_TOKEN set in the current shell i will see it execute successfully and list the buckets.

So from this snippet it looks like its working. if you can update this snippet to fail, would be happy to take a look into it. I know the issue says get object, but your snippet didnt have a get object call in it, and this should also fail for list objects if the endpoint provider is null. so best to build from this basic use case.

all of that being said i am suspect of incorrect installation in your dockerfile even though its working for me from a clean install. I would suggest building and installing from source. that will likely work for you i.e. an adapted dockerfile from the example above.

FROM alpine:latest

RUN apk add -U --no-cache \
    build-base=0.5-r3 \
    cmake=3.29.3-r0 \
    openssl-dev=3.3.2-r1 \
    git=2.45.2-r0 \
    curl-dev=8.10.1-r0 \
    zlib-dev=1.3.1-r1

RUN git clone --depth 1 --recurse-submodules https://github.com/aws/aws-sdk-cpp && \
    cd aws-sdk-cpp && \
    mkdir build && \
    cd build && \
    cmake -DBUILD_ONLY="s3" \
      -DAUTORUN_UNIT_TESTS=OFF \
      -DCMAKE_INSTALL_PREFIX=/sdk-install .. && \
    cmake --build . && \
    cmake --install .

## Copy over and build
RUN mkdir sdk-example
COPY CMakeLists.txt /sdk-example/CMakeLists.txt
COPY main.cpp /sdk-example/main.cpp
RUN cd sdk-example &&\
    mkdir build &&\
    cd build &&\
    cmake -DCMAKE_PREFIX_PATH=/sdk-install .. && \
    cmake --build .

that should remove any chances of incorrectly mix and matching installations entirely by finding it purely on the CMAKE_PREFIX_PATH.

Give that a shot a let me know if you can update my example to fail/if installing and using from source works for you.

@sbiscigl sbiscigl added response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 10 days. build-problem problems with building this sdk and removed bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Oct 23, 2024
@SergeyRyabinin
Copy link
Contributor

Hi @itseramin ,

I see you are using a bit old version of the AWS CPP SDK,
The version 1.11.205 was requiring the endpointProvider pointer to be initialized and passed to the client constructor (there was a default argument set in the API definition in headers as well).

In the #2849, I had to refactor the API to satisfy the condition of the MSVS delay load dll flag, as a result, passing a nullptr became a valid usecase, and a default provider will be initialized (anyway you need one and anyway there are only few users requiring a non-default one).

So it is either

Aws::S3::S3Client s3Client(awsCredentials, Aws::MakeShared<S3EndpointProvider>("ALLOC_TAG"), clientConfig);

or update to a latest version (to a version at least #1.11.262).

Just in case, enableEndpointDiscovery should do / does nothing for S3, it is a functionality of DynamoDB and Timestream services (however, this flag was added to a generic ClientConfig class for some reason)

Please let us know if you still see the issue after the update or you experience other issues. Please refer to the repro template brought by @sbiscigl .

Best regards,

@itseramin
Copy link
Author

Huge thanks to @sbiscigl and @SergeyRyabinin for your detailed responses! Passing Aws::MakeShared<S3EndpointProvider>("ALLOC_TAG") as the second argument to the Aws::S3:: S3Client constructor finally solved the problem for me.

Unfortunately, I’m stuck on Alpine’s package version. The latest version (v1.11.400-r0) has dependency issues, and the highest stable version I can use from the non-edge branch is v1.11.205-r1. (I’m probably just new to Alpine and haven’t figured out how to access versions between those.)

I realise the ideal solution would be building the library from scratch, but we’ve already spent way too much time fiddling with CMakeLists and Dockerfile to get it working in our CI/CD. We’re still fairly new to the C++ ecosystem and learning as we go…

Copy link

This issue is now closed. Comments on closed issues are hard for our team to see.
If you need more assistance, please open a new issue that references this one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
build-problem problems with building this sdk response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 10 days.
Projects
None yet
Development

No branches or pull requests

3 participants