Mercurial > hg > orthanc-object-storage
changeset 223:026b2c8957c7
AWS: tags
| author | Alain Mazy <am@orthanc.team> |
|---|---|
| date | Wed, 15 Oct 2025 10:36:47 +0200 |
| parents | d7aadea091f4 |
| children | 5561be9e9fd4 a03f1959d78d |
| files | Aws/AwsS3StoragePlugin.cpp NEWS |
| diffstat | 2 files changed, 68 insertions(+), 11 deletions(-) [+] |
line wrap: on
line diff
--- a/Aws/AwsS3StoragePlugin.cpp Tue May 20 08:45:41 2025 +0200 +++ b/Aws/AwsS3StoragePlugin.cpp Wed Oct 15 10:36:47 2025 +0200 @@ -27,6 +27,8 @@ #include <aws/s3/model/GetObjectRequest.h> #include <aws/s3/model/ListObjectsRequest.h> #include <aws/s3/model/DeleteObjectRequest.h> +#include <aws/s3/model/PutObjectTaggingRequest.h> +#include <aws/s3/model/Tag.h> #include <aws/core/auth/AWSCredentialsProvider.h> #include <aws/core/utils/HashingUtils.h> #include <aws/core/utils/logging/DefaultLogSystem.h> @@ -60,10 +62,20 @@ std::shared_ptr<Aws::Utils::Threading::Executor> executor_; std::shared_ptr<Aws::Transfer::TransferManager> transferManager_; Aws::S3::Model::StorageClass storageClass_; + std::map<std::string, std::string> tags_; public: - AwsS3StoragePlugin(const std::string& nameForLogs, std::shared_ptr<Aws::S3::S3Client> client, const std::string& bucketName, bool enableLegacyStorageStructure, bool storageContainsUnknownFiles, bool useTransferManager, unsigned int transferThreadPoolSize, unsigned int transferBufferSizeMB, Aws::S3::Model::StorageClass storageClass); + AwsS3StoragePlugin(const std::string& nameForLogs, + std::shared_ptr<Aws::S3::S3Client> client, + const std::string& bucketName, + bool enableLegacyStorageStructure, + bool storageContainsUnknownFiles, + bool useTransferManager, + unsigned int transferThreadPoolSize, + unsigned int transferBufferSizeMB, + Aws::S3::Model::StorageClass storageClass, + const std::map<std::string, std::string>& tags); virtual ~AwsS3StoragePlugin(); @@ -77,6 +89,34 @@ } }; +static void SetTags(std::shared_ptr<Aws::S3::S3Client> client, const std::string& bucketName, const std::string& path, const std::map<std::string, std::string>& tags) +{ + if (tags.size() > 0) + { + Aws::S3::Model::PutObjectTaggingRequest taggingRequest; + taggingRequest.SetBucket(bucketName.c_str()); + taggingRequest.SetKey(path.c_str()); + + Aws::S3::Model::Tagging tagging; + + for (std::map<std::string, std::string>::const_iterator it = tags.begin(); it != tags.end(); ++it) + { + Aws::S3::Model::Tag tag; + tag.SetKey(it->first); + tag.SetValue(it->second); + tagging.AddTagSet(tag); + } + + taggingRequest.SetTagging(tagging); + auto taggingResult = client->PutObjectTagging(taggingRequest); + + if (!taggingResult.IsSuccess()) + { + throw StoragePluginException(std::string("error while tagging file ") + path + ": response code = " + boost::lexical_cast<std::string>((int)taggingResult.GetError().GetResponseCode()) + " " + taggingResult.GetError().GetExceptionName().c_str() + " " + taggingResult.GetError().GetMessage().c_str()); + } + } +} + class DirectWriter : public IStorage::IWriter { @@ -84,13 +124,15 @@ std::shared_ptr<Aws::S3::S3Client> client_; std::string bucketName_; Aws::S3::Model::StorageClass storageClass_; + std::map<std::string, std::string> tags_; public: - DirectWriter(std::shared_ptr<Aws::S3::S3Client> client, const std::string& bucketName, const std::string& path, Aws::S3::Model::StorageClass storageClass) + DirectWriter(std::shared_ptr<Aws::S3::S3Client> client, const std::string& bucketName, const std::string& path, Aws::S3::Model::StorageClass storageClass, const std::map<std::string, std::string>& tags) : path_(path), client_(client), bucketName_(bucketName), - storageClass_(storageClass) + storageClass_(storageClass), + tags_(tags) { } @@ -125,6 +167,8 @@ { throw StoragePluginException(std::string("error while writing file ") + path_ + ": response code = " + boost::lexical_cast<std::string>((int)result.GetError().GetResponseCode()) + " " + result.GetError().GetExceptionName().c_str() + " " + result.GetError().GetMessage().c_str()); } + + SetTags(client_, bucketName_, path_, tags_); } }; @@ -279,17 +323,21 @@ class TransferWriter : public IStorage::IWriter { + std::shared_ptr<Aws::S3::S3Client> client_; std::string path_; std::shared_ptr<Aws::Transfer::TransferManager> transferManager_; std::string bucketName_; Aws::S3::Model::StorageClass storageClass_; + std::map<std::string, std::string> tags_; public: - TransferWriter(std::shared_ptr<Aws::Transfer::TransferManager> transferManager, const std::string& bucketName, const std::string& path, Aws::S3::Model::StorageClass storageClass) - : path_(path), + TransferWriter(std::shared_ptr<Aws::S3::S3Client> client, std::shared_ptr<Aws::Transfer::TransferManager> transferManager, const std::string& bucketName, const std::string& path, Aws::S3::Model::StorageClass storageClass, const std::map<std::string, std::string>& tags) + : client_(client), + path_(path), transferManager_(transferManager), bucketName_(bucketName), - storageClass_(storageClass) + storageClass_(storageClass), + tags_(tags) { } @@ -309,6 +357,8 @@ { throw StoragePluginException(std::string("error while writing file ") + path_ + ": response code = " + boost::lexical_cast<std::string>(static_cast<int>(transferHandle->GetLastError().GetResponseCode())) + " " + transferHandle->GetLastError().GetMessage()); } + + SetTags(client_, bucketName_, path_, tags_); } }; @@ -642,9 +692,12 @@ client = Aws::MakeShared<Aws::S3::S3Client>(ALLOCATION_TAG, configuration, Aws::Client::AWSAuthV4Signer::PayloadSigningPolicy::Never, virtualAddressing); } + std::map<std::string, std::string> tags; + pluginSection.GetDictionary(tags, "Tags"); + LOG(INFO) << "AWS S3 storage initialized"; - return new AwsS3StoragePlugin(nameForLogs, client, bucketName, enableLegacyStorageStructure, storageContainsUnknownFiles, useTransferManager, transferPoolSize, transferBufferSizeMB, storageClass); + return new AwsS3StoragePlugin(nameForLogs, client, bucketName, enableLegacyStorageStructure, storageContainsUnknownFiles, useTransferManager, transferPoolSize, transferBufferSizeMB, storageClass, tags); } catch (const std::exception& e) { @@ -672,13 +725,15 @@ bool useTransferManager, unsigned int transferThreadPoolSize, unsigned int transferBufferSizeMB, - Aws::S3::Model::StorageClass storageClass) + Aws::S3::Model::StorageClass storageClass, + const std::map<std::string, std::string>& tags) : BaseStorage(nameForLogs, enableLegacyStorageStructure), bucketName_(bucketName), storageContainsUnknownFiles_(storageContainsUnknownFiles), useTransferManager_(useTransferManager), client_(client), - storageClass_(storageClass) + storageClass_(storageClass), + tags_(tags) { if (useTransferManager_) { @@ -700,11 +755,11 @@ { if (useTransferManager_) { - return new TransferWriter(transferManager_, bucketName_, GetPath(uuid, type, encryptionEnabled), storageClass_); + return new TransferWriter(client_, transferManager_, bucketName_, GetPath(uuid, type, encryptionEnabled), storageClass_, tags_); } else { - return new DirectWriter(client_, bucketName_, GetPath(uuid, type, encryptionEnabled), storageClass_); + return new DirectWriter(client_, bucketName_, GetPath(uuid, type, encryptionEnabled), storageClass_, tags_); } }
--- a/NEWS Tue May 20 08:45:41 2025 +0200 +++ b/NEWS Wed Oct 15 10:36:47 2025 +0200 @@ -4,6 +4,8 @@ * AWS plugin: * "ConnectTimeout" has been renamed into "ConnectionTimeout" to match the documentation. Both names are still accepted. + * New configuration "Tags" (dictionary) to add tags to the objects after they + have been written to the bucket. 2025-03-28 - v 2.5.1
