GetBlobServiceProperties and SetBlobServiceProperties (#366)
This commit is contained in:
parent
cbec5c6af6
commit
b9212922e7
@ -137,6 +137,28 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
Azure::Core::Context Context;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Optional parameters for BlobServiceClient::SetProperties.
|
||||
*/
|
||||
struct SetBlobServicePropertiesOptions
|
||||
{
|
||||
/**
|
||||
* @brief Context for cancelling long running operations.
|
||||
*/
|
||||
Azure::Core::Context Context;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Optional parameters for BlobServiceClient::GetProperties.
|
||||
*/
|
||||
struct GetBlobServicePropertiesOptions
|
||||
{
|
||||
/**
|
||||
* @brief Context for cancelling long running operations.
|
||||
*/
|
||||
Azure::Core::Context Context;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Container client options used to initalize BlobContainerClient.
|
||||
*/
|
||||
|
||||
@ -124,6 +124,34 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
const std::string& expiresOn,
|
||||
const GetUserDelegationKeyOptions& options = GetUserDelegationKeyOptions()) const;
|
||||
|
||||
/**
|
||||
* @brief Sets properties for a storage account’s Blob service endpoint, including
|
||||
* properties for Storage Analytics, CORS (Cross-Origin Resource Sharing) rules and soft delete
|
||||
* settings. You can also use this operation to set the default request version for all incoming
|
||||
* requests to the Blob service that do not have a version specified.
|
||||
*
|
||||
* @param
|
||||
* properties The blob service properties.
|
||||
* @param options Optional parameters to execute
|
||||
* this function.
|
||||
* @return A SetServicePropertiesInfo on successfully setting the
|
||||
* properties.
|
||||
*/
|
||||
Azure::Core::Response<SetServicePropertiesInfo> SetProperties(
|
||||
BlobServiceProperties properties,
|
||||
const SetBlobServicePropertiesOptions& options = SetBlobServicePropertiesOptions()) const;
|
||||
|
||||
/**
|
||||
* @brief Gets the properties of a storage account’s blob service, including properties
|
||||
* for Storage Analytics and CORS (Cross-Origin Resource Sharing) rules.
|
||||
*
|
||||
* @param options Optional parameters to execute this function.
|
||||
* @return A BlobServiceProperties
|
||||
* describing the service properties.
|
||||
*/
|
||||
Azure::Core::Response<BlobServiceProperties> GetProperties(
|
||||
const GetBlobServicePropertiesOptions& options = GetBlobServicePropertiesOptions()) const;
|
||||
|
||||
protected:
|
||||
UriBuilder m_serviceUrl;
|
||||
std::shared_ptr<Azure::Core::Http::HttpPipeline> m_pipeline;
|
||||
|
||||
@ -247,6 +247,15 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
Azure::Core::Nullable<std::string> EncryptionKeySHA256;
|
||||
}; // struct BlobContentInfo
|
||||
|
||||
struct BlobCorsRule
|
||||
{
|
||||
std::string AllowedOrigins;
|
||||
std::string AllowedMethods;
|
||||
std::string AllowedHeaders;
|
||||
std::string ExposedHeaders;
|
||||
int32_t MaxAgeInSeconds = 0;
|
||||
}; // struct BlobCorsRule
|
||||
|
||||
struct BlobHttpHeaders
|
||||
{
|
||||
std::string ContentType;
|
||||
@ -354,6 +363,12 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
std::string Name;
|
||||
}; // struct BlobPrefix
|
||||
|
||||
struct BlobRetentionPolicy
|
||||
{
|
||||
bool Enabled = false;
|
||||
Azure::Core::Nullable<int32_t> Days;
|
||||
}; // struct BlobRetentionPolicy
|
||||
|
||||
struct BlobSnapshotInfo
|
||||
{
|
||||
std::string Snapshot;
|
||||
@ -363,6 +378,14 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
Azure::Core::Nullable<std::string> EncryptionKeySHA256;
|
||||
}; // struct BlobSnapshotInfo
|
||||
|
||||
struct BlobStaticWebsite
|
||||
{
|
||||
bool Enabled = false;
|
||||
Azure::Core::Nullable<std::string> IndexDocument;
|
||||
Azure::Core::Nullable<std::string> DefaultIndexDocumentPath;
|
||||
Azure::Core::Nullable<std::string> ErrorDocument404Path;
|
||||
}; // struct BlobStaticWebsite
|
||||
|
||||
enum class BlobType
|
||||
{
|
||||
Unknown,
|
||||
@ -824,6 +847,10 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
{
|
||||
}; // struct SetBlobAccessTierInfo
|
||||
|
||||
struct SetServicePropertiesInfo
|
||||
{
|
||||
}; // struct SetServicePropertiesInfo
|
||||
|
||||
struct UndeleteBlobInfo
|
||||
{
|
||||
}; // struct UndeleteBlobInfo
|
||||
@ -839,6 +866,15 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
std::string Value;
|
||||
}; // struct UserDelegationKey
|
||||
|
||||
struct BlobAnalyticsLogging
|
||||
{
|
||||
std::string Version;
|
||||
bool Delete = false;
|
||||
bool Read = false;
|
||||
bool Write = false;
|
||||
BlobRetentionPolicy RetentionPolicy;
|
||||
}; // struct BlobAnalyticsLogging
|
||||
|
||||
struct BlobBlockListInfo
|
||||
{
|
||||
std::string ETag;
|
||||
@ -925,6 +961,14 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
Azure::Core::Nullable<std::string> EncryptionKeySHA256;
|
||||
}; // struct BlobItem
|
||||
|
||||
struct BlobMetrics
|
||||
{
|
||||
std::string Version;
|
||||
bool Enabled = false;
|
||||
BlobRetentionPolicy RetentionPolicy;
|
||||
Azure::Core::Nullable<bool> IncludeApis;
|
||||
}; // struct BlobMetrics
|
||||
|
||||
struct BlobProperties
|
||||
{
|
||||
std::string ETag;
|
||||
@ -952,6 +996,17 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
Azure::Core::Nullable<std::string> CopyCompletionTime;
|
||||
}; // struct BlobProperties
|
||||
|
||||
struct BlobServiceProperties
|
||||
{
|
||||
BlobAnalyticsLogging Logging;
|
||||
BlobMetrics HourMetrics;
|
||||
BlobMetrics MinuteMetrics;
|
||||
std::vector<BlobCorsRule> Cors;
|
||||
std::string DefaultServiceVersion;
|
||||
BlobRetentionPolicy DeleteRetentionPolicy;
|
||||
BlobStaticWebsite StaticWebsite;
|
||||
}; // struct BlobServiceProperties
|
||||
|
||||
struct BlobsFlatSegment
|
||||
{
|
||||
std::string ServiceEndpoint;
|
||||
@ -1065,6 +1120,7 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
XmlWriter writer;
|
||||
GetUserDelegationKeyOptionsToXml(writer, options);
|
||||
xml_body = writer.GetDocument();
|
||||
writer.Write(XmlNode{XmlNodeType::End});
|
||||
}
|
||||
Azure::Core::Http::MemoryBodyStream xml_body_stream(
|
||||
reinterpret_cast<const uint8_t*>(xml_body.data()), xml_body.length());
|
||||
@ -1098,7 +1154,222 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
std::move(response), std::move(pHttpResponse));
|
||||
}
|
||||
|
||||
struct GetPropertiesOptions
|
||||
{
|
||||
Azure::Core::Nullable<int32_t> Timeout;
|
||||
}; // struct GetPropertiesOptions
|
||||
|
||||
static Azure::Core::Response<BlobServiceProperties> GetProperties(
|
||||
Azure::Core::Context context,
|
||||
Azure::Core::Http::HttpPipeline& pipeline,
|
||||
const std::string& url,
|
||||
const GetPropertiesOptions& options)
|
||||
{
|
||||
auto request = Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Get, url);
|
||||
request.AddQueryParameter("restype", "service");
|
||||
request.AddQueryParameter("comp", "properties");
|
||||
request.AddHeader("x-ms-version", c_APIVersion);
|
||||
if (options.Timeout.HasValue())
|
||||
{
|
||||
request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue()));
|
||||
}
|
||||
auto pHttpResponse = pipeline.Send(context, request);
|
||||
Azure::Core::Http::RawResponse& httpResponse = *pHttpResponse;
|
||||
BlobServiceProperties response;
|
||||
auto http_status_code
|
||||
= static_cast<std::underlying_type<Azure::Core::Http::HttpStatusCode>::type>(
|
||||
httpResponse.GetStatusCode());
|
||||
if (!(http_status_code == 200))
|
||||
{
|
||||
throw StorageError::CreateFromResponse(context, std::move(pHttpResponse));
|
||||
}
|
||||
{
|
||||
const auto& httpResponseBody = httpResponse.GetBody();
|
||||
XmlReader reader(
|
||||
reinterpret_cast<const char*>(httpResponseBody.data()), httpResponseBody.size());
|
||||
response = BlobServicePropertiesFromXml(reader);
|
||||
}
|
||||
return Azure::Core::Response<BlobServiceProperties>(
|
||||
std::move(response), std::move(pHttpResponse));
|
||||
}
|
||||
|
||||
struct SetPropertiesOptions
|
||||
{
|
||||
Azure::Core::Nullable<int32_t> Timeout;
|
||||
BlobServiceProperties Properties;
|
||||
}; // struct SetPropertiesOptions
|
||||
|
||||
static Azure::Core::Response<SetServicePropertiesInfo> SetProperties(
|
||||
Azure::Core::Context context,
|
||||
Azure::Core::Http::HttpPipeline& pipeline,
|
||||
const std::string& url,
|
||||
const SetPropertiesOptions& options)
|
||||
{
|
||||
std::string xml_body;
|
||||
{
|
||||
XmlWriter writer;
|
||||
SetPropertiesOptionsToXml(writer, options);
|
||||
xml_body = writer.GetDocument();
|
||||
writer.Write(XmlNode{XmlNodeType::End});
|
||||
}
|
||||
Azure::Core::Http::MemoryBodyStream xml_body_stream(
|
||||
reinterpret_cast<const uint8_t*>(xml_body.data()), xml_body.length());
|
||||
auto request
|
||||
= Azure::Core::Http::Request(Azure::Core::Http::HttpMethod::Put, url, &xml_body_stream);
|
||||
request.AddHeader("Content-Length", std::to_string(xml_body_stream.Length()));
|
||||
request.AddQueryParameter("restype", "service");
|
||||
request.AddQueryParameter("comp", "properties");
|
||||
request.AddHeader("x-ms-version", c_APIVersion);
|
||||
if (options.Timeout.HasValue())
|
||||
{
|
||||
request.AddQueryParameter("timeout", std::to_string(options.Timeout.GetValue()));
|
||||
}
|
||||
auto pHttpResponse = pipeline.Send(context, request);
|
||||
Azure::Core::Http::RawResponse& httpResponse = *pHttpResponse;
|
||||
SetServicePropertiesInfo response;
|
||||
auto http_status_code
|
||||
= static_cast<std::underlying_type<Azure::Core::Http::HttpStatusCode>::type>(
|
||||
httpResponse.GetStatusCode());
|
||||
if (!(http_status_code == 202))
|
||||
{
|
||||
throw StorageError::CreateFromResponse(context, std::move(pHttpResponse));
|
||||
}
|
||||
return Azure::Core::Response<SetServicePropertiesInfo>(
|
||||
std::move(response), std::move(pHttpResponse));
|
||||
}
|
||||
|
||||
private:
|
||||
static BlobServiceProperties BlobServicePropertiesFromXml(XmlReader& reader)
|
||||
{
|
||||
BlobServiceProperties ret;
|
||||
enum class XmlTagName
|
||||
{
|
||||
k_StorageServiceProperties,
|
||||
k_Logging,
|
||||
k_HourMetrics,
|
||||
k_MinuteMetrics,
|
||||
k_Cors,
|
||||
k_CorsRule,
|
||||
k_DefaultServiceVersion,
|
||||
k_DeleteRetentionPolicy,
|
||||
k_StaticWebsite,
|
||||
k_Unknown,
|
||||
};
|
||||
std::vector<XmlTagName> path;
|
||||
while (true)
|
||||
{
|
||||
auto node = reader.Read();
|
||||
if (node.Type == XmlNodeType::End)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (node.Type == XmlNodeType::EndTag)
|
||||
{
|
||||
if (path.size() > 0)
|
||||
{
|
||||
path.pop_back();
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (node.Type == XmlNodeType::StartTag)
|
||||
{
|
||||
if (std::strcmp(node.Name, "StorageServiceProperties") == 0)
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_StorageServiceProperties);
|
||||
}
|
||||
else if (std::strcmp(node.Name, "Logging") == 0)
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_Logging);
|
||||
}
|
||||
else if (std::strcmp(node.Name, "HourMetrics") == 0)
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_HourMetrics);
|
||||
}
|
||||
else if (std::strcmp(node.Name, "MinuteMetrics") == 0)
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_MinuteMetrics);
|
||||
}
|
||||
else if (std::strcmp(node.Name, "Cors") == 0)
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_Cors);
|
||||
}
|
||||
else if (std::strcmp(node.Name, "CorsRule") == 0)
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_CorsRule);
|
||||
}
|
||||
else if (std::strcmp(node.Name, "DefaultServiceVersion") == 0)
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_DefaultServiceVersion);
|
||||
}
|
||||
else if (std::strcmp(node.Name, "DeleteRetentionPolicy") == 0)
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_DeleteRetentionPolicy);
|
||||
}
|
||||
else if (std::strcmp(node.Name, "StaticWebsite") == 0)
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_StaticWebsite);
|
||||
}
|
||||
else
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_Unknown);
|
||||
}
|
||||
if (path.size() == 2 && path[0] == XmlTagName::k_StorageServiceProperties
|
||||
&& path[1] == XmlTagName::k_Logging)
|
||||
{
|
||||
ret.Logging = BlobAnalyticsLoggingFromXml(reader);
|
||||
path.pop_back();
|
||||
}
|
||||
else if (
|
||||
path.size() == 2 && path[0] == XmlTagName::k_StorageServiceProperties
|
||||
&& path[1] == XmlTagName::k_HourMetrics)
|
||||
{
|
||||
ret.HourMetrics = BlobMetricsFromXml(reader);
|
||||
path.pop_back();
|
||||
}
|
||||
else if (
|
||||
path.size() == 2 && path[0] == XmlTagName::k_StorageServiceProperties
|
||||
&& path[1] == XmlTagName::k_MinuteMetrics)
|
||||
{
|
||||
ret.MinuteMetrics = BlobMetricsFromXml(reader);
|
||||
path.pop_back();
|
||||
}
|
||||
else if (
|
||||
path.size() == 3 && path[0] == XmlTagName::k_StorageServiceProperties
|
||||
&& path[1] == XmlTagName::k_Cors && path[2] == XmlTagName::k_CorsRule)
|
||||
{
|
||||
ret.Cors.emplace_back(BlobCorsRuleFromXml(reader));
|
||||
path.pop_back();
|
||||
}
|
||||
else if (
|
||||
path.size() == 2 && path[0] == XmlTagName::k_StorageServiceProperties
|
||||
&& path[1] == XmlTagName::k_DeleteRetentionPolicy)
|
||||
{
|
||||
ret.DeleteRetentionPolicy = BlobRetentionPolicyFromXml(reader);
|
||||
path.pop_back();
|
||||
}
|
||||
else if (
|
||||
path.size() == 2 && path[0] == XmlTagName::k_StorageServiceProperties
|
||||
&& path[1] == XmlTagName::k_StaticWebsite)
|
||||
{
|
||||
ret.StaticWebsite = BlobStaticWebsiteFromXml(reader);
|
||||
path.pop_back();
|
||||
}
|
||||
}
|
||||
else if (node.Type == XmlNodeType::Text)
|
||||
{
|
||||
if (path.size() == 2 && path[0] == XmlTagName::k_StorageServiceProperties
|
||||
&& path[1] == XmlTagName::k_DefaultServiceVersion)
|
||||
{
|
||||
ret.DefaultServiceVersion = node.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ListContainersSegment ListContainersSegmentFromXml(XmlReader& reader)
|
||||
{
|
||||
ListContainersSegment ret;
|
||||
@ -1321,6 +1592,92 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BlobAnalyticsLogging BlobAnalyticsLoggingFromXml(XmlReader& reader)
|
||||
{
|
||||
BlobAnalyticsLogging ret;
|
||||
enum class XmlTagName
|
||||
{
|
||||
k_Version,
|
||||
k_Delete,
|
||||
k_Read,
|
||||
k_Write,
|
||||
k_RetentionPolicy,
|
||||
k_Unknown,
|
||||
};
|
||||
std::vector<XmlTagName> path;
|
||||
while (true)
|
||||
{
|
||||
auto node = reader.Read();
|
||||
if (node.Type == XmlNodeType::End)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (node.Type == XmlNodeType::EndTag)
|
||||
{
|
||||
if (path.size() > 0)
|
||||
{
|
||||
path.pop_back();
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (node.Type == XmlNodeType::StartTag)
|
||||
{
|
||||
if (std::strcmp(node.Name, "Version") == 0)
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_Version);
|
||||
}
|
||||
else if (std::strcmp(node.Name, "Delete") == 0)
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_Delete);
|
||||
}
|
||||
else if (std::strcmp(node.Name, "Read") == 0)
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_Read);
|
||||
}
|
||||
else if (std::strcmp(node.Name, "Write") == 0)
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_Write);
|
||||
}
|
||||
else if (std::strcmp(node.Name, "RetentionPolicy") == 0)
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_RetentionPolicy);
|
||||
}
|
||||
else
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_Unknown);
|
||||
}
|
||||
if (path.size() == 1 && path[0] == XmlTagName::k_RetentionPolicy)
|
||||
{
|
||||
ret.RetentionPolicy = BlobRetentionPolicyFromXml(reader);
|
||||
path.pop_back();
|
||||
}
|
||||
}
|
||||
else if (node.Type == XmlNodeType::Text)
|
||||
{
|
||||
if (path.size() == 1 && path[0] == XmlTagName::k_Version)
|
||||
{
|
||||
ret.Version = node.Value;
|
||||
}
|
||||
else if (path.size() == 1 && path[0] == XmlTagName::k_Delete)
|
||||
{
|
||||
ret.Delete = std::strcmp(node.Value, "true") == 0;
|
||||
}
|
||||
else if (path.size() == 1 && path[0] == XmlTagName::k_Read)
|
||||
{
|
||||
ret.Read = std::strcmp(node.Value, "true") == 0;
|
||||
}
|
||||
else if (path.size() == 1 && path[0] == XmlTagName::k_Write)
|
||||
{
|
||||
ret.Write = std::strcmp(node.Value, "true") == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BlobContainerItem BlobContainerItemFromXml(XmlReader& reader)
|
||||
{
|
||||
BlobContainerItem ret;
|
||||
@ -1473,6 +1830,302 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BlobCorsRule BlobCorsRuleFromXml(XmlReader& reader)
|
||||
{
|
||||
BlobCorsRule ret;
|
||||
enum class XmlTagName
|
||||
{
|
||||
k_AllowedOrigins,
|
||||
k_AllowedMethods,
|
||||
k_MaxAgeInSeconds,
|
||||
k_ExposedHeaders,
|
||||
k_AllowedHeaders,
|
||||
k_Unknown,
|
||||
};
|
||||
std::vector<XmlTagName> path;
|
||||
while (true)
|
||||
{
|
||||
auto node = reader.Read();
|
||||
if (node.Type == XmlNodeType::End)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (node.Type == XmlNodeType::EndTag)
|
||||
{
|
||||
if (path.size() > 0)
|
||||
{
|
||||
path.pop_back();
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (node.Type == XmlNodeType::StartTag)
|
||||
{
|
||||
if (std::strcmp(node.Name, "AllowedOrigins") == 0)
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_AllowedOrigins);
|
||||
}
|
||||
else if (std::strcmp(node.Name, "AllowedMethods") == 0)
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_AllowedMethods);
|
||||
}
|
||||
else if (std::strcmp(node.Name, "MaxAgeInSeconds") == 0)
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_MaxAgeInSeconds);
|
||||
}
|
||||
else if (std::strcmp(node.Name, "ExposedHeaders") == 0)
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_ExposedHeaders);
|
||||
}
|
||||
else if (std::strcmp(node.Name, "AllowedHeaders") == 0)
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_AllowedHeaders);
|
||||
}
|
||||
else
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_Unknown);
|
||||
}
|
||||
}
|
||||
else if (node.Type == XmlNodeType::Text)
|
||||
{
|
||||
if (path.size() == 1 && path[0] == XmlTagName::k_AllowedOrigins)
|
||||
{
|
||||
ret.AllowedOrigins = node.Value;
|
||||
}
|
||||
else if (path.size() == 1 && path[0] == XmlTagName::k_AllowedMethods)
|
||||
{
|
||||
ret.AllowedMethods = node.Value;
|
||||
}
|
||||
else if (path.size() == 1 && path[0] == XmlTagName::k_MaxAgeInSeconds)
|
||||
{
|
||||
ret.MaxAgeInSeconds = std::stoi(node.Value);
|
||||
}
|
||||
else if (path.size() == 1 && path[0] == XmlTagName::k_ExposedHeaders)
|
||||
{
|
||||
ret.ExposedHeaders = node.Value;
|
||||
}
|
||||
else if (path.size() == 1 && path[0] == XmlTagName::k_AllowedHeaders)
|
||||
{
|
||||
ret.AllowedHeaders = node.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BlobMetrics BlobMetricsFromXml(XmlReader& reader)
|
||||
{
|
||||
BlobMetrics ret;
|
||||
enum class XmlTagName
|
||||
{
|
||||
k_Version,
|
||||
k_Enabled,
|
||||
k_IncludeAPIs,
|
||||
k_RetentionPolicy,
|
||||
k_Unknown,
|
||||
};
|
||||
std::vector<XmlTagName> path;
|
||||
while (true)
|
||||
{
|
||||
auto node = reader.Read();
|
||||
if (node.Type == XmlNodeType::End)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (node.Type == XmlNodeType::EndTag)
|
||||
{
|
||||
if (path.size() > 0)
|
||||
{
|
||||
path.pop_back();
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (node.Type == XmlNodeType::StartTag)
|
||||
{
|
||||
if (std::strcmp(node.Name, "Version") == 0)
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_Version);
|
||||
}
|
||||
else if (std::strcmp(node.Name, "Enabled") == 0)
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_Enabled);
|
||||
}
|
||||
else if (std::strcmp(node.Name, "IncludeAPIs") == 0)
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_IncludeAPIs);
|
||||
}
|
||||
else if (std::strcmp(node.Name, "RetentionPolicy") == 0)
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_RetentionPolicy);
|
||||
}
|
||||
else
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_Unknown);
|
||||
}
|
||||
if (path.size() == 1 && path[0] == XmlTagName::k_RetentionPolicy)
|
||||
{
|
||||
ret.RetentionPolicy = BlobRetentionPolicyFromXml(reader);
|
||||
path.pop_back();
|
||||
}
|
||||
}
|
||||
else if (node.Type == XmlNodeType::Text)
|
||||
{
|
||||
if (path.size() == 1 && path[0] == XmlTagName::k_Version)
|
||||
{
|
||||
ret.Version = node.Value;
|
||||
}
|
||||
else if (path.size() == 1 && path[0] == XmlTagName::k_Enabled)
|
||||
{
|
||||
ret.Enabled = std::strcmp(node.Value, "true") == 0;
|
||||
}
|
||||
else if (path.size() == 1 && path[0] == XmlTagName::k_IncludeAPIs)
|
||||
{
|
||||
ret.IncludeApis = std::strcmp(node.Value, "true") == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BlobRetentionPolicy BlobRetentionPolicyFromXml(XmlReader& reader)
|
||||
{
|
||||
BlobRetentionPolicy ret;
|
||||
enum class XmlTagName
|
||||
{
|
||||
k_Enabled,
|
||||
k_Days,
|
||||
k_Unknown,
|
||||
};
|
||||
std::vector<XmlTagName> path;
|
||||
while (true)
|
||||
{
|
||||
auto node = reader.Read();
|
||||
if (node.Type == XmlNodeType::End)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (node.Type == XmlNodeType::EndTag)
|
||||
{
|
||||
if (path.size() > 0)
|
||||
{
|
||||
path.pop_back();
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (node.Type == XmlNodeType::StartTag)
|
||||
{
|
||||
if (std::strcmp(node.Name, "Enabled") == 0)
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_Enabled);
|
||||
}
|
||||
else if (std::strcmp(node.Name, "Days") == 0)
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_Days);
|
||||
}
|
||||
else
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_Unknown);
|
||||
}
|
||||
}
|
||||
else if (node.Type == XmlNodeType::Text)
|
||||
{
|
||||
if (path.size() == 1 && path[0] == XmlTagName::k_Enabled)
|
||||
{
|
||||
ret.Enabled = std::strcmp(node.Value, "true") == 0;
|
||||
}
|
||||
else if (path.size() == 1 && path[0] == XmlTagName::k_Days)
|
||||
{
|
||||
ret.Days = std::stoi(node.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BlobStaticWebsite BlobStaticWebsiteFromXml(XmlReader& reader)
|
||||
{
|
||||
BlobStaticWebsite ret;
|
||||
enum class XmlTagName
|
||||
{
|
||||
k_Enabled,
|
||||
k_IndexDocument,
|
||||
k_DefaultIndexDocumentPath,
|
||||
k_ErrorDocument404Path,
|
||||
k_Unknown,
|
||||
};
|
||||
std::vector<XmlTagName> path;
|
||||
while (true)
|
||||
{
|
||||
auto node = reader.Read();
|
||||
if (node.Type == XmlNodeType::End)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (node.Type == XmlNodeType::EndTag)
|
||||
{
|
||||
if (path.size() > 0)
|
||||
{
|
||||
path.pop_back();
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (node.Type == XmlNodeType::StartTag)
|
||||
{
|
||||
if (std::strcmp(node.Name, "Enabled") == 0)
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_Enabled);
|
||||
}
|
||||
else if (std::strcmp(node.Name, "IndexDocument") == 0)
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_IndexDocument);
|
||||
}
|
||||
else if (std::strcmp(node.Name, "DefaultIndexDocumentPath") == 0)
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_DefaultIndexDocumentPath);
|
||||
}
|
||||
else if (std::strcmp(node.Name, "ErrorDocument404Path") == 0)
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_ErrorDocument404Path);
|
||||
}
|
||||
else
|
||||
{
|
||||
path.emplace_back(XmlTagName::k_Unknown);
|
||||
}
|
||||
}
|
||||
else if (node.Type == XmlNodeType::Text)
|
||||
{
|
||||
if (path.size() == 1 && path[0] == XmlTagName::k_Enabled)
|
||||
{
|
||||
ret.Enabled = std::strcmp(node.Value, "true") == 0;
|
||||
}
|
||||
else if (path.size() == 1 && path[0] == XmlTagName::k_IndexDocument)
|
||||
{
|
||||
ret.IndexDocument = node.Value;
|
||||
}
|
||||
else if (path.size() == 1 && path[0] == XmlTagName::k_DefaultIndexDocumentPath)
|
||||
{
|
||||
ret.DefaultIndexDocumentPath = node.Value;
|
||||
}
|
||||
else if (path.size() == 1 && path[0] == XmlTagName::k_ErrorDocument404Path)
|
||||
{
|
||||
ret.ErrorDocument404Path = node.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static std::map<std::string, std::string> MetadataFromXml(XmlReader& reader)
|
||||
{
|
||||
std::map<std::string, std::string> ret;
|
||||
@ -1519,7 +2172,146 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
writer.Write(XmlNode{XmlNodeType::Text, nullptr, options.ExpiresOn.data()});
|
||||
writer.Write(XmlNode{XmlNodeType::EndTag});
|
||||
writer.Write(XmlNode{XmlNodeType::EndTag});
|
||||
writer.Write(XmlNode{XmlNodeType::End});
|
||||
}
|
||||
|
||||
static void SetPropertiesOptionsToXml(XmlWriter& writer, const SetPropertiesOptions& options)
|
||||
{
|
||||
writer.Write(XmlNode{XmlNodeType::StartTag, "StorageServiceProperties"});
|
||||
BlobServicePropertiesToXml(writer, options.Properties);
|
||||
writer.Write(XmlNode{XmlNodeType::EndTag});
|
||||
}
|
||||
|
||||
static void BlobServicePropertiesToXml(
|
||||
XmlWriter& writer,
|
||||
const BlobServiceProperties& options)
|
||||
{
|
||||
writer.Write(XmlNode{XmlNodeType::StartTag, "Logging"});
|
||||
BlobAnalyticsLoggingToXml(writer, options.Logging);
|
||||
writer.Write(XmlNode{XmlNodeType::EndTag});
|
||||
writer.Write(XmlNode{XmlNodeType::StartTag, "HourMetrics"});
|
||||
BlobMetricsToXml(writer, options.HourMetrics);
|
||||
writer.Write(XmlNode{XmlNodeType::EndTag});
|
||||
writer.Write(XmlNode{XmlNodeType::StartTag, "MinuteMetrics"});
|
||||
BlobMetricsToXml(writer, options.MinuteMetrics);
|
||||
writer.Write(XmlNode{XmlNodeType::EndTag});
|
||||
writer.Write(XmlNode{XmlNodeType::StartTag, "Cors"});
|
||||
for (const auto& i : options.Cors)
|
||||
{
|
||||
BlobCorsRuleToXml(writer, i);
|
||||
}
|
||||
writer.Write(XmlNode{XmlNodeType::EndTag});
|
||||
writer.Write(XmlNode{XmlNodeType::StartTag, "DefaultServiceVersion"});
|
||||
writer.Write(XmlNode{XmlNodeType::Text, nullptr, options.DefaultServiceVersion.data()});
|
||||
writer.Write(XmlNode{XmlNodeType::EndTag});
|
||||
writer.Write(XmlNode{XmlNodeType::StartTag, "DeleteRetentionPolicy"});
|
||||
BlobRetentionPolicyToXml(writer, options.DeleteRetentionPolicy);
|
||||
writer.Write(XmlNode{XmlNodeType::EndTag});
|
||||
writer.Write(XmlNode{XmlNodeType::StartTag, "StaticWebsite"});
|
||||
BlobStaticWebsiteToXml(writer, options.StaticWebsite);
|
||||
writer.Write(XmlNode{XmlNodeType::EndTag});
|
||||
}
|
||||
|
||||
static void BlobAnalyticsLoggingToXml(XmlWriter& writer, const BlobAnalyticsLogging& options)
|
||||
{
|
||||
writer.Write(XmlNode{XmlNodeType::StartTag, "Version"});
|
||||
writer.Write(XmlNode{XmlNodeType::Text, nullptr, options.Version.data()});
|
||||
writer.Write(XmlNode{XmlNodeType::EndTag});
|
||||
writer.Write(XmlNode{XmlNodeType::StartTag, "Delete"});
|
||||
writer.Write(XmlNode{XmlNodeType::Text, nullptr, options.Delete ? "true" : "false"});
|
||||
writer.Write(XmlNode{XmlNodeType::EndTag});
|
||||
writer.Write(XmlNode{XmlNodeType::StartTag, "Read"});
|
||||
writer.Write(XmlNode{XmlNodeType::Text, nullptr, options.Read ? "true" : "false"});
|
||||
writer.Write(XmlNode{XmlNodeType::EndTag});
|
||||
writer.Write(XmlNode{XmlNodeType::StartTag, "Write"});
|
||||
writer.Write(XmlNode{XmlNodeType::Text, nullptr, options.Write ? "true" : "false"});
|
||||
writer.Write(XmlNode{XmlNodeType::EndTag});
|
||||
writer.Write(XmlNode{XmlNodeType::StartTag, "RetentionPolicy"});
|
||||
BlobRetentionPolicyToXml(writer, options.RetentionPolicy);
|
||||
writer.Write(XmlNode{XmlNodeType::EndTag});
|
||||
}
|
||||
|
||||
static void BlobCorsRuleToXml(XmlWriter& writer, const BlobCorsRule& options)
|
||||
{
|
||||
writer.Write(XmlNode{XmlNodeType::StartTag, "CorsRule"});
|
||||
writer.Write(XmlNode{XmlNodeType::StartTag, "AllowedOrigins"});
|
||||
writer.Write(XmlNode{XmlNodeType::Text, nullptr, options.AllowedOrigins.data()});
|
||||
writer.Write(XmlNode{XmlNodeType::EndTag});
|
||||
writer.Write(XmlNode{XmlNodeType::StartTag, "AllowedMethods"});
|
||||
writer.Write(XmlNode{XmlNodeType::Text, nullptr, options.AllowedMethods.data()});
|
||||
writer.Write(XmlNode{XmlNodeType::EndTag});
|
||||
writer.Write(XmlNode{XmlNodeType::StartTag, "AllowedHeaders"});
|
||||
writer.Write(XmlNode{XmlNodeType::Text, nullptr, options.AllowedHeaders.data()});
|
||||
writer.Write(XmlNode{XmlNodeType::EndTag});
|
||||
writer.Write(XmlNode{XmlNodeType::StartTag, "ExposedHeaders"});
|
||||
writer.Write(XmlNode{XmlNodeType::Text, nullptr, options.ExposedHeaders.data()});
|
||||
writer.Write(XmlNode{XmlNodeType::EndTag});
|
||||
writer.Write(XmlNode{XmlNodeType::StartTag, "MaxAgeInSeconds"});
|
||||
writer.Write(
|
||||
XmlNode{XmlNodeType::Text, nullptr, std::to_string(options.MaxAgeInSeconds).data()});
|
||||
writer.Write(XmlNode{XmlNodeType::EndTag});
|
||||
writer.Write(XmlNode{XmlNodeType::EndTag});
|
||||
}
|
||||
|
||||
static void BlobMetricsToXml(XmlWriter& writer, const BlobMetrics& options)
|
||||
{
|
||||
writer.Write(XmlNode{XmlNodeType::StartTag, "Version"});
|
||||
writer.Write(XmlNode{XmlNodeType::Text, nullptr, options.Version.data()});
|
||||
writer.Write(XmlNode{XmlNodeType::EndTag});
|
||||
writer.Write(XmlNode{XmlNodeType::StartTag, "Enabled"});
|
||||
writer.Write(XmlNode{XmlNodeType::Text, nullptr, options.Enabled ? "true" : "false"});
|
||||
writer.Write(XmlNode{XmlNodeType::EndTag});
|
||||
if (options.IncludeApis.HasValue())
|
||||
{
|
||||
writer.Write(XmlNode{XmlNodeType::StartTag, "IncludeAPIs"});
|
||||
writer.Write(XmlNode{
|
||||
XmlNodeType::Text, nullptr, options.IncludeApis.GetValue() ? "true" : "false"});
|
||||
writer.Write(XmlNode{XmlNodeType::EndTag});
|
||||
}
|
||||
writer.Write(XmlNode{XmlNodeType::StartTag, "RetentionPolicy"});
|
||||
BlobRetentionPolicyToXml(writer, options.RetentionPolicy);
|
||||
writer.Write(XmlNode{XmlNodeType::EndTag});
|
||||
}
|
||||
|
||||
static void BlobRetentionPolicyToXml(XmlWriter& writer, const BlobRetentionPolicy& options)
|
||||
{
|
||||
writer.Write(XmlNode{XmlNodeType::StartTag, "Enabled"});
|
||||
writer.Write(XmlNode{XmlNodeType::Text, nullptr, options.Enabled ? "true" : "false"});
|
||||
writer.Write(XmlNode{XmlNodeType::EndTag});
|
||||
if (options.Days.HasValue())
|
||||
{
|
||||
writer.Write(XmlNode{XmlNodeType::StartTag, "Days"});
|
||||
writer.Write(
|
||||
XmlNode{XmlNodeType::Text, nullptr, std::to_string(options.Days.GetValue()).data()});
|
||||
writer.Write(XmlNode{XmlNodeType::EndTag});
|
||||
}
|
||||
}
|
||||
|
||||
static void BlobStaticWebsiteToXml(XmlWriter& writer, const BlobStaticWebsite& options)
|
||||
{
|
||||
writer.Write(XmlNode{XmlNodeType::StartTag, "Enabled"});
|
||||
writer.Write(XmlNode{XmlNodeType::Text, nullptr, options.Enabled ? "true" : "false"});
|
||||
writer.Write(XmlNode{XmlNodeType::EndTag});
|
||||
if (options.IndexDocument.HasValue())
|
||||
{
|
||||
writer.Write(XmlNode{XmlNodeType::StartTag, "IndexDocument"});
|
||||
writer.Write(
|
||||
XmlNode{XmlNodeType::Text, nullptr, options.IndexDocument.GetValue().data()});
|
||||
writer.Write(XmlNode{XmlNodeType::EndTag});
|
||||
}
|
||||
if (options.DefaultIndexDocumentPath.HasValue())
|
||||
{
|
||||
writer.Write(XmlNode{XmlNodeType::StartTag, "DefaultIndexDocumentPath"});
|
||||
writer.Write(XmlNode{
|
||||
XmlNodeType::Text, nullptr, options.DefaultIndexDocumentPath.GetValue().data()});
|
||||
writer.Write(XmlNode{XmlNodeType::EndTag});
|
||||
}
|
||||
if (options.ErrorDocument404Path.HasValue())
|
||||
{
|
||||
writer.Write(XmlNode{XmlNodeType::StartTag, "ErrorDocument404Path"});
|
||||
writer.Write(
|
||||
XmlNode{XmlNodeType::Text, nullptr, options.ErrorDocument404Path.GetValue().data()});
|
||||
writer.Write(XmlNode{XmlNodeType::EndTag});
|
||||
}
|
||||
}
|
||||
|
||||
}; // class Service
|
||||
@ -2582,6 +3374,7 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
{
|
||||
throw StorageError::CreateFromResponse(context, std::move(pHttpResponse));
|
||||
}
|
||||
response.BodyStream = httpResponse.GetBodyStream();
|
||||
response.ETag = httpResponse.GetHeaders().at("etag");
|
||||
response.LastModified = httpResponse.GetHeaders().at("last-modified");
|
||||
auto response_content_md5_iterator = httpResponse.GetHeaders().find("content-md5");
|
||||
@ -2686,7 +3479,6 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
= std::stoll(response_committed_block_count_iterator->second);
|
||||
}
|
||||
response.BlobType = BlobTypeFromString(httpResponse.GetHeaders().at("x-ms-blob-type"));
|
||||
response.BodyStream = httpResponse.GetBodyStream();
|
||||
return Azure::Core::Response<BlobDownloadResponse>(
|
||||
std::move(response), std::move(pHttpResponse));
|
||||
}
|
||||
@ -3881,6 +4673,7 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
XmlWriter writer;
|
||||
CommitBlockListOptionsToXml(writer, options);
|
||||
xml_body = writer.GetDocument();
|
||||
writer.Write(XmlNode{XmlNodeType::End});
|
||||
}
|
||||
Azure::Core::Http::MemoryBodyStream xml_body_stream(
|
||||
reinterpret_cast<const uint8_t*>(xml_body.data()), xml_body.length());
|
||||
@ -4194,7 +4987,6 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
XmlNode{XmlNodeType::StartTag, BlockTypeToString(i.first).data(), i.second.data()});
|
||||
}
|
||||
writer.Write(XmlNode{XmlNodeType::EndTag});
|
||||
writer.Write(XmlNode{XmlNodeType::End});
|
||||
}
|
||||
|
||||
}; // class BlockBlob
|
||||
|
||||
@ -141,4 +141,22 @@ namespace Azure { namespace Storage { namespace Blobs {
|
||||
options.Context, *m_pipeline, m_serviceUrl.ToString(), protocolLayerOptions);
|
||||
}
|
||||
|
||||
Azure::Core::Response<SetServicePropertiesInfo> BlobServiceClient::SetProperties(
|
||||
BlobServiceProperties properties,
|
||||
const SetBlobServicePropertiesOptions& options) const
|
||||
{
|
||||
BlobRestClient::Service::SetPropertiesOptions protocolLayerOptions;
|
||||
protocolLayerOptions.Properties = std::move(properties);
|
||||
return BlobRestClient::Service::SetProperties(
|
||||
options.Context, *m_pipeline, m_serviceUrl.ToString(), protocolLayerOptions);
|
||||
}
|
||||
|
||||
Azure::Core::Response<BlobServiceProperties> BlobServiceClient::GetProperties(
|
||||
const GetBlobServicePropertiesOptions& options) const
|
||||
{
|
||||
BlobRestClient::Service::GetPropertiesOptions protocolLayerOptions;
|
||||
return BlobRestClient::Service::GetProperties(
|
||||
options.Context, *m_pipeline, m_serviceUrl.ToString(), protocolLayerOptions);
|
||||
}
|
||||
|
||||
}}} // namespace Azure::Storage::Blobs
|
||||
|
||||
@ -4,6 +4,74 @@
|
||||
#include "blobs/blob.hpp"
|
||||
#include "test_base.hpp"
|
||||
|
||||
#include <thread>
|
||||
|
||||
namespace Azure { namespace Storage { namespace Blobs {
|
||||
|
||||
bool operator==(
|
||||
const Azure::Storage::Blobs::BlobRetentionPolicy& lhs,
|
||||
const Azure::Storage::Blobs::BlobRetentionPolicy& rhs)
|
||||
{
|
||||
if (lhs.Enabled != rhs.Enabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (lhs.Days.HasValue() != rhs.Days.HasValue())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (lhs.Days.HasValue() && rhs.Days.HasValue() && lhs.Days.GetValue() != rhs.Days.GetValue())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator==(
|
||||
const Azure::Storage::Blobs::BlobCorsRule& lhs,
|
||||
const Azure::Storage::Blobs::BlobCorsRule& rhs)
|
||||
{
|
||||
return lhs.AllowedHeaders == rhs.AllowedHeaders && lhs.AllowedMethods == rhs.AllowedMethods
|
||||
&& lhs.AllowedOrigins == rhs.AllowedOrigins && lhs.ExposedHeaders == rhs.ExposedHeaders
|
||||
&& lhs.MaxAgeInSeconds == rhs.MaxAgeInSeconds;
|
||||
}
|
||||
|
||||
bool operator==(
|
||||
const Azure::Storage::Blobs::BlobStaticWebsite& lhs,
|
||||
const Azure::Storage::Blobs::BlobStaticWebsite& rhs)
|
||||
{
|
||||
if (lhs.Enabled != rhs.Enabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (lhs.DefaultIndexDocumentPath.HasValue() != rhs.DefaultIndexDocumentPath.HasValue())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (lhs.DefaultIndexDocumentPath.HasValue() && rhs.DefaultIndexDocumentPath.HasValue()
|
||||
&& lhs.DefaultIndexDocumentPath.GetValue() != rhs.DefaultIndexDocumentPath.GetValue())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (lhs.DefaultIndexDocumentPath.HasValue() != rhs.DefaultIndexDocumentPath.HasValue())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (lhs.ErrorDocument404Path.HasValue() && rhs.ErrorDocument404Path.HasValue()
|
||||
&& lhs.ErrorDocument404Path.GetValue() != rhs.ErrorDocument404Path.GetValue())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (lhs.IndexDocument.HasValue() && rhs.IndexDocument.HasValue()
|
||||
&& lhs.IndexDocument.GetValue() != rhs.IndexDocument.GetValue())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}}} // namespace Azure::Storage::Blobs
|
||||
|
||||
namespace Azure { namespace Storage { namespace Test {
|
||||
|
||||
class BlobServiceClientTest : public ::testing::Test {
|
||||
@ -95,4 +163,138 @@ namespace Azure { namespace Storage { namespace Test {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(BlobServiceClientTest, GetProperties)
|
||||
{
|
||||
auto ret = m_blobServiceClient.GetProperties();
|
||||
auto properties = *ret;
|
||||
auto logging = properties.Logging;
|
||||
EXPECT_FALSE(logging.Version.empty());
|
||||
if (logging.RetentionPolicy.Enabled)
|
||||
{
|
||||
EXPECT_TRUE(logging.RetentionPolicy.Days.HasValue());
|
||||
}
|
||||
auto hourMetrics = properties.HourMetrics;
|
||||
if (hourMetrics.Enabled)
|
||||
{
|
||||
EXPECT_FALSE(hourMetrics.Version.empty());
|
||||
if (hourMetrics.RetentionPolicy.Enabled)
|
||||
{
|
||||
EXPECT_TRUE(hourMetrics.RetentionPolicy.Days.HasValue());
|
||||
}
|
||||
}
|
||||
auto minuteMetrics = properties.HourMetrics;
|
||||
if (minuteMetrics.Enabled)
|
||||
{
|
||||
EXPECT_FALSE(minuteMetrics.Version.empty());
|
||||
if (minuteMetrics.RetentionPolicy.Enabled)
|
||||
{
|
||||
EXPECT_TRUE(minuteMetrics.RetentionPolicy.Days.HasValue());
|
||||
}
|
||||
}
|
||||
EXPECT_FALSE(properties.DefaultServiceVersion.empty());
|
||||
auto deleteRetentionPolicy = properties.DeleteRetentionPolicy;
|
||||
if (deleteRetentionPolicy.Enabled)
|
||||
{
|
||||
EXPECT_TRUE(deleteRetentionPolicy.Days.HasValue());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(BlobServiceClientTest, DISABLED_SetProperties)
|
||||
{
|
||||
Blobs::BlobServiceProperties properties = *m_blobServiceClient.GetProperties();
|
||||
auto originalProperties = properties;
|
||||
|
||||
properties.Logging.Delete = !properties.Logging.Delete;
|
||||
properties.Logging.Read = !properties.Logging.Read;
|
||||
properties.Logging.Write = !properties.Logging.Write;
|
||||
properties.Logging.RetentionPolicy.Enabled = true;
|
||||
properties.Logging.RetentionPolicy.Days = 3;
|
||||
|
||||
properties.HourMetrics.Enabled = true;
|
||||
properties.HourMetrics.RetentionPolicy.Enabled = true;
|
||||
properties.HourMetrics.RetentionPolicy.Days = 4;
|
||||
properties.HourMetrics.IncludeApis = true;
|
||||
|
||||
properties.MinuteMetrics.Enabled = true;
|
||||
properties.MinuteMetrics.RetentionPolicy.Enabled = true;
|
||||
properties.MinuteMetrics.RetentionPolicy.Days = 4;
|
||||
properties.MinuteMetrics.IncludeApis = true;
|
||||
|
||||
properties.DefaultServiceVersion = Blobs::c_APIVersion;
|
||||
|
||||
properties.StaticWebsite.Enabled = true;
|
||||
properties.StaticWebsite.IndexDocument = "index.html";
|
||||
properties.StaticWebsite.ErrorDocument404Path = "404.html";
|
||||
properties.StaticWebsite.DefaultIndexDocumentPath.Reset();
|
||||
|
||||
Blobs::BlobCorsRule corsRule;
|
||||
corsRule.AllowedOrigins = "http://www.example1.com";
|
||||
corsRule.AllowedMethods = "GET,PUT";
|
||||
corsRule.AllowedHeaders = "x-ms-header1,x-ms-header2";
|
||||
corsRule.ExposedHeaders = "x-ms-header3";
|
||||
corsRule.MaxAgeInSeconds = 10;
|
||||
properties.Cors.emplace_back(corsRule);
|
||||
|
||||
corsRule.AllowedOrigins = "http://www.example2.com";
|
||||
corsRule.AllowedMethods = "DELETE";
|
||||
corsRule.AllowedHeaders = "x-ms-header1";
|
||||
corsRule.ExposedHeaders = "x-ms-header2,x-ms-header3";
|
||||
corsRule.MaxAgeInSeconds = 20;
|
||||
properties.Cors.emplace_back(corsRule);
|
||||
|
||||
properties.DeleteRetentionPolicy.Enabled = true;
|
||||
properties.DeleteRetentionPolicy.Days = 5;
|
||||
|
||||
EXPECT_NO_THROW(m_blobServiceClient.SetProperties(properties));
|
||||
// It takes some time before the new properties comes into effect.
|
||||
using namespace std::chrono_literals;
|
||||
std::this_thread::sleep_for(10s);
|
||||
auto downloadedProperties = *m_blobServiceClient.GetProperties();
|
||||
EXPECT_EQ(downloadedProperties.Logging.Version, properties.Logging.Version);
|
||||
EXPECT_EQ(downloadedProperties.Logging.Delete, properties.Logging.Delete);
|
||||
EXPECT_EQ(downloadedProperties.Logging.Read, properties.Logging.Read);
|
||||
EXPECT_EQ(downloadedProperties.Logging.Write, properties.Logging.Write);
|
||||
EXPECT_EQ(downloadedProperties.Logging.RetentionPolicy, properties.Logging.RetentionPolicy);
|
||||
|
||||
EXPECT_EQ(downloadedProperties.HourMetrics.Version, properties.HourMetrics.Version);
|
||||
EXPECT_EQ(downloadedProperties.HourMetrics.Enabled, properties.HourMetrics.Enabled);
|
||||
EXPECT_EQ(
|
||||
downloadedProperties.HourMetrics.IncludeApis.HasValue(),
|
||||
properties.HourMetrics.IncludeApis.HasValue());
|
||||
if (downloadedProperties.HourMetrics.IncludeApis.HasValue()
|
||||
== properties.HourMetrics.IncludeApis.HasValue())
|
||||
{
|
||||
EXPECT_EQ(
|
||||
downloadedProperties.HourMetrics.IncludeApis.GetValue(),
|
||||
properties.HourMetrics.IncludeApis.GetValue());
|
||||
}
|
||||
EXPECT_EQ(
|
||||
downloadedProperties.HourMetrics.RetentionPolicy, properties.HourMetrics.RetentionPolicy);
|
||||
|
||||
EXPECT_EQ(downloadedProperties.MinuteMetrics.Version, properties.MinuteMetrics.Version);
|
||||
EXPECT_EQ(downloadedProperties.MinuteMetrics.Enabled, properties.MinuteMetrics.Enabled);
|
||||
EXPECT_EQ(
|
||||
downloadedProperties.MinuteMetrics.IncludeApis.HasValue(),
|
||||
properties.MinuteMetrics.IncludeApis.HasValue());
|
||||
if (downloadedProperties.MinuteMetrics.IncludeApis.HasValue()
|
||||
== properties.MinuteMetrics.IncludeApis.HasValue())
|
||||
{
|
||||
EXPECT_EQ(
|
||||
downloadedProperties.MinuteMetrics.IncludeApis.GetValue(),
|
||||
properties.MinuteMetrics.IncludeApis.GetValue());
|
||||
}
|
||||
EXPECT_EQ(
|
||||
downloadedProperties.MinuteMetrics.RetentionPolicy,
|
||||
properties.MinuteMetrics.RetentionPolicy);
|
||||
|
||||
EXPECT_EQ(downloadedProperties.DefaultServiceVersion, properties.DefaultServiceVersion);
|
||||
EXPECT_EQ(downloadedProperties.Cors, properties.Cors);
|
||||
|
||||
EXPECT_EQ(downloadedProperties.StaticWebsite, properties.StaticWebsite);
|
||||
|
||||
EXPECT_EQ(downloadedProperties.DeleteRetentionPolicy, properties.DeleteRetentionPolicy);
|
||||
|
||||
m_blobServiceClient.SetProperties(originalProperties);
|
||||
}
|
||||
|
||||
}}} // namespace Azure::Storage::Test
|
||||
|
||||
Loading…
Reference in New Issue
Block a user