Skip to content

Commit

Permalink
feat userver: documentation for s3api
Browse files Browse the repository at this point in the history
commit_hash:a1ae0f08dfa878007ccf95b0cd89e26feda2f93a
  • Loading branch information
aserebriyskiy committed Nov 8, 2024
1 parent 90eddf7 commit ef406df
Show file tree
Hide file tree
Showing 10 changed files with 308 additions and 1 deletion.
6 changes: 6 additions & 0 deletions .mapping.json
Original file line number Diff line number Diff line change
Expand Up @@ -3230,6 +3230,11 @@
"samples/redis_service/testsuite/conftest.py":"taxi/uservices/userver/samples/redis_service/testsuite/conftest.py",
"samples/redis_service/testsuite/test_redis.py":"taxi/uservices/userver/samples/redis_service/testsuite/test_redis.py",
"samples/redis_service/unittests/redis_test.cpp":"taxi/uservices/userver/samples/redis_service/unittests/redis_test.cpp",
"samples/s3api/CMakeLists.txt":"taxi/uservices/userver/samples/s3api/CMakeLists.txt",
"samples/s3api/main.cpp":"taxi/uservices/userver/samples/s3api/main.cpp",
"samples/s3api/src/s3api_client.cpp":"taxi/uservices/userver/samples/s3api/src/s3api_client.cpp",
"samples/s3api/src/s3api_client.hpp":"taxi/uservices/userver/samples/s3api/src/s3api_client.hpp",
"samples/s3api/unittests/client_test.cpp":"taxi/uservices/userver/samples/s3api/unittests/client_test.cpp",
"samples/static_service/CMakeLists.txt":"taxi/uservices/userver/samples/static_service/CMakeLists.txt",
"samples/static_service/public/dir1/.hidden_file.txt":"taxi/uservices/userver/samples/static_service/public/dir1/.hidden_file.txt",
"samples/static_service/public/dir1/dir2/data.html":"taxi/uservices/userver/samples/static_service/public/dir1/dir2/data.html",
Expand Down Expand Up @@ -3420,6 +3425,7 @@
"scripts/docs/en/userver/tutorial/postgres_service.md":"taxi/uservices/userver/scripts/docs/en/userver/tutorial/postgres_service.md",
"scripts/docs/en/userver/tutorial/production_service.md":"taxi/uservices/userver/scripts/docs/en/userver/tutorial/production_service.md",
"scripts/docs/en/userver/tutorial/redis_service.md":"taxi/uservices/userver/scripts/docs/en/userver/tutorial/redis_service.md",
"scripts/docs/en/userver/tutorial/s3api.md":"taxi/uservices/userver/scripts/docs/en/userver/tutorial/s3api.md",
"scripts/docs/en/userver/tutorial/tcp_full.md":"taxi/uservices/userver/scripts/docs/en/userver/tutorial/tcp_full.md",
"scripts/docs/en/userver/tutorial/tcp_service.md":"taxi/uservices/userver/scripts/docs/en/userver/tutorial/tcp_service.md",
"scripts/docs/en/userver/tutorial/websocket_service.md":"taxi/uservices/userver/scripts/docs/en/userver/tutorial/websocket_service.md",
Expand Down
5 changes: 5 additions & 0 deletions samples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,11 @@ if (USERVER_FEATURE_YDB AND USERVER_FEATURE_MONGODB)
add_dependencies(${PROJECT_NAME} ${PROJECT_NAME}-ydb_service)
endif()

if (USERVER_FEATURE_S3API)
add_subdirectory(s3api)
add_dependencies(${PROJECT_NAME} ${PROJECT_NAME}-s3api)
endif()

# Clean up fake userver installation above to avoid messing
# with find_package(userver) in the parent project.
file(REMOVE "${CMAKE_BINARY_DIR}/package_stubs/userverConfig.cmake")
26 changes: 26 additions & 0 deletions samples/s3api/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
cmake_minimum_required(VERSION 3.14)
project(userver-samples-s3api CXX)

# /// [s3api]
find_package(userver COMPONENTS core s3api REQUIRED)

add_library(${PROJECT_NAME}_objs OBJECT
src/s3api_client.cpp
)
target_link_libraries(${PROJECT_NAME}_objs PUBLIC userver::s3api)
target_include_directories(${PROJECT_NAME}_objs PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src)
# /// [s3api]

add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} ${PROJECT_NAME}_objs)

# /// [gtest]
add_executable(${PROJECT_NAME}-unittest unittests/client_test.cpp)
target_link_libraries(${PROJECT_NAME}-unittest
${PROJECT_NAME}_objs
userver::utest
userver::s3api-utest
)
add_google_tests(${PROJECT_NAME}-unittest)
# /// [gtest]

13 changes: 13 additions & 0 deletions samples/s3api/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include <userver/components/minimal_server_component_list.hpp>
#include <userver/utest/using_namespace_userver.hpp>
#include <userver/utils/daemon_run.hpp>

#include <s3api_client.hpp>

/// [main]
int main(int argc, char* argv[]) {
const auto component_list = components::MinimalServerComponentList().Append<samples::S3ApiSampleComponent>();

return utils::DaemonMain(argc, argv, component_list);
}
/// [main]
62 changes: 62 additions & 0 deletions samples/s3api/src/s3api_client.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include "s3api_client.hpp"

#include <userver/components/component_config.hpp>
#include <userver/components/component_context.hpp>

/// [includes]

#include <userver/s3api/authenticators/access_key.hpp>
#include <userver/s3api/clients/s3api.hpp>
#include <userver/s3api/models/s3api_connection_type.hpp>

/// [includes]

namespace samples {

S3ApiSampleComponent::S3ApiSampleComponent(
const components::ComponentConfig& config,
const components::ComponentContext& context
)
: LoggableComponentBase(config, context),
http_client_(context.FindComponent<::components::HttpClient>().GetHttpClient()) {
auto my_client = GetClient();
DoVeryImportantThingsInS3(my_client);
}

/// [create_client]

s3api::ClientPtr S3ApiSampleComponent::GetClient() {
// Create connection settings
auto connection_cfg = s3api::ConnectionCfg(
std::chrono::milliseconds{100}, /* timeout */
2, /* retries */
std::nullopt /* proxy */
);

// Create connection object
auto s3_connection = s3api::MakeS3Connection(
http_client_, s3api::S3ConnectionType::kHttps, "s3-some-site.awsornot.com", connection_cfg
);

// Create authorizer.
auto auth = std::make_shared<s3api::authenticators::AccessKey>("my-access-key", s3api::Secret("my-secret-key"));

// create and return client
return s3api::GetS3Client(s3_connection, auth, "mybucket");
}

/// [create_client]

/// [using_client]

void DoVeryImportantThingsInS3(s3api::ClientPtr client) {
std::string path = "path/to/object";
std::string data{"some string data"};

client->PutObject(path, data);
client->GetObject(path);
}

/// [using_client]

} // namespace samples
33 changes: 33 additions & 0 deletions samples/s3api/src/s3api_client.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include <userver/clients/http/component.hpp>
#include <userver/components/loggable_component_base.hpp>

// Note: this is for the purposes of tests/samples only
#include <userver/utest/using_namespace_userver.hpp>

#include <userver/s3api/clients/fwd.hpp>

namespace samples {

/// [s3_sample_component]

// This component is not required to create S3 api client. It is used for demonstation
// purposes only.
class S3ApiSampleComponent : public components::LoggableComponentBase {
public:
// `kName` is used as the component name in static config
static constexpr std::string_view kName = "s3-sample-component";

S3ApiSampleComponent(const components::ComponentConfig& config, const components::ComponentContext& context);

s3api::ClientPtr GetClient();

private:
// http_client MUST outlive any dependent s3 client
clients::http::Client& http_client_;
};

/// [s3_sample_component]

void DoVeryImportantThingsInS3(s3api::ClientPtr client);

} // namespace samples
26 changes: 26 additions & 0 deletions samples/s3api/unittests/client_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include <gmock/gmock.h>

#include <userver/s3api/utest/client_gmock.hpp>
#include <userver/utest/using_namespace_userver.hpp>
#include <userver/utest/utest.hpp>

#include <s3api_client.hpp>

/// [client_tests]
UTEST(S3ClientTest, HappyPath) {
auto mock = std::make_shared<s3api::GMockClient>();
EXPECT_CALL(
*mock,
PutObject(
std::string_view{"path/to/object"}, ::testing::_, ::testing::_, ::testing::_, ::testing::_, ::testing::_
)
)
.Times(1)
.WillOnce(::testing::Return("OK"));
EXPECT_CALL(*mock, GetObject(std::string_view{"path/to/object"}, ::testing::_, ::testing::_, ::testing::_))
.Times(1)
.WillOnce(::testing::Return(std::string{"some data"}));

samples::DoVeryImportantThingsInS3(mock);
}
/// [client_tests]
40 changes: 40 additions & 0 deletions scripts/docs/en/userver/libraries/grpc-reflection.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,43 @@
service. It is in fact an original implementation with a few modifications to
replace all standard primitives with userver ones.


## Usage

To be honest, usage is exceedingly simple:

1. Link with in your CMakeLists.txt
```
find_package(userver COMPONENTS grpc grpc-reflection REQUIRED)
target_link_libraries(${PROJECT_NAME} userver::grpc-reflection)
```

2. Add component to your service
```
#include <userver/grpc-reflection/reflection_service_component.hpp>
int main(int argc, char* argv[]) {
const auto component_list = components::MinimalServerComponentList()
....
.Append<grpc_reflection::ReflectionServiceComponent>()
....
}
....
3. Add simple line to your config.yaml
Don't forget that grpc-reflection requires grpc
```
components_manager:
components:
grpc-reflection-service:
# Or you can set these up in grpc-server.service-defaults
task-processor: main-task-processor
middlewares: []
```
4. Thats it. Reflection component will start automatically and expose every gRPC entity in your service.
@htmlonly <div class="bottom-nav"> @endhtmlonly
⇦ @ref scripts/docs/en/userver/libraries/s3api.md | @ref scripts/docs/en/userver/development/stability.md ⇨
@htmlonly </div> @endhtmlonly
25 changes: 24 additions & 1 deletion scripts/docs/en/userver/libraries/s3api.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,27 @@

**Quality:** @ref QUALITY_TIERS "Silver Tier".

🐙 **userver** provides client to any endpoint that implements S3
## Introduction

🐙 **userver** provides client to any endpoint that implements client to any S3
endpoints. It uses ```namespace s3api```

The client is currently not feature-complete and exposes only some of the possible
methods, parameters and settings. The client also suffers from some
weird design decisions, like explicit selection of "http://" vs "https://". We
intend to gradually improve its quality in consequent releases.

See also:
* @ref scripts/docs/en/userver/tutorial/s3api.md
* [Official S3 API](https://docs.aws.amazon.com/AmazonS3/latest/API/Type_API_Reference.html)

## Usage and testing

* @ref scripts/docs/en/userver/tutorial/s3api.md shows hot to create, use and test
client

----------

@htmlonly <div class="bottom-nav"> @endhtmlonly
@ref scripts/docs/en/userver/clickhouse_driver.md | @ref scripts/docs/en/userver/libraries/grpc-reflection.md ⇨
@htmlonly </div> @endhtmlonly
73 changes: 73 additions & 0 deletions scripts/docs/en/userver/tutorial/s3api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# S3 client tutorial

## Before you start

Take a look at official S3 documentation. Have your access key and secret key ready.

## Step by step guide

In this example, we will create a client and make a request to S3 endpoint.

### Installation


Find and link to userver module:

@snippet samples/s3api/CMakeLists.txt s3api

## Creating client in code

We recomend wrapping your clients into some component. This way you can make sure that reference to http_client outlives S3 client. It can look, for example, like this:

@snippet samples/s3api/src/s3api_client.hpp s3_sample_component


To create client itself, you do only few simple steps:

@snippet samples/s3api/src/s3api_client.cpp create_client

## Using client

Here is usage example

@snippet samples/s3api/src/s3api_client.cpp using_client

## Testing

We provide google mock for client, that you can access by including header
```#include <userver/s3api/utest/client_gmock.hpp>```

With this mock, you have full power of Google Mock at your fingertips:

@snippet samples/s3api/unittests/client_test.cpp client_tests

To add tests to your project, add appropriate lines to CMakeLists.txt, like this:

@snippet samples/s3api/CMakeLists.txt gtest


## Testsuite support

Testsuite module is provided as part of testsuite plugins and can be found here:

@ref testsuite/pytest_plugins/pytest_userver/plugins/s3api.py


## Full Sources

See the full example at:

* @ref samples/s3api/src/s3api_client.hpp
* @ref samples/s3api/src/s3api_client.cpp
* @ref samples/s3api/unittests/client_test.cpp
* @ref samples/s3api/main.cpp
* @ref samples/s3api/CMakeLists.txt


----------

@example samples/s3api/src/s3api_client.hpp
@example samples/s3api/src/s3api_client.cpp
@example samples/s3api/unittests/client_test.cpp
@example samples/s3api/main.cpp
@example samples/s3api/CMakeLists.txt

0 comments on commit ef406df

Please sign in to comment.