diff --git a/.changes/2.29.0.json b/.changes/2.29.x/2.29.0.json similarity index 100% rename from .changes/2.29.0.json rename to .changes/2.29.x/2.29.0.json diff --git a/.changes/2.29.1.json b/.changes/2.29.x/2.29.1.json similarity index 100% rename from .changes/2.29.1.json rename to .changes/2.29.x/2.29.1.json diff --git a/.changes/2.29.10.json b/.changes/2.29.x/2.29.10.json similarity index 100% rename from .changes/2.29.10.json rename to .changes/2.29.x/2.29.10.json diff --git a/.changes/2.29.11.json b/.changes/2.29.x/2.29.11.json similarity index 100% rename from .changes/2.29.11.json rename to .changes/2.29.x/2.29.11.json diff --git a/.changes/2.29.12.json b/.changes/2.29.x/2.29.12.json similarity index 100% rename from .changes/2.29.12.json rename to .changes/2.29.x/2.29.12.json diff --git a/.changes/2.29.13.json b/.changes/2.29.x/2.29.13.json similarity index 100% rename from .changes/2.29.13.json rename to .changes/2.29.x/2.29.13.json diff --git a/.changes/2.29.14.json b/.changes/2.29.x/2.29.14.json similarity index 100% rename from .changes/2.29.14.json rename to .changes/2.29.x/2.29.14.json diff --git a/.changes/2.29.15.json b/.changes/2.29.x/2.29.15.json similarity index 100% rename from .changes/2.29.15.json rename to .changes/2.29.x/2.29.15.json diff --git a/.changes/2.29.16.json b/.changes/2.29.x/2.29.16.json similarity index 100% rename from .changes/2.29.16.json rename to .changes/2.29.x/2.29.16.json diff --git a/.changes/2.29.17.json b/.changes/2.29.x/2.29.17.json similarity index 100% rename from .changes/2.29.17.json rename to .changes/2.29.x/2.29.17.json diff --git a/.changes/2.29.18.json b/.changes/2.29.x/2.29.18.json similarity index 100% rename from .changes/2.29.18.json rename to .changes/2.29.x/2.29.18.json diff --git a/.changes/2.29.19.json b/.changes/2.29.x/2.29.19.json similarity index 100% rename from .changes/2.29.19.json rename to .changes/2.29.x/2.29.19.json diff --git a/.changes/2.29.2.json b/.changes/2.29.x/2.29.2.json similarity index 100% rename from .changes/2.29.2.json rename to .changes/2.29.x/2.29.2.json diff --git a/.changes/2.29.20.json b/.changes/2.29.x/2.29.20.json similarity index 100% rename from .changes/2.29.20.json rename to .changes/2.29.x/2.29.20.json diff --git a/.changes/2.29.21.json b/.changes/2.29.x/2.29.21.json similarity index 100% rename from .changes/2.29.21.json rename to .changes/2.29.x/2.29.21.json diff --git a/.changes/2.29.22.json b/.changes/2.29.x/2.29.22.json similarity index 100% rename from .changes/2.29.22.json rename to .changes/2.29.x/2.29.22.json diff --git a/.changes/2.29.23.json b/.changes/2.29.x/2.29.23.json similarity index 100% rename from .changes/2.29.23.json rename to .changes/2.29.x/2.29.23.json diff --git a/.changes/2.29.24.json b/.changes/2.29.x/2.29.24.json similarity index 100% rename from .changes/2.29.24.json rename to .changes/2.29.x/2.29.24.json diff --git a/.changes/2.29.25.json b/.changes/2.29.x/2.29.25.json similarity index 100% rename from .changes/2.29.25.json rename to .changes/2.29.x/2.29.25.json diff --git a/.changes/2.29.26.json b/.changes/2.29.x/2.29.26.json similarity index 100% rename from .changes/2.29.26.json rename to .changes/2.29.x/2.29.26.json diff --git a/.changes/2.29.27.json b/.changes/2.29.x/2.29.27.json similarity index 100% rename from .changes/2.29.27.json rename to .changes/2.29.x/2.29.27.json diff --git a/.changes/2.29.28.json b/.changes/2.29.x/2.29.28.json similarity index 100% rename from .changes/2.29.28.json rename to .changes/2.29.x/2.29.28.json diff --git a/.changes/2.29.29.json b/.changes/2.29.x/2.29.29.json similarity index 100% rename from .changes/2.29.29.json rename to .changes/2.29.x/2.29.29.json diff --git a/.changes/2.29.3.json b/.changes/2.29.x/2.29.3.json similarity index 100% rename from .changes/2.29.3.json rename to .changes/2.29.x/2.29.3.json diff --git a/.changes/2.29.30.json b/.changes/2.29.x/2.29.30.json similarity index 100% rename from .changes/2.29.30.json rename to .changes/2.29.x/2.29.30.json diff --git a/.changes/2.29.31.json b/.changes/2.29.x/2.29.31.json similarity index 100% rename from .changes/2.29.31.json rename to .changes/2.29.x/2.29.31.json diff --git a/.changes/2.29.32.json b/.changes/2.29.x/2.29.32.json similarity index 100% rename from .changes/2.29.32.json rename to .changes/2.29.x/2.29.32.json diff --git a/.changes/2.29.33.json b/.changes/2.29.x/2.29.33.json similarity index 100% rename from .changes/2.29.33.json rename to .changes/2.29.x/2.29.33.json diff --git a/.changes/2.29.34.json b/.changes/2.29.x/2.29.34.json similarity index 100% rename from .changes/2.29.34.json rename to .changes/2.29.x/2.29.34.json diff --git a/.changes/2.29.35.json b/.changes/2.29.x/2.29.35.json similarity index 100% rename from .changes/2.29.35.json rename to .changes/2.29.x/2.29.35.json diff --git a/.changes/2.29.36.json b/.changes/2.29.x/2.29.36.json similarity index 100% rename from .changes/2.29.36.json rename to .changes/2.29.x/2.29.36.json diff --git a/.changes/2.29.37.json b/.changes/2.29.x/2.29.37.json similarity index 100% rename from .changes/2.29.37.json rename to .changes/2.29.x/2.29.37.json diff --git a/.changes/2.29.38.json b/.changes/2.29.x/2.29.38.json similarity index 100% rename from .changes/2.29.38.json rename to .changes/2.29.x/2.29.38.json diff --git a/.changes/2.29.39.json b/.changes/2.29.x/2.29.39.json similarity index 100% rename from .changes/2.29.39.json rename to .changes/2.29.x/2.29.39.json diff --git a/.changes/2.29.4.json b/.changes/2.29.x/2.29.4.json similarity index 100% rename from .changes/2.29.4.json rename to .changes/2.29.x/2.29.4.json diff --git a/.changes/2.29.40.json b/.changes/2.29.x/2.29.40.json similarity index 100% rename from .changes/2.29.40.json rename to .changes/2.29.x/2.29.40.json diff --git a/.changes/2.29.41.json b/.changes/2.29.x/2.29.41.json similarity index 100% rename from .changes/2.29.41.json rename to .changes/2.29.x/2.29.41.json diff --git a/.changes/2.29.42.json b/.changes/2.29.x/2.29.42.json similarity index 100% rename from .changes/2.29.42.json rename to .changes/2.29.x/2.29.42.json diff --git a/.changes/2.29.43.json b/.changes/2.29.x/2.29.43.json similarity index 100% rename from .changes/2.29.43.json rename to .changes/2.29.x/2.29.43.json diff --git a/.changes/2.29.44.json b/.changes/2.29.x/2.29.44.json similarity index 100% rename from .changes/2.29.44.json rename to .changes/2.29.x/2.29.44.json diff --git a/.changes/2.29.45.json b/.changes/2.29.x/2.29.45.json similarity index 100% rename from .changes/2.29.45.json rename to .changes/2.29.x/2.29.45.json diff --git a/.changes/2.29.46.json b/.changes/2.29.x/2.29.46.json similarity index 100% rename from .changes/2.29.46.json rename to .changes/2.29.x/2.29.46.json diff --git a/.changes/2.29.47.json b/.changes/2.29.x/2.29.47.json similarity index 100% rename from .changes/2.29.47.json rename to .changes/2.29.x/2.29.47.json diff --git a/.changes/2.29.48.json b/.changes/2.29.x/2.29.48.json similarity index 100% rename from .changes/2.29.48.json rename to .changes/2.29.x/2.29.48.json diff --git a/.changes/2.29.49.json b/.changes/2.29.x/2.29.49.json similarity index 100% rename from .changes/2.29.49.json rename to .changes/2.29.x/2.29.49.json diff --git a/.changes/2.29.5.json b/.changes/2.29.x/2.29.5.json similarity index 100% rename from .changes/2.29.5.json rename to .changes/2.29.x/2.29.5.json diff --git a/.changes/2.29.50.json b/.changes/2.29.x/2.29.50.json similarity index 100% rename from .changes/2.29.50.json rename to .changes/2.29.x/2.29.50.json diff --git a/.changes/2.29.51.json b/.changes/2.29.x/2.29.51.json similarity index 100% rename from .changes/2.29.51.json rename to .changes/2.29.x/2.29.51.json diff --git a/.changes/2.29.52.json b/.changes/2.29.x/2.29.52.json similarity index 100% rename from .changes/2.29.52.json rename to .changes/2.29.x/2.29.52.json diff --git a/.changes/2.29.6.json b/.changes/2.29.x/2.29.6.json similarity index 100% rename from .changes/2.29.6.json rename to .changes/2.29.x/2.29.6.json diff --git a/.changes/2.29.7.json b/.changes/2.29.x/2.29.7.json similarity index 100% rename from .changes/2.29.7.json rename to .changes/2.29.x/2.29.7.json diff --git a/.changes/2.29.8.json b/.changes/2.29.x/2.29.8.json similarity index 100% rename from .changes/2.29.8.json rename to .changes/2.29.x/2.29.8.json diff --git a/.changes/2.29.9.json b/.changes/2.29.x/2.29.9.json similarity index 100% rename from .changes/2.29.9.json rename to .changes/2.29.x/2.29.9.json diff --git a/.changes/2.30.0.json b/.changes/2.30.0.json new file mode 100644 index 000000000000..314b4b54d9df --- /dev/null +++ b/.changes/2.30.0.json @@ -0,0 +1,78 @@ +{ + "version": "2.30.0", + "date": "2025-01-15", + "entries": [ + { + "type": "bugfix", + "category": "S3 Event Notification", + "contributor": "", + "description": "add static modifier to fromJson(InputStream) method of S3EventNotification" + }, + { + "type": "bugfix", + "category": "AWS SDK for Java v2 Migration Tool", + "contributor": "", + "description": "Transform the getter methods on the service model classes that return SdkBytes to return ByteBuffer to be compatible with v1 style getters" + }, + { + "type": "feature", + "category": "Agents for Amazon Bedrock Runtime", + "contributor": "", + "description": "Now supports streaming for inline agents." + }, + { + "type": "feature", + "category": "Amazon API Gateway", + "contributor": "", + "description": "Documentation updates for Amazon API Gateway" + }, + { + "type": "feature", + "category": "Amazon Cognito Identity", + "contributor": "", + "description": "corrects the dual-stack endpoint configuration" + }, + { + "type": "feature", + "category": "Amazon Simple Email Service", + "contributor": "", + "description": "This release introduces a new recommendation in Virtual Deliverability Manager Advisor, which detects elevated complaint rates for customer sending identities." + }, + { + "type": "feature", + "category": "Amazon Simple Storage Service", + "contributor": "", + "description": "This change enhances integrity protections for new SDK requests to S3. S3 SDKs now support the CRC64NVME checksum algorithm, full object checksums for multipart S3 objects, and new default integrity protections for S3 requests." + }, + { + "type": "feature", + "category": "Amazon WorkSpaces", + "contributor": "", + "description": "Added GeneralPurpose.4xlarge & GeneralPurpose.8xlarge ComputeTypes." + }, + { + "type": "feature", + "category": "Amazon WorkSpaces Thin Client", + "contributor": "", + "description": "Mark type in MaintenanceWindow as required." + }, + { + "type": "feature", + "category": "Partner Central Selling API", + "contributor": "", + "description": "Add Tagging support for ResourceSnapshotJob resources" + }, + { + "type": "feature", + "category": "Security Incident Response", + "contributor": "", + "description": "Increase minimum length of Threat Actor IP 'userAgent' to 1." + }, + { + "type": "feature", + "category": "AWS SDK for Java v2", + "contributor": "", + "description": "Updated endpoint and partition metadata." + } + ] +} \ No newline at end of file diff --git a/.changes/next-release/feature-AmazonS3-c101d4d.json b/.changes/next-release/feature-AmazonS3-c101d4d.json new file mode 100644 index 000000000000..cbffb8266946 --- /dev/null +++ b/.changes/next-release/feature-AmazonS3-c101d4d.json @@ -0,0 +1,6 @@ +{ + "type": "feature", + "category": "Amazon S3", + "contributor": "", + "description": "S3 client behavior is updated to always calculate a checksum by default for operations that support it (such as PutObject or UploadPart), or require it (such as DeleteObjects). The checksum algorithm used by default is CRC32. The S3 client attempts to validate response checksums for all S3 API operations that support checksums. However, if the SDK has not implemented the specified checksum algorithm then this validation is skipped. See [Dev Guide](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/s3-checksums.html) for more information" +} diff --git a/CHANGELOG.md b/CHANGELOG.md index f1f72bc25fb4..dff52ec237a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,1876 +1,50 @@ #### 👋 _Looking for changelogs for older versions? You can find them in the [changelogs](./changelogs) directory._ -# __2.29.52__ __2025-01-14__ -## __AWS SDK for Java v2__ - - ### Features - - Updated endpoint and partition metadata. - -## __Amazon GameLift__ - - ### Features - - Amazon GameLift releases a new game session placement feature: PriorityConfigurationOverride. You can now override how a game session queue prioritizes placement locations for a single StartGameSessionPlacement request. - -## __Amazon Route 53__ - - ### Features - - Amazon Route 53 now supports the Mexico (Central) Region (mx-central-1) for latency records, geoproximity records, and private DNS for Amazon VPCs in that region - -# __2.29.51__ __2025-01-13__ -## __AWS Artifact__ - - ### Features - - Support resolving regional API calls to partition's leader region endpoint. - -## __AWS SDK for Java v2__ - - ### Features - - Updated endpoint and partition metadata. - -## __Amazon Bedrock__ - - ### Features - - With this release, Bedrock Evaluation will now support latency-optimized inference for foundation models. - -## __Amazon Elastic Compute Cloud__ - - ### Features - - Add support for DisconnectOnSessionTimeout flag in CreateClientVpnEndpoint and ModifyClientVpnEndpoint requests and DescribeClientVpnEndpoints responses - -## __Amazon Transcribe Service__ - - ### Features - - This update provides tagging support for Transcribe's Call Analytics Jobs and Call Analytics Categories. - -## __Managed Streaming for Kafka Connect__ - - ### Features - - Support updating connector configuration via UpdateConnector API. Release Operations API to monitor the status of the connector operation. - -# __2.29.50__ __2025-01-10__ -## __AWS SDK for Java v2__ - - ### Features - - Updated endpoint and partition metadata. - -## __AWS Security Token Service__ - - ### Features - - Fixed typos in the descriptions. - -## __Amazon Redshift__ - - ### Features - - Additions to the PubliclyAccessible and Encrypted parameters clarifying what the defaults are. - -## __Amazon Security Lake__ - - ### Features - - Doc only update for ServiceName that fixes several customer-reported issues - -# __2.29.49__ __2025-01-09__ -## __AWS CodeBuild__ - - ### Features - - AWS CodeBuild Now Supports BuildBatch in Reserved Capacity and Lambda - -## __AWS Compute Optimizer__ - - ### Features - - This release expands AWS Compute Optimizer rightsizing recommendation support for Amazon EC2 Auto Scaling groups to include those with scaling policies and multiple instance types. - -## __AWS SDK for Java v2__ - - ### Features - - Updated endpoint and partition metadata. - -## __Firewall Management Service__ - - ### Features - - AWS Firewall Manager now lets you combine multiple resource tags using the logical AND operator or the logical OR operator. - -## __S3 Transfer Manager__ - - ### Bugfixes - - Fix an issue where if the request transformation function given to UploadDirectoryRequest throws an error when it is invoked, the error would be silently swallowed. Now, the completion future will be completed exceptionally if the function throws. - -# __2.29.48__ __2025-01-08__ -## __AWS SDK for Java v2__ - - ### Features - - Updated endpoint and partition metadata. - -## __Amazon Relational Database Service__ - - ### Features - - Updates Amazon RDS documentation to clarify the RestoreDBClusterToPointInTime description. - -## __Amazon Route 53__ - - ### Features - - Amazon Route 53 now supports the Asia Pacific (Thailand) Region (ap-southeast-7) for latency records, geoproximity records, and private DNS for Amazon VPCs in that region - -## __Amazon SageMaker Service__ - - ### Features - - Adds support for IPv6 for SageMaker HyperPod cluster nodes. - -# __2.29.47__ __2025-01-07__ -## __AWS CloudHSM V2__ - - ### Features - - Adds support to ModifyCluster for modifying a Cluster's Hsm Type. - -## __AWS SDK for Java v2__ - - ### Features - - Updated endpoint and partition metadata. - -## __Amazon DynamoDB__ - - ### Features - - This release makes Amazon DynamoDB point-in-time-recovery (PITR) to be configurable. You can set PITR recovery period for each table individually to between 1 and 35 days. - -## __EC2 Image Builder__ - - ### Features - - This release adds support for importing images from ISO disk files. Added new ImportDiskImage API operation. - -# __2.29.46__ __2025-01-06__ -## __AWS IoT Secure Tunneling__ - - ### Features - - Adds dualstack endpoint support for IoT Secure Tunneling - -## __AWS SDK for Java v2__ - - ### Features - - Updated endpoint and partition metadata. - -## __AWS Supply Chain__ - - ### Features - - Allow vanity DNS domain when creating a new ASC instance - -## __S3 Event Notifications__ - - ### Bugfixes - - Fixed a bug where null values are not handled properly when `S3EventNotification#fromJson` is invoked, throwing `IllegalArgumentException`. See [#5730](https://github.com/aws/aws-sdk-java-v2/issues/5730) - -# __2.29.45__ __2025-01-03__ -## __AWS SDK for Java v2__ - - ### Features - - Updated endpoint and partition metadata. - -## __Amazon EC2 Container Service__ - - ### Features - - Adding SDK reference examples for Amazon ECS operations. - -## __Amazon Route 53 Domains__ - - ### Features - - Doc only update for Route 53 Domains that fixes several customer-reported issues - -## __Amazon Simple Storage Service__ - - ### Features - - This change is only for updating the model regexp of CopySource which is not for validation but only for documentation and user guide change. - -# __2.29.44__ __2025-01-02__ -## __AWS AppSync__ - - ### Features - - Modify UpdateGraphQLAPI operation and flag authenticationType as required. - -## __AWS Elemental MediaConvert__ - - ### Features - - This release adds support for the AVC3 codec and fixes an alignment issue with Japanese vertical captions. - -## __AWS MediaConnect__ - - ### Features - - AWS Elemental MediaConnect now supports Content Quality Analysis for enhanced source stream monitoring. This enables you to track specific audio and video metrics in transport stream source flows, ensuring your content meets quality standards. - -## __AWS Organizations__ - - ### Features - - Added ALL_FEATURES_MIGRATION_ORGANIZATION_SIZE_LIMIT_EXCEEDED to ConstraintViolationException for the EnableAllFeatures operation. - -## __AWS SDK for Java v2__ - - ### Features - - Updated endpoint and partition metadata. - -## __Amazon GameLift__ - - ### Features - - Amazon GameLift releases a new game session shutdown feature. Use the Amazon GameLift console or AWS CLI to terminate an in-progress game session that's entered a bad state or is no longer needed. - -## __Amazon SageMaker Service__ - - ### Features - - Adding ETag information with Model Artifacts for Model Registry - -## __Amazon Simple Queue Service__ - - ### Features - - In-flight message typo fix from 20k to 120k. - -# __2.29.43__ __2024-12-27__ -## __Amazon Elastic Container Registry__ - - ### Features - - Restoring custom endpoint functionality for ECR - -## __Amazon Elastic Container Registry Public__ - - ### Features - - Restoring custom endpoint functionality for ECR Public - -# __2.29.42__ __2024-12-27__ -## __Amazon Relational Database Service__ - - ### Features - - Updates Amazon RDS documentation to correct various descriptions. - -# __2.29.41__ __2024-12-26__ -## __AWS Billing and Cost Management Pricing Calculator__ - - ### Features - - Added ConflictException to DeleteBillEstimate. - -## __AWS Network Firewall__ - - ### Features - - Dual-stack endpoints are now supported. - -## __AWS SDK for Java v2__ - - ### Features - - Updated endpoint and partition metadata. - -## __AWS SecurityHub__ - - ### Features - - Documentation updates for AWS Security Hub - -## __Amazon Elastic Container Registry__ - - ### Features - - Add support for Dualstack Endpoints - -# __2.29.40__ __2024-12-23__ -## __AWS Glue__ - - ### Features - - Add IncludeRoot parameters to GetCatalogs API to return root catalog. - -## __AWS SDK for Java v2__ - - ### Features - - Updated endpoint and partition metadata. - -## __Amazon Elastic Container Registry__ - - ### Features - - Documentation update for ECR GetAccountSetting and PutAccountSetting APIs. - -## __Amazon Elastic Container Registry Public__ - - ### Features - - Add support for Dualstack endpoints - -## __Amazon Elastic Kubernetes Service__ - - ### Features - - This release adds support for DescribeClusterVersions API that provides important information about Kubernetes versions along with end of support dates - -# __2.29.39__ __2024-12-20__ -## __AWS Billing__ - - ### Features - - Added new API's for defining and fetching Billing Views. - -## __AWS Cost Explorer Service__ - - ### Features - - Support for retrieving cost, usage, and forecast for billing view. - -## __AWS Outposts__ - - ### Features - - Add CS8365C as a supported power connector for Outpost sites. - -## __AWS SDK for Java v2__ - - ### Features - - Updated endpoint and partition metadata. - -## __Agents for Amazon Bedrock__ - - ### Features - - Support for custom user agent and max web pages crawled for web connector. Support app only credentials for SharePoint connector. Increase agents memory duration limit to 365 days. Support to specify max number of session summaries to include in agent invocation context. - -## __Agents for Amazon Bedrock Runtime__ - - ### Features - - bedrock agents now supports long term memory and performance configs. Invokeflow supports performance configs. RetrieveAndGenerate performance configs - -## __Amazon Connect Service__ - - ### Features - - This release supports adding NotAttributeCondition and Range to the RoutingCriteria object. - -## __Amazon DocumentDB with MongoDB compatibility__ - - ### Features - - Support AWS Secret Manager managed password for AWS DocumentDB instance-based cluster. - -## __Amazon Elastic Kubernetes Service__ - - ### Features - - This release expands the catalog of upgrade insight checks - -## __Amazon Macie 2__ - - ### Features - - This release adds support for identifying S3 general purpose buckets that exceed the Amazon Macie quota for preventative control monitoring. - -## __Amazon SageMaker Service__ - - ### Features - - This release adds support for c6i, m6i and r6i instance on SageMaker Hyperpod and trn1 instances in batch - -## __Data Automation for Amazon Bedrock__ - - ### Features - - Documentation update for Amazon Bedrock Data Automation - -## __Runtime for Amazon Bedrock Data Automation__ - - ### Features - - Documentation update for Amazon Bedrock Data Automation Runtime - -# __2.29.38__ __2024-12-19__ -## __AWS Elemental MediaConvert__ - - ### Features - - This release adds support for inserting timecode tracks into MP4 container outputs. - -## __AWS Elemental MediaLive__ - - ### Features - - MediaLive is releasing ListVersions api - -## __AWS SDK for Java v2__ - - ### Features - - Updated endpoint and partition metadata. - -## __AWS Systems Manager for SAP__ - - ### Features - - AWS Systems Manager for SAP added support for registration and discovery of distributed ABAP applications - -## __Amazon AppStream__ - - ### Features - - Added support for Rocky Linux 8 on Amazon AppStream 2.0 - -## __Amazon Q Connect__ - - ### Features - - Amazon Q in Connect enables agents to ask Q for assistance in multiple languages and Q will provide answers and recommended step-by-step guides in those languages. Qs default language is English (United States) and you can switch this by setting the locale configuration on the AI Agent. - -## __Amazon WorkSpaces__ - - ### Features - - Added AWS Global Accelerator (AGA) support for WorkSpaces Personal. - -# __2.29.37__ __2024-12-18__ -## __AWS Amplify__ - - ### Features - - Added WAF Configuration to Amplify Apps - -## __AWS Budgets__ - - ### Features - - Releasing minor partition endpoint updates - -## __AWS DataSync__ - - ### Features - - AWS DataSync introduces the ability to update attributes for in-cloud locations. - -## __AWS IoT__ - - ### Features - - Release connectivity status query API which is a dedicated high throughput(TPS) API to query a specific device's most recent connectivity state and metadata. - -## __AWS Resilience Hub__ - - ### Features - - AWS Resilience Hub now automatically detects already configured CloudWatch alarms and FIS experiments as part of the assessment process and returns the discovered resources in the corresponding list API responses. It also allows you to include or exclude test recommendations for an AppComponent. - -## __AWS SDK for Java v2__ - - ### Features - - Updated endpoint and partition metadata. - -## __AWS Transfer Family__ - - ### Features - - Added AS2 agreement configurations to control filename preservation and message signing enforcement. Added AS2 connector configuration to preserve content type from S3 objects. - -## __Amazon Connect Participant Service__ - - ### Features - - This release adds support for the GetAuthenticationUrl and CancelParticipantAuthentication APIs used for customer authentication within Amazon Connect chats. There are also minor updates to the GetAttachment API. - -## __Amazon Connect Service__ - - ### Features - - This release adds support for the UpdateParticipantAuthentication API used for customer authentication within Amazon Connect chats. - -## __Amazon QuickSight__ - - ### Features - - Add support for PerformanceConfiguration attribute to Dataset entity. Allow PerformanceConfiguration specification in CreateDataset and UpdateDataset APIs. - -## __AmazonMWAA__ - - ### Features - - Added support for Apache Airflow version 2.10.3 to MWAA. - -# __2.29.36__ __2024-12-17__ -## __AWS Account__ - - ### Features - - Update endpoint configuration. - -## __AWS Backup__ - - ### Features - - Add Support for Backup Indexing - -## __AWS Backup Search__ - - ### Features - - Add support for searching backups - -## __AWS Batch__ - - ### Features - - This feature allows AWS Batch on Amazon EKS to support configuration of Pod Annotations, overriding Namespace on which the Batch job's Pod runs on, and allows Subpath and Persistent Volume claim to be set for AWS Batch on Amazon EKS jobs. - -## __AWS Clean Rooms ML__ - - ### Features - - Add support for SQL compute configuration for StartAudienceGenerationJob API. - -## __AWS CodePipeline__ - - ### Features - - AWS CodePipeline V2 type pipelines now support Managed Compute Rule. - -## __AWS SDK for Java v2__ - - ### Features - - Added `AWS_METADATA_SERVICE_TIMEOUT` environment variable, System property and `metadata_service_timeout` Profile property to configure connection and read timeouts (in seconds) for both InstanceProfileCredentialsProvider and IMDS client. - - Updated endpoint and partition metadata. - -## __AWSMainframeModernization__ - - ### Features - - This release adds support for AWS Mainframe Modernization(M2) Service to allow specifying network type(ipv4, dual) for the environment instances. For dual network type, m2 environment applications will serve both IPv4 and IPv6 requests, whereas for ipv4 it will serve only IPv4 requests. - -## __Amazon CloudFront__ - - ### Features - - Adds support for OriginReadTimeout and OriginKeepaliveTimeout to create CloudFront Distributions with VPC Origins. - -## __Amazon EC2 Container Service__ - - ### Features - - Added support for enableFaultInjection task definition parameter which can be used to enable Fault Injection feature on ECS tasks. - -## __Synthetics__ - - ### Features - - Add support to toggle outbound IPv6 traffic on canaries connected to dualstack subnets. This behavior can be controlled via the new Ipv6AllowedForDualStack parameter of the VpcConfig input object in CreateCanary and UpdateCanary APIs. - -# __2.29.35__ __2024-12-16__ -## __AWS Cloud9__ - - ### Features - - Added information about Ubuntu 18.04 will be removed from the available imageIds for Cloud9 because Ubuntu 18.04 has ended standard support on May 31, 2023. - -## __AWS Elemental MediaLive__ - - ### Features - - AWS Elemental MediaLive adds three new features: MediaPackage v2 endpoint support for live stream delivery, KLV metadata passthrough in CMAF Ingest output groups, and Metadata Name Modifier in CMAF Ingest output groups for customizing metadata track names in output streams. - -## __AWS IoT Greengrass V2__ - - ### Features - - Add support for runtime in GetCoreDevice and ListCoreDevices APIs. - -## __Amazon Data Lifecycle Manager__ - - ### Features - - This release adds support for Local Zones in Amazon Data Lifecycle Manager EBS snapshot lifecycle policies. - -## __Amazon Elastic Compute Cloud__ - - ### Features - - This release adds support for EBS local snapshots in AWS Dedicated Local Zones, which allows you to store snapshots of EBS volumes locally in Dedicated Local Zones. - -## __Amazon Relational Database Service__ - - ### Features - - This release adds support for the "MYSQL_CACHING_SHA2_PASSWORD" enum value for RDS Proxy ClientPasswordAuthType. - -# __2.29.34__ __2024-12-13__ -## __AWS Cloud Map__ - - ### Features - - AWS Cloud Map now supports service-level attributes, allowing you to associate custom metadata directly with services. These attributes can be retrieved, updated, and deleted using the new GetServiceAttributes, UpdateServiceAttributes, and DeleteServiceAttributes API calls. - -## __AWS CloudHSM V2__ - - ### Features - - Add support for Dual-Stack hsm2m.medium clusters. The customers will now be able to create hsm2m.medium clusters having both IPv4 and IPv6 connection capabilities by specifying a new param called NetworkType=DUALSTACK during cluster creation. - -## __AWS MediaConnect__ - - ### Features - - AWS Elemental MediaConnect Gateway now supports Source Specific Multicast (SSM) for ingress bridges. This enables you to specify a source IP address in addition to a multicast IP when creating or updating an ingress bridge source. - -## __AWS Network Manager__ - - ### Features - - There was a sentence fragment in UpdateDirectConnectGatewayAttachment that was causing customer confusion as to whether it's an incomplete sentence or if it was a typo. Removed the fragment. - -## __AWS SDK for Java v2__ - - ### Features - - Updated endpoint and partition metadata. - -## __Amazon CloudWatch Logs__ - - ### Features - - Limit PutIntegration IntegrationName and ListIntegrations IntegrationNamePrefix parameters to 50 characters - -## __Amazon Elastic Compute Cloud__ - - ### Features - - This release adds GroupId to the response for DeleteSecurityGroup. - -## __Amazon Elastic Kubernetes Service__ - - ### Features - - Add NodeRepairConfig in CreateNodegroupRequest and UpdateNodegroupConfigRequest - -# __2.29.33__ __2024-12-12__ -## __AWS Database Migration Service__ - - ### Features - - Add parameters to support for kerberos authentication. Add parameter for disabling the Unicode source filter with PostgreSQL settings. Add parameter to use large integer value with Kinesis/Kafka settings. - -## __AWS Glue__ - - ### Features - - To support customer-managed encryption in Data Quality to allow customers encrypt data with their own KMS key, we will add a DataQualityEncryption field to the SecurityConfiguration API where customers can provide their KMS keys. - -## __AWS SDK for Java v2__ - - ### Features - - Updated endpoint and partition metadata. - -## __Amazon Connect Service__ - - ### Features - - Configure holidays and other overrides to hours of operation in advance. During contact handling, Amazon Connect automatically checks for overrides and provides customers with an appropriate flow path. After an override period passes call center automatically reverts to standard hours of operation. - -## __Amazon GuardDuty__ - - ### Features - - Improved descriptions for certain APIs. - -## __Amazon Route 53 Domains__ - - ### Features - - This release includes the following API updates: added the enumeration type RESTORE_DOMAIN to the OperationType; constrained the Price attribute to non-negative values; updated the LangCode to allow 2 or 3 alphabetical characters. - -# __2.29.32__ __2024-12-11__ -## __AWS Artifact__ - - ### Features - - Add support for listing active customer agreements for the calling AWS Account. - -## __AWS CloudTrail__ - - ### Features - - Doc-only updates for CloudTrail. - -## __AWS Control Catalog__ - - ### Features - - Minor documentation updates to the content of ImplementationDetails object part of the Control Catalog GetControl API - -## __AWS Migration Hub__ - - ### Features - - API and documentation updates for AWS MigrationHub related to adding support for listing migration task updates and associating, disassociating and listing source resources - -## __AWS SDK for Java v2__ - - ### Features - - Updated endpoint and partition metadata. - -## __Amazon Cognito Identity Provider__ - - ### Features - - Updated descriptions for some API operations and parameters, corrected some errors in Cognito user pools - -## __Amazon Simple Email Service__ - - ### Features - - Introduces support for multi-region endpoint. - -## __EMR Serverless__ - - ### Features - - This release adds support for accessing system profile logs in Lake Formation-enabled jobs. - -## __Timestream InfluxDB__ - - ### Features - - Adds networkType parameter to CreateDbInstance API which allows IPv6 support to the InfluxDB endpoint - -# __2.29.31__ __2024-12-10__ -## __AWS Billing and Cost Management Pricing Calculator__ - - ### Features - - Updated condition key inference from Workload Estimate, Bill Scenario, and Bill Estimate resources. Updated documentation links. - -## __AWS SDK for Java v2__ - - ### Features - - Updated endpoint and partition metadata. - -## __Amazon Aurora DSQL__ - - ### Features - - Doc only update to examples for DeleteMultiRegionClusters & CreateMultiRegionClusters - -## __Amazon Connect Service__ - - ### Features - - Add support for Push Notifications for Amazon Connect chat. With Push Notifications enabled an alert could be sent to customers about new messages even when they aren't actively using the mobile application. - -## __Amazon Interactive Video Service RealTime__ - - ### Features - - IVS Real-Time now offers customers the ability to customize thumbnails recording mode and interval for both Individual Participant Recording (IPR) and Server-Side Compositions (SSC). - -## __Amazon Simple Email Service__ - - ### Features - - Introduces support for creating DEED (Deterministic Easy-DKIM) identities. - -## __Application Auto Scaling__ - - ### Features - - Doc only update for AAS Predictive Scaling policy configuration API. - -## __FinSpace User Environment Management service__ - - ### Features - - Update KxCommandLineArgument value parameter regex to allow for spaces and semicolons - -# __2.29.30__ __2024-12-09__ -## __AWS AppSync__ - - ### Features - - Provides description of new Amazon Bedrock runtime datasource. - -## __AWS Elemental MediaLive__ - - ### Features - - H265 outputs now support disabling the deblocking filter. - -## __AWS SDK for Java v2__ - - ### Features - - Updated endpoint and partition metadata. - -## __Amazon Cognito Identity Provider__ - - ### Features - - Change `CustomDomainConfig` from a required to an optional parameter for the `UpdateUserPoolDomain` operation. - -## __Amazon EC2 Container Service__ - - ### Features - - This is a documentation only update to address various tickets for Amazon ECS. - -## __Amazon Elastic Compute Cloud__ - - ### Features - - This release includes a new API for modifying instance network-performance-options after launch. - -## __Amazon Keyspaces__ - - ### Features - - Amazon Keyspaces: adding the list of IAM actions required by the UpdateKeyspace API. - -## __Amazon WorkSpaces__ - - ### Features - - Added text to clarify case-sensitivity - -# __2.29.29__ __2024-12-04__ -## __Partner Central Selling API__ - - ### Features - - Introducing the preview of new partner central selling APIs designed to transform how AWS partners collaborate and co-sell with multiple partners. This enables multiple partners to seamlessly engage and jointly pursue customer opportunities, fostering a new era of collaborative selling. - -## __QBusiness__ - - ### Features - - This release removes the deprecated UserId and UserGroups fields from SearchRelevantContent api's request parameters. - -# __2.29.28__ __2024-12-04__ -## __AWS SDK for Java v2__ - - ### Bugfixes - - Add default retry predicates on top of user-provided ones - -## __AWSKendraFrontendService__ - - ### Features - - This release adds GenAI Index in Amazon Kendra for Retrieval Augmented Generation (RAG) and intelligent search. With the Kendra GenAI Index, customers get high retrieval accuracy powered by the latest information retrieval technologies and semantic models. - -## __Agents for Amazon Bedrock__ - - ### Features - - This release introduces the ability to generate SQL using natural language, through a new GenerateQuery API (with native integration into Knowledge Bases); ability to ingest and retrieve images through Bedrock Data Automation; and ability to create a Knowledge Base backed by Kendra GenAI Index. - -## __Agents for Amazon Bedrock Runtime__ - - ### Features - - This release introduces the ability to generate SQL using natural language, through a new GenerateQuery API (with native integration into Knowledge Bases); ability to ingest and retrieve images through Bedrock Data Automation; and ability to create a Knowledge Base backed by Kendra GenAI Index. - -## __Amazon Bedrock__ - - ### Features - - Introduced two APIs ListPromptRouters and GetPromptRouter for Intelligent Prompt Router feature. Add support for Bedrock Guardrails image content filter. New Bedrock Marketplace feature enabling a wider range of bedrock compatible models with self-hosted capability. - -## __Amazon Bedrock Runtime__ - - ### Features - - Added support for Intelligent Prompt Router in Invoke, InvokeStream, Converse and ConverseStream. Add support for Bedrock Guardrails image content filter. New Bedrock Marketplace feature enabling a wider range of bedrock compatible models with self-hosted capability. - -## __Amazon SageMaker Service__ - - ### Features - - Amazon SageMaker HyperPod launched task governance to help customers maximize accelerator utilization for model development and flexible training plans to meet training timelines and budget while reducing weeks of training time. AI apps from AWS partner is now available in SageMaker. - -## __DSQL__ - - ### Features - - Add IAM Token Generation Utility for DSQL - - Contributed by: [@APandher](https://github.com/APandher) - -## __Data Automation for Amazon Bedrock__ - - ### Features - - Release Bedrock Data Automation SDK - -## __Runtime for Amazon Bedrock Data Automation__ - - ### Features - - Release Bedrock Data Automation Runtime SDK - -## __Contributors__ -Special thanks to the following contributors to this release: - -[@APandher](https://github.com/APandher) -# __2.29.27__ __2024-12-03__ -## __Amazon Aurora DSQL__ - - ### Features - - Add IAM Token Generation Utility for DSQL. - -# __2.29.26__ __2024-12-03__ -## __AWS Glue__ - - ### Features - - This release includes(1)Zero-ETL integration to ingest data from 3P SaaS and DynamoDB to Redshift/Redlake (2)new properties on Connections to enable reuse; new connection APIs for retrieve/preview metadata (3)support of CRUD operations for Multi-catalog (4)support of automatic statistics collections - -## __AWS Lake Formation__ - - ### Features - - This release added two new LakeFormation Permissions (CREATE_CATALOG, SUPER_USER) and added Id field for CatalogResource. It also added new conditon and expression field. - -## __AWS SDK for Java v2__ - - ### Bugfixes - - Reverted PR https://github.com/aws/aws-sdk-java-v2/pull/5704, which modified all HTTP methods to include the request body entity, as it caused regression issues for some services. - -## __Agents for Amazon Bedrock__ - - ### Features - - Releasing SDK for Multi-Agent Collaboration. - -## __Agents for Amazon Bedrock Runtime__ - - ### Features - - Releasing SDK for multi agent collaboration - -## __Amazon Athena__ - - ### Features - - Add FEDERATED type to CreateDataCatalog. This creates Athena Data Catalog, AWS Lambda connector, and AWS Glue connection. Create/DeleteDataCatalog returns DataCatalog. Add Status, ConnectionType, and Error to DataCatalog and DataCatalogSummary. Add DeleteCatalogOnly to delete Athena Catalog only. - -## __Amazon Aurora DSQL__ - - ### Features - - Add new API operations for Amazon Aurora DSQL. Amazon Aurora DSQL is a serverless, distributed SQL database with virtually unlimited scale, highest availability, and zero infrastructure management. - -## __Amazon Bedrock__ - - ### Features - - Tagging support for Async Invoke resources. Added support for Distillation in CreateModelCustomizationJob API. Support for videoDataDeliveryEnabled flag in invocation logging. - -## __Amazon Bedrock Runtime__ - - ### Features - - Added support for Async Invoke Operations Start, List and Get. Support for invocation logs with `requestMetadata` field in Converse, ConverseStream, Invoke and InvokeStream. Video content blocks in Converse/ConverseStream accept raw bytes or S3 URI. - -## __Amazon CloudWatch__ - - ### Features - - Support for configuring AiOps investigation as alarm action - -## __Amazon DataZone__ - - ### Features - - Adds support for Connections, ProjectProfiles, and JobRuns APIs. Supports the new Lineage feature at GA. Adjusts optionality of a parameter for DataSource and SubscriptionTarget APIs which may adjust types in some clients. - -## __Amazon DynamoDB__ - - ### Features - - This change adds support for global tables with multi-Region strong consistency (in preview). The UpdateTable API now supports a new attribute MultiRegionConsistency to set consistency when creating global tables. The DescribeTable output now optionally includes the MultiRegionConsistency attribute. - -## __Amazon QuickSight__ - - ### Features - - This release includes API needed to support for Unstructured Data in Q in QuickSight Q&A (IDC). - -## __Amazon Redshift__ - - ### Features - - Adds support for Amazon Redshift RegisterNamespace and DeregisterNamespace APIs to share data to AWS Glue Data Catalog. - -## __Amazon S3 Tables__ - - ### Features - - Amazon S3 Tables deliver the first cloud object store with built-in open table format support, and the easiest way to store tabular data at scale. - -## __Amazon Simple Storage Service__ - - ### Features - - Amazon S3 Metadata stores object metadata in read-only, fully managed Apache Iceberg metadata tables that you can query. You can create metadata table configurations for S3 general purpose buckets. - -## __QApps__ - - ### Features - - Add support for 11 new plugins as action cards to help automate repetitive tasks and improve productivity. - -## __QBusiness__ - - ### Features - - Amazon Q Business now supports customization options for your web experience, 11 new Plugins, and QuickSight support. Amazon Q index allows software providers to enrich their native generative AI experiences with their customer's enterprise knowledge and user context spanning multiple applications. - -## __Redshift Serverless__ - - ### Features - - Adds support for the ListManagedWorkgroups API to get an overview of existing managed workgroups. - -# __2.29.25__ __2024-12-02__ -## __AWS End User Messaging Social__ - - ### Features - - Added support for passing role arn corresponding to the supported event destination - -## __AWS S3 Control__ - - ### Features - - It allows customers to pass CRC64NVME as a header in S3 Batch Operations copy requests - -## __AWS SDK for Java v2__ - - ### Features - - Updated endpoint and partition metadata. - -## __Amazon Bedrock Runtime__ - - ### Features - - Add an API parameter that allows customers to set performance configuration for invoking a model. - -# __2.29.24__ __2024-12-01__ -## __AWS CRT-based S3 client__ - - ### Bugfixes - - Fixed an issue where an error was not surfaced if request failed halfway for a GetObject operation. See [#5631](https://github.com/aws/aws-sdk-java-v2/issues/5631) - -## __AWS Clean Rooms Service__ - - ### Features - - This release allows customers and their partners to easily collaborate with data stored in Snowflake and Amazon Athena, without having to move or share their underlying data among collaborators. - -## __AWS Invoicing__ - - ### Features - - AWS Invoice Configuration allows you to receive separate AWS invoices based on your organizational needs. You can use the AWS SDKs to manage Invoice Units and programmatically fetch the information of the invoice receiver. - -## __AWS Organizations__ - - ### Features - - Add support for policy operations on the DECLARATIVE_POLICY_EC2 policy type. - -## __AWS S3 Control__ - - ### Features - - Amazon S3 introduces support for AWS Dedicated Local Zones - -## __AWS SecurityHub__ - - ### Features - - Add new Multi Domain Correlation findings. - -## __AWS Transfer Family__ - - ### Features - - AWS Transfer Family now offers Web apps that enables simple and secure access to data stored in Amazon S3. - -## __Agents for Amazon Bedrock__ - - ### Features - - This release introduces APIs to upload documents directly into a Knowledge Base - -## __Agents for Amazon Bedrock Runtime__ - - ### Features - - This release introduces a new Rerank API to leverage reranking models (with integration into Knowledge Bases); APIs to upload documents directly into Knowledge Base; RetrieveAndGenerateStream API for streaming response; Guardrails on Retrieve API; and ability to automatically generate filters - -## __Amazon Bedrock__ - - ### Features - - Add support for Knowledge Base Evaluations & LLM as a judge - -## __Amazon Chime SDK Voice__ - - ### Features - - This release adds supports for enterprises to integrate Amazon Connect with other voice systems. It supports directly transferring voice calls and metadata without using the public telephone network. It also supports real-time and post-call analytics. - -## __Amazon CloudWatch Logs__ - - ### Features - - Adds PutIntegration, GetIntegration, ListIntegrations and DeleteIntegration APIs. Adds QueryLanguage support to StartQuery, GetQueryResults, DescribeQueries, DescribeQueryDefinitions, and PutQueryDefinition APIs. - -## __Amazon Connect Customer Profiles__ - - ### Features - - This release introduces Event Trigger APIs as part of Amazon Connect Customer Profiles service. - -## __Amazon Connect Service__ - - ### Features - - Adds support for WhatsApp Business messaging, IVR call recording, enabling Contact Lens for existing on-premise contact centers and telephony platforms, and enabling telephony and IVR migration to Amazon Connect independent of their contact center agents. - -## __Amazon EC2 Container Service__ - - ### Features - - This release adds support for Container Insights with Enhanced Observability for Amazon ECS. - -## __Amazon Elastic Compute Cloud__ - - ### Features - - Adds support for declarative policies that allow you to enforce desired configuration across an AWS organization through configuring account attributes. Adds support for Allowed AMIs that allows you to limit the use of AMIs in AWS accounts. Adds support for connectivity over non-HTTP protocols. - -## __Amazon Elastic Kubernetes Service__ - - ### Features - - Added support for Auto Mode Clusters, Hybrid Nodes, and specifying computeTypes in the DescribeAddonVersions API. - -## __Amazon EventBridge__ - - ### Features - - Call private APIs by configuring Connections with VPC connectivity through PrivateLink and VPC Lattice - -## __Amazon FSx__ - - ### Features - - FSx API changes to support the public launch of the Amazon FSx Intelligent Tiering for OpenZFS storage class. - -## __Amazon GuardDuty__ - - ### Features - - Add new Multi Domain Correlation findings. - -## __Amazon MemoryDB__ - - ### Features - - Amazon MemoryDB SDK now supports all APIs for Multi-Region. Please refer to the updated Amazon MemoryDB public documentation for detailed information on API usage. - -## __Amazon OpenSearch Service__ - - ### Features - - This feature introduces support for CRUDL APIs, enabling the creation and management of Connected data sources. - -## __Amazon Q Connect__ - - ### Features - - This release adds following capabilities: Configuring safeguards via AIGuardrails for Q in Connect inferencing, and APIs to support Q&A self-service use cases - -## __Amazon Relational Database Service__ - - ### Features - - Amazon RDS supports CloudWatch Database Insights. You can use the SDK to create, modify, and describe the DatabaseInsightsMode for your DB instances and clusters. - -## __Amazon Simple Storage Service__ - - ### Features - - Amazon S3 introduces support for AWS Dedicated Local Zones - -## __Amazon VPC Lattice__ - - ### Features - - Lattice APIs that allow sharing and access of VPC resources across accounts. - -## __AmazonConnectCampaignServiceV2__ - - ### Features - - Amazon Connect Outbound Campaigns V2 / Features : Adds support for Event-Triggered Campaigns. - -## __EC2 Image Builder__ - - ### Features - - Added support for EC2 Image Builder's integration with AWS Marketplace for Marketplace components. - -## __Network Flow Monitor__ - - ### Features - - This release adds documentation for a new feature in Amazon CloudWatch called Network Flow Monitor. You can use Network Flow Monitor to get near real-time metrics, including retransmissions and data transferred, for your actual workloads. - -## __QBusiness__ - - ### Features - - Amazon Q Business now supports capabilities to extract insights and answer questions from visual elements embedded within documents, a browser extension for Google Chrome, Mozilla Firefox, and Microsoft Edge, and attachments across conversations. - -## __Security Incident Response__ - - ### Features - - AWS Security Incident Response is a purpose-built security incident solution designed to help customers prepare for, respond to, and recover from security incidents. - -# __2.29.23__ __2024-11-27__ -## __AWS Config__ - - ### Features - - AWS Config adds support for service-linked recorders, a new type of Config recorder managed by AWS services to record specific subsets of resource configuration data and functioning independently from customer managed AWS Config recorders. - -## __AWS SDK for Java v2__ - - ### Features - - Updated endpoint and partition metadata. - -## __Agents for Amazon Bedrock__ - - ### Features - - Add support for specifying embeddingDataType, either FLOAT32 or BINARY - -## __Amazon FSx__ - - ### Features - - This release adds EFA support to increase FSx for Lustre file systems' throughput performance to a single client instance. This can be done by specifying EfaEnabled=true at the time of creation of Persistent_2 file systems. - -## __CloudWatch Observability Admin Service__ - - ### Features - - Amazon CloudWatch Observability Admin adds the ability to audit telemetry configuration for AWS resources in customers AWS Accounts and Organizations. The release introduces new APIs to turn on/off the new experience, which supports discovering supported AWS resources and their state of telemetry. - -## __DynamoDB Enhanced Client__ - - ### Bugfixes - - Fix a bug where DurationAttributeConverter was considering any number past the decimal point as a nanosecond during deserialization - -# __2.29.22__ __2024-11-26__ -## __AWS SDK for Java v2__ - - ### Bugfixes - - Fix ApacheHttpClient's handling of request bodies on DELETE, GET, HEAD & OPTIONS requests - - Contributed by: [@Xtansia](https://github.com/Xtansia) - -## __Agents for Amazon Bedrock__ - - ### Features - - Custom Orchestration API release for AWSBedrockAgents. - -## __Agents for Amazon Bedrock Runtime__ - - ### Features - - Custom Orchestration and Streaming configurations API release for AWSBedrockAgents. - -## __Amazon Connect Service__ - - ### Features - - Enables access to ValueMap and ValueInteger types for SegmentAttributes and fixes deserialization bug for DescribeContactFlow in AmazonConnect Public API - -## __Amazon Elastic Compute Cloud__ - - ### Features - - Adds support for Time-based Copy for EBS Snapshots and Cross Region PrivateLink. Time-based Copy ensures that EBS Snapshots are copied within and across AWS Regions in a specified timeframe. Cross Region PrivateLink enables customers to connect to VPC endpoint services hosted in other AWS Regions. - -## __QApps__ - - ### Features - - Private sharing, file upload and data collection feature support for Q Apps - -## __Contributors__ -Special thanks to the following contributors to this release: - -[@Xtansia](https://github.com/Xtansia) -# __2.29.21__ __2024-11-25__ -## __AWS Direct Connect__ - - ### Features - - Update DescribeDirectConnectGatewayAssociations API to return associated core network information if a Direct Connect gateway is attached to a Cloud WAN core network. - -## __AWS Network Manager__ - - ### Features - - This release adds native Direct Connect integration on Cloud WAN enabling customers to directly attach their Direct Connect gateways to Cloud WAN without the need for an intermediate Transit Gateway. - -## __Amazon Simple Storage Service__ - - ### Features - - Amazon Simple Storage Service / Features: Add support for ETag based conditional writes in PutObject and CompleteMultiPartUpload APIs to prevent unintended object modifications. - -## __v2-migration OpenRewrite recipe__ - - ### Bugfixes - - This fixes a ConcurrentModificationException - just by replacing a HashMap with ConcurrentHashMap - - Contributed by: [@sk-br](https://github.com/sk-br) - -## __Contributors__ -Special thanks to the following contributors to this release: - -[@sk-br](https://github.com/sk-br) -# __2.29.20__ __2024-11-22__ -## __AWS Billing and Cost Management Pricing Calculator__ - - ### Features - - Initial release of the AWS Billing and Cost Management Pricing Calculator API. - -## __AWS Chatbot__ - - ### Features - - Adds support for programmatic management of custom actions and aliases which can be associated with channel configurations. - -## __AWS CodePipeline__ - - ### Features - - AWS CodePipeline V2 type pipelines now support ECRBuildAndPublish and InspectorScan actions. - -## __AWS Cost Explorer Service__ - - ### Features - - This release adds the Impact field(contains Contribution field) to the GetAnomalies API response under RootCause - -## __AWS Lambda__ - - ### Features - - Add ProvisionedPollerConfig to Lambda event-source-mapping API. - -## __AWS SDK for Java v2__ - - ### Features - - Updated endpoint and partition metadata. - -## __AWS Step Functions__ - - ### Features - - Add support for variables and JSONata in TestState, GetExecutionHistory, DescribeStateMachine, and DescribeStateMachineForExecution - -## __Agents for Amazon Bedrock Runtime__ - - ### Features - - InvokeInlineAgent API release to help invoke runtime agents without any dependency on preconfigured agents. - -## __Amazon Cognito Identity Provider__ - - ### Features - - Add support for users to sign up and sign in without passwords, using email and SMS OTPs and Passkeys. Add support for Passkeys based on WebAuthn. Add support for enhanced branding customization for hosted authentication pages with Amazon Cognito Managed Login. Add feature tiers with new pricing. - -## __Amazon Connect Service__ - - ### Features - - Amazon Connect Service Feature: Add APIs for Amazon Connect Email Channel - -## __Amazon EMR__ - - ### Features - - Advanced Scaling in Amazon EMR Managed Scaling - -## __Amazon Neptune Graph__ - - ### Features - - Add 4 new APIs to support new Export features, allowing Parquet and CSV formats. Add new arguments in Import APIs to support Parquet import. Add a new query "neptune.read" to run algorithms without loading data into database - -## __Amazon Omics__ - - ### Features - - This release adds support for resource policy based cross account S3 access to sequence store read sets. - -## __Amazon QuickSight__ - - ### Features - - This release includes: Update APIs to support Image, Layer Map, font customization, and Plugin Visual. Add Identity center related information in ListNamsespace API. Update API for restrictedFolder support in topics and add API for SearchTopics, Describe/Update DashboardsQA Configration. - -## __Amazon SageMaker Service__ - - ### Features - - This release adds APIs for new features for SageMaker endpoint to scale down to zero instances, native support for multi-adapter inference, and endpoint scaling improvements. - -## __Amazon Simple Email Service__ - - ### Features - - This release adds support for starting email contacts in your Amazon Connect instance as an email receiving action. - -## __Amazon Simple Notification Service__ - - ### Features - - ArchivePolicy attribute added to Archive and Replay feature - -## __Amazon WorkSpaces__ - - ### Features - - While integrating WSP-DCV rebrand, a few mentions were erroneously renamed from WSP to DCV. This release reverts those mentions back to WSP. - -## __Auto Scaling__ - - ### Features - - Now, Amazon EC2 Auto Scaling customers can enable target tracking policies to take quicker scaling decisions, enhancing their application performance and EC2 utilization. To get started, specify target tracking to monitor a metric that is available on Amazon CloudWatch at seconds-level interval. - -## __Elastic Load Balancing__ - - ### Features - - This release adds support for advertising trusted CA certificate names in associated trust stores. - -## __Inspector2__ - - ### Features - - Extend inspector2 service model to include ServiceQuotaExceededException. - -## __MailManager__ - - ### Features - - Added new "DeliverToQBusiness" rule action to MailManager RulesSet for ingesting email data into Amazon Q Business customer applications - -# __2.29.19__ __2024-11-21__ -## __AWS AppSync__ - - ### Features - - Add support for the Amazon Bedrock Runtime. - -## __AWS CloudTrail__ - - ### Features - - This release introduces new APIs for creating and managing CloudTrail Lake dashboards. It also adds support for resource-based policies on CloudTrail EventDataStore and Dashboard resource. - -## __AWS Cost Explorer Service__ - - ### Features - - This release introduces three new APIs that enable you to estimate the cost, coverage, and utilization impact of Savings Plans you plan to purchase. The three APIs are StartCommitmentPurchaseAnalysis, GetCommitmentPurchaseAnalysis, and ListCommitmentPurchaseAnalyses. - -## __AWS Health APIs and Notifications__ - - ### Features - - Adds metadata property to an AffectedEntity. - -## __AWS IoT__ - - ### Features - - General Availability (GA) release of AWS IoT Device Management - Commands, to trigger light-weight remote actions on targeted devices - -## __AWS IoT FleetWise__ - - ### Features - - AWS IoT FleetWise now includes campaign parameters to store and forward data, configure MQTT topic as a data destination, and collect diagnostic trouble code data. It includes APIs for network agnostic data collection using custom decoding interfaces, and monitoring the last known state of vehicles. - -## __AWS IoT Jobs Data Plane__ - - ### Features - - General Availability (GA) release of AWS IoT Device Management - Commands, to trigger light-weight remote actions on targeted devices - -## __AWS Lambda__ - - ### Features - - Adds support for metrics for event source mappings for AWS Lambda - -## __AWS Resilience Hub__ - - ### Features - - AWS Resilience Hub's new summary view visually represents applications' resilience through charts, enabling efficient resilience management. It provides a consolidated view of the app portfolio's resilience state and allows data export for custom stakeholder reporting. - -## __AWS SDK for Java v2__ - - ### Features - - Updated endpoint and partition metadata. - -## __AWS Systems Manager QuickSetup__ - - ### Features - - Add methods that retrieve details about deployed configurations: ListConfigurations, GetConfiguration - -## __AWS User Notifications__ - - ### Features - - This release adds support for AWS User Notifications. You can now configure and view notifications from AWS services in a central location using the AWS SDK. - -## __AWS User Notifications Contacts__ - - ### Features - - This release adds support for AWS User Notifications Contacts. You can now configure and view email contacts for AWS User Notifications using the AWS SDK. - -## __AWS X-Ray__ - - ### Features - - AWS X-Ray introduces Transaction Search APIs, enabling span ingestion into CloudWatch Logs for high-scale trace data indexing. These APIs support span-level queries, trace graph generation, and metric correlation for deeper application insights. - -## __Amazon API Gateway__ - - ### Features - - Added support for custom domain names for private APIs. - -## __Amazon CloudFront__ - - ### Features - - Adds support for Origin Selection between EMPv2 origins based on media quality score. - -## __Amazon CloudWatch Logs__ - - ### Features - - Adds "Create field indexes to improve query performance and reduce scan volume" and "Transform logs during ingestion". Updates documentation for "PutLogEvents with Entity". - -## __Amazon ElastiCache__ - - ### Features - - Added support to modify the engine type for existing ElastiCache Users and User Groups. Customers can now modify the engine type from redis to valkey. - -## __Amazon Elastic Compute Cloud__ - - ### Features - - Adds support for requesting future-dated Capacity Reservations with a minimum commitment duration, enabling IPAM for organizational units within AWS Organizations, reserving EC2 Capacity Blocks that start in 30 minutes, and extending the end date of existing Capacity Blocks. - -## __Amazon Simple Storage Service__ - - ### Features - - Add support for conditional deletes for the S3 DeleteObject and DeleteObjects APIs. Add support for write offset bytes option used to append to objects with the S3 PutObject API. - -## __Amazon Simple Systems Manager (SSM)__ - - ### Features - - Added support for providing high-level overviews of managed nodes and previewing the potential impact of a runbook execution. - -## __Application Auto Scaling__ - - ### Features - - Application Auto Scaling now supports Predictive Scaling to proactively increase the desired capacity ahead of predicted demand, ensuring improved availability and responsiveness for customers' applications. This feature is currently only made available for Amazon ECS Service scalable targets. - -## __Elastic Load Balancing__ - - ### Features - - This feature adds support for enabling zonal shift on cross-zone enabled Application Load Balancer, as well as modifying HTTP request and response headers. - -# __2.29.18__ __2024-11-20__ -## __AWS Application Discovery Service__ - - ### Features - - Add support to import data from commercially available discovery tools without file manipulation. - -## __AWS Compute Optimizer__ - - ### Features - - This release enables AWS Compute Optimizer to analyze and generate optimization recommendations for Amazon Aurora database instances. It also enables Compute Optimizer to identify idle Amazon EC2 instances, Amazon EBS volumes, Amazon ECS services running on Fargate, and Amazon RDS databases. - -## __AWS Control Tower__ - - ### Features - - Adds support for child enabled baselines which allow you to see the enabled baseline status for individual accounts. - -## __AWS Elemental MediaConvert__ - - ### Features - - This release adds the ability to reconfigure concurrent job settings for existing queues and create queues with custom concurrent job settings. - -## __AWS Elemental MediaPackage v2__ - - ### Features - - MediaPackage v2 now supports the Media Quality Confidence Score (MQCS) published from MediaLive. Customers can control input switching based on the MQCS and publishing HTTP Headers for the MQCS via the API. - -## __AWS Lambda__ - - ### Features - - Add Node 22.x (node22.x) support to AWS Lambda - -## __AWS SDK for Java v2__ - - ### Features - - Updated endpoint and partition metadata. - -## __Agents for Amazon Bedrock Runtime__ - - ### Features - - Releasing new Prompt Optimization to enhance your prompts for improved performance - -## __Amazon CloudFront__ - - ### Features - - Add support for gRPC, VPC origins, and Anycast IP Lists. Allow LoggingConfig IncludeCookies to be set regardless of whether the LoggingConfig is enabled. - -## __Amazon DataZone__ - - ### Features - - This release supports Metadata Enforcement Rule feature for Create Subscription Request action. - -## __Amazon EC2 Container Service__ - - ### Features - - This release adds support for the Availability Zone rebalancing feature on Amazon ECS. - -## __Amazon Elastic Compute Cloud__ - - ### Features - - With this release, customers can express their desire to launch instances only in an ODCR or ODCR group rather than OnDemand capacity. Customers can express their baseline instances' CPU-performance in attribute-based Instance Requirements configuration by referencing an instance family. - -## __Amazon Omics__ - - ### Features - - Enabling call caching feature that allows customers to reuse previously computed results from a set of completed tasks in a new workflow run. - -## __Amazon Recycle Bin__ - - ### Features - - This release adds support for exclusion tags for Recycle Bin, which allows you to identify resources that are to be excluded, or ignored, by a Region-level retention rule. - -## __Amazon Relational Database Service__ - - ### Features - - This release adds support for scale storage on the DB instance using a Blue/Green Deployment. - -## __Amazon Timestream Query__ - - ### Features - - This release adds support for Provisioning Timestream Compute Units (TCUs), a new feature that allows provisioning dedicated compute resources for your queries, providing predictable and cost-effective query performance. - -## __Amazon WorkSpaces__ - - ### Features - - Added support for Rocky Linux 8 on Amazon WorkSpaces Personal. - -## __Amazon WorkSpaces Web__ - - ### Features - - Added data protection settings with support for inline data redaction. - -## __Auto Scaling__ - - ### Features - - With this release, customers can prioritize launching instances into ODCRs using targets from ASGs or Launch Templates. Customers can express their baseline instances' CPU-performance in attribute-based Instance Requirements configuration by referencing an instance family that meets their needs. - -## __Cost Optimization Hub__ - - ### Features - - This release adds action type "Delete" to the GetRecommendation, ListRecommendations and ListRecommendationSummaries APIs to support new EBS and ECS recommendations with action type "Delete". - -## __Elastic Load Balancing__ - - ### Features - - This release adds support for configuring Load balancer Capacity Unit reservations - -# __2.29.17__ __2024-11-19__ -## __AWS B2B Data Interchange__ - - ### Features - - Add new X12 transactions sets and versions - -## __AWS Glue__ - - ### Features - - AWS Glue Data Catalog now enhances managed table optimizations of Apache Iceberg tables that can be accessed only from a specific Amazon Virtual Private Cloud (VPC) environment. - -## __AWS SDK for Java v2__ - - ### Features - - Updated endpoint and partition metadata. - -## __Amazon EC2 Container Service__ - - ### Features - - This release introduces support for configuring the version consistency feature for individual containers defined within a task definition. The configuration allows to specify whether ECS should resolve the container image tag specified in the container definition to an image digest. - -## __Amazon Elastic Compute Cloud__ - - ### Features - - This release adds VPC Block Public Access (VPC BPA), a new declarative control which blocks resources in VPCs and subnets that you own in a Region from reaching or being reached from the internet through internet gateways and egress-only internet gateways. - -## __Amazon Elastic File System__ - - ### Features - - Add support for the new parameters in EFS replication APIs - -## __Amazon Keyspaces__ - - ### Features - - Amazon Keyspaces Multi-Region Replication: Adds support to add new regions to multi and single-region keyspaces. - -## __Amazon WorkSpaces__ - - ### Features - - Releasing new ErrorCodes for Image Validation failure during CreateWorkspaceImage process - -## __AmazonMWAA__ - - ### Features - - Amazon MWAA now supports a new environment class, mw1.micro, ideal for workloads requiring fewer resources than mw1.small. This class supports a single instance of each Airflow component: Scheduler, Worker, and Webserver. - -## __Tax Settings__ - - ### Features - - Release Tax Inheritance APIs, Tax Exemption APIs, and functionality update for some existing Tax Registration APIs - -# __2.29.16__ __2024-11-18__ -## __AWS CloudFormation__ - - ### Features - - This release adds a new API, ListHookResults, that allows retrieving CloudFormation Hooks invocation results for hooks invoked during a create change set operation or Cloud Control API operation - -## __AWS IoT SiteWise__ - - ### Features - - The release introduces a generative AI Assistant in AWS IoT SiteWise. It includes: 1) InvokeAssistant API - Invoke the Assistant to get alarm summaries and ask questions. 2) Dataset APIs - Manage knowledge base configuration for the Assistant. 3) Portal APIs enhancement - Manage AI-aware dashboards. - -## __AWS RDS DataService__ - - ### Features - - Add support for the automatic pause/resume feature of Aurora Serverless v2. - -## __Amazon AppConfig__ - - ### Features - - AWS AppConfig has added a new extension action point, AT_DEPLOYMENT_TICK, to support third-party monitors to trigger an automatic rollback during a deployment. - -## __Amazon Connect Customer Profiles__ - - ### Features - - This release introduces Segmentation APIs and new Calculated Attribute Event Filters as part of Amazon Connect Customer Profiles service. - -## __Amazon Connect Service__ - - ### Features - - Adds CreateContactFlowVersion and ListContactFlowVersions APIs to create and view the versions of a contact flow. - -## __Amazon EC2 Container Service__ - - ### Features - - This release adds support for adding VPC Lattice configurations in ECS CreateService/UpdateService APIs. The configuration allows for associating VPC Lattice target groups with ECS Services. - -## __Amazon Elastic Compute Cloud__ - - ### Features - - Adding request and response elements for managed resources. - -## __Amazon Q Connect__ - - ### Features - - This release introduces MessageTemplate as a resource in Amazon Q in Connect, along with APIs to create, read, search, update, and delete MessageTemplate resources. - -## __Amazon Relational Database Service__ - - ### Features - - Add support for the automatic pause/resume feature of Aurora Serverless v2. - -## __Auto Scaling__ - - ### Features - - Amazon EC2 Auto Scaling now supports Amazon Application Recovery Controller (ARC) zonal shift and zonal autoshift to help you quickly recover an impaired application from failures in an Availability Zone (AZ). - -# __2.29.15__ __2024-11-15__ -## __AWS DataSync__ - - ### Features - - Doc-only updates and enhancements related to creating DataSync tasks and describing task executions. - -## __AWS IoT__ - - ### Features - - This release allows AWS IoT Core users to enrich MQTT messages with propagating attributes, to associate a thing to a connection, and to enable Online Certificate Status Protocol (OCSP) stapling for TLS X.509 server certificates through private endpoints. - -## __AWS Outposts__ - - ### Features - - You can now purchase AWS Outposts rack or server capacity for a 5-year term with one of the following payment options: All Upfront, Partial Upfront, and No Upfront. - -## __AWS SDK for Java v2__ - - ### Features - - Updated endpoint and partition metadata. - -## __Amazon CloudWatch__ - - ### Features - - Adds support for adding related Entity information to metrics ingested through PutMetricData. - -## __Amazon Elastic Compute Cloud__ - - ### Features - - Remove non-functional enum variants for FleetCapacityReservationUsageStrategy - -## __Amazon Pinpoint SMS Voice V2__ - - ### Features - - Use rule overrides to always allow or always block messages to specific phone numbers. Use message feedback to monitor if a customer interacts with your message. - -## __Amazon Polly__ - - ### Features - - Fixes PutLexicon usage example. - -## __Amazon Route 53 Resolver__ - - ### Features - - Route 53 Resolver DNS Firewall Advanced Rules allows you to monitor and block suspicious DNS traffic based on anomalies detected in the queries, such as DNS tunneling and Domain Generation Algorithms (DGAs). - -## __AmazonConnectCampaignServiceV2__ - - ### Features - - Added Amazon Connect Outbound Campaigns V2 SDK. - -# __2.29.14__ __2024-11-14__ -## __AWS SDK for Java v2__ - - ### Features - - Updated endpoint and partition metadata. - -## __Partner Central Selling API__ - - ### Features - - Announcing AWS Partner Central API for Selling: This service launch Introduces new APIs for co-selling opportunity management and related functions. Key features include notifications, a dynamic sandbox for testing, and streamlined validations. - -# __2.29.13__ __2024-11-14__ -## __AWS Cloud Control API__ - - ### Features - - Added support for CloudFormation Hooks with Cloud Control API. The GetResourceRequestStatus API response now includes an optional HooksProgressEvent and HooksRequestToken parameter for Hooks Invocation Progress as part of resource operation with Cloud Control. - -## __AWS Identity and Access Management__ - - ### Features - - This release includes support for five new APIs and changes to existing APIs that give AWS Organizations customers the ability to use temporary root credentials, targeted to member accounts in the organization. - -## __AWS IoT Wireless__ - - ### Features - - New FuotaTask resource type to enable logging for your FUOTA tasks. A ParticipatingGatewaysforMulticast parameter to choose the list of gateways to receive the multicast downlink message and the transmission interval between them. Descriptor field which will be sent to devices during FUOTA transfer. - -## __AWS License Manager User Subscriptions__ - - ### Features - - New and updated API operations to support License Included User-based Subscription of Microsoft Remote Desktop Services (RDS). - -## __AWS SDK for Java v2__ - - ### Features - - Updated endpoint and partition metadata. - -## __AWS Security Token Service__ - - ### Features - - This release introduces the new API 'AssumeRoot', which returns short-term credentials that you can use to perform privileged tasks. - -## __AWSDeadlineCloud__ - - ### Features - - Adds support for select GPU accelerated instance types when creating new service-managed fleets. - -## __Access Analyzer__ - - ### Features - - Expand analyzer configuration capabilities for unused access analyzers. Unused access analyzer configurations now support the ability to exclude accounts and resource tags from analysis providing more granular control over the scope of analysis. - -## __Amazon Interactive Video Service__ - - ### Features - - IVS now offers customers the ability to stream multitrack video to Channels. - -## __Amazon QuickSight__ - - ### Features - - This release adds APIs for Custom Permissions management in QuickSight, and APIs to support QuickSight Branding. - -## __Amazon Redshift__ - - ### Features - - Adds support for Amazon Redshift S3AccessGrants - -## __Amazon SageMaker Service__ - - ### Features - - Add support for Neuron instance types [ trn1/trn1n/inf2 ] on SageMaker Notebook Instances Platform. - -## __Amazon Simple Storage Service__ - - ### Features - - This release updates the ListBuckets API Reference documentation in support of the new 10,000 general purpose bucket default quota on all AWS accounts. To increase your bucket quota from 10,000 to up to 1 million buckets, simply request a quota increase via Service Quotas. - -## __Netty NIO HTTP Client__ - - ### Features - - Update Netty version to `4.1.115.Final`. - -## __Partner Central Selling API__ - - ### Features - - Announcing AWS Partner Central API for Selling: This service launch Introduces new APIs for co-selling opportunity management and related functions. Key features include notifications, a dynamic sandbox for testing, and streamlined validations. - -# __2.29.12__ __2024-11-13__ -## __AWS B2B Data Interchange__ - - ### Features - - This release adds a GenerateMapping API to allow generation of JSONata or XSLT transformer code based on input and output samples. - -## __AWS Billing__ - - ### Features - - Today, AWS announces the general availability of ListBillingViews API in the AWS SDKs, to enable AWS Billing Conductor (ABC) users to create proforma Cost and Usage Reports (CUR) programmatically. - -## __AWS CloudTrail__ - - ### Features - - This release adds a new API GenerateQuery that generates a query from a natural language prompt about the event data in your event data store. This operation uses generative artificial intelligence (generative AI) to produce a ready-to-use SQL query from the prompt. - -## __AWS Elemental MediaConvert__ - - ### Features - - This release adds support for ARN inputs in the Kantar credentials secrets name field and the MSPR field to the manifests for PlayReady DRM protected outputs. - -## __AWS Organizations__ - - ### Features - - Add support for policy operations on the Resource Control Polices. - -## __AWS SDK for Java v2__ - - ### Features - - Updated endpoint and partition metadata. - -## __Access Analyzer__ - - ### Features - - This release adds support for policy validation and external access findings for resource control policies (RCP). IAM Access Analyzer helps you author functional and secure RCPs and awareness that a RCP may restrict external access. Updated service API, documentation, and paginators. - -## __Amazon CloudWatch Application Signals__ - - ### Features - - Amazon CloudWatch Application Signals now supports creating Service Level Objectives with burn rates. Users can now create or update SLOs with burn rate configurations to meet their specific business requirements. - -## __Amazon CloudWatch Internet Monitor__ - - ### Features - - Add new query type Routing_Suggestions regarding querying interface - -## __Amazon DynamoDB__ - - ### Features - - This release includes supports the new WarmThroughput feature for DynamoDB. You can now provide an optional WarmThroughput attribute for CreateTable or UpdateTable APIs to pre-warm your table or global secondary index. You can also use DescribeTable to see the latest WarmThroughput value. - -## __Amazon Elastic Compute Cloud__ - - ### Features - - This release adds the source AMI details in DescribeImages API - -# __2.29.11__ __2024-11-12__ -## __AWS CodeBuild__ - - ### Features - - AWS CodeBuild now supports non-containerized Linux and Windows builds on Reserved Capacity. - -## __AWS Control Tower__ - - ### Features - - Added ResetEnabledControl API. - -## __AWS Fault Injection Simulator__ - - ### Features - - This release adds support for generating experiment reports with the experiment report configuration - -## __AWS SDK for Java v2__ - - ### Features - - Updated endpoint and partition metadata. - -## __Amazon GameLift__ - - ### Features - - Amazon GameLift releases container fleets support for general availability. Deploy Linux-based containerized game server software for hosting on Amazon GameLift. - -## __Amazon Relational Database Service__ - - ### Features - - Updates Amazon RDS documentation for Amazon RDS Extended Support for Amazon Aurora MySQL. - -## __Payment Cryptography Control Plane__ - - ### Features - - Updated ListAliases API with KeyArn filter. - -# __2.29.10__ __2024-11-11__ -## __AWS Lambda__ - - ### Features - - Add Python 3.13 (python3.13) support to AWS Lambda - -## __AWS Outposts__ - - ### Features - - This release updates StartCapacityTask to allow an active Outpost to be modified. It also adds a new API to list all running EC2 instances on the Outpost. - +# __2.30.0__ __2025-01-15__ ## __AWS SDK for Java v2__ - ### Features - Updated endpoint and partition metadata. +## __AWS SDK for Java v2 Migration Tool__ - ### Bugfixes - - SigV4: Add host header only when not already provided - - Contributed by: [@vsudilov](https://github.com/vsudilov) - -## __Amazon CloudFront__ - - ### Features - - No API changes from previous release. This release migrated the model to Smithy keeping all features unchanged. - -## __Amazon OpenSearch Service__ - - ### Features - - Adds Support for new AssociatePackages and DissociatePackages API in Amazon OpenSearch Service that allows association and dissociation operations to be carried out on multiple packages at the same time. - -## __Inspector2__ - - ### Features - - Adds support for filePath filter. - -## __Contributors__ -Special thanks to the following contributors to this release: - -[@vsudilov](https://github.com/vsudilov) -# __2.29.9__ __2024-11-08__ -## __AWS Batch__ - - ### Features - - This feature allows override LaunchTemplates to be specified in an AWS Batch Compute Environment. - -## __AWS Control Catalog__ - - ### Features - - AWS Control Catalog GetControl public API returns additional data in output, including Implementation and Parameters - -## __AWS Lambda__ - - ### Features - - This release adds support for using AWS KMS customer managed keys to encrypt AWS Lambda .zip deployment packages. - -## __AWS SDK for Java v2__ - - ### Features - - Updated endpoint and partition metadata. + - Transform the getter methods on the service model classes that return SdkBytes to return ByteBuffer to be compatible with v1 style getters ## __Agents for Amazon Bedrock Runtime__ - ### Features - - This release adds trace functionality to Bedrock Prompt Flows - -## __Amazon Chime SDK Media Pipelines__ - - ### Features - - Added support for Media Capture Pipeline and Media Concatenation Pipeline for customer managed server side encryption. Now Media Capture Pipeline can use IAM sink role to get access to KMS key and encrypt/decrypt recorded artifacts. KMS key ID can also be supplied with encryption context. - -## __Amazon Elastic Kubernetes Service__ - - ### Features - - Adds new error code `Ec2InstanceTypeDoesNotExist` for Amazon EKS managed node groups - -## __Amazon Kinesis Firehose__ - - ### Features - - Amazon Data Firehose / Features : Adds support for a new DeliveryStreamType, DatabaseAsSource. DatabaseAsSource hoses allow customers to stream CDC events from their RDS and Amazon EC2 hosted databases, running MySQL and PostgreSQL database engines, to Iceberg Table destinations. - -## __Amazon Pinpoint SMS Voice V2__ - - ### Features - - Added the RequiresAuthenticationTimestamp field to the RegistrationVersionStatusHistory data type. - -## __QBusiness__ - - ### Features - - Adds S3 path option to pass group member list for PutGroup API. - -# __2.29.8__ __2024-11-07__ -## __AWS Clean Rooms ML__ - - ### Features - - This release introduces support for Custom Models in AWS Clean Rooms ML. - -## __AWS Clean Rooms Service__ - - ### Features - - This release introduces support for Custom Models in AWS Clean Rooms ML. - -## __AWS Resource Explorer__ - - ### Features - - Add GetManagedView, ListManagedViews APIs. - -## __AWS SDK for Java v2__ - - ### Features - - Updated endpoint and partition metadata. - -## __Agents for Amazon Bedrock__ - - ### Features - - Add prompt support for chat template configuration and agent generative AI resource. Add support for configuring an optional guardrail in Prompt and Knowledge Base nodes in Prompt Flows. Add API to validate flow definition - -## __Amazon Bedrock Runtime__ - - ### Features - - Add Prompt management support to Bedrock runtime APIs: Converse, ConverseStream, InvokeModel, InvokeModelWithStreamingResponse - -## __Amazon QuickSight__ - - ### Features - - Add Client Credentials based OAuth support for Snowflake and Starburst - -## __Auto Scaling__ - - ### Features - - Auto Scaling groups now support the ability to strictly balance instances across Availability Zones by configuring the AvailabilityZoneDistribution parameter. If balanced-only is configured for a group, launches will always be attempted in the under scaled Availability Zone even if it is unhealthy. - -## __Synthetics__ - - ### Features - - Add support to toggle if a canary will automatically delete provisioned canary resources such as Lambda functions and layers when a canary is deleted. This behavior can be controlled via the new ProvisionedResourceCleanup property exposed in the CreateCanary and UpdateCanary APIs. - -# __2.29.7__ __2024-11-06__ -## __AWS CodeBuild__ - - ### Features - - AWS CodeBuild now adds additional compute types for reserved capacity fleet. - -## __AWS Lake Formation__ - - ### Features - - API changes for new named tag expressions feature. - -## __AWS S3 Control__ - - ### Features - - Fix ListStorageLensConfigurations and ListStorageLensGroups deserialization for Smithy SDKs. - -## __AWS SDK for Java v2__ - - ### Features - - Improve unmarshalling performance of all JSON protocols by unifying parsing with unmarshalling instead of doing one after the other. + - Now supports streaming for inline agents. - - ### Bugfixes - - Moves setting the default backoff strategies for all retry strategies to the builder as per the javadocs instead of only doing it in the `DefaultRetryStrategy` builder methods. - -## __Amazon GuardDuty__ - - ### Features - - GuardDuty RDS Protection expands support for Amazon Aurora PostgreSQL Limitless Databases. - -## __Amazon Verified Permissions__ - - ### Features - - Adding BatchGetPolicy API which supports the retrieval of multiple policies across multiple policy stores within a single request. - -## __QApps__ - - ### Features - - Introduces category apis in AmazonQApps. Web experience users use Categories to tag and filter library items. - -# __2.29.6__ __2024-11-01__ -## __AWS SDK for Java v2__ - - ### Features - - Updated endpoint and partition metadata. - - - ### Bugfixes - - Load Checksum classes of CRT from Classloader instead of direct references of CRT classes. - -## __Agents for Amazon Bedrock__ - - ### Features - - Amazon Bedrock Knowledge Bases now supports using application inference profiles to increase throughput and improve resilience. - -## __Amazon CloudWatch Logs__ - - ### Features - - This release introduces an improvement in PutLogEvents - -## __Amazon DocumentDB Elastic Clusters__ - - ### Features - - Amazon DocumentDB Elastic Clusters adds support for pending maintenance actions feature with APIs GetPendingMaintenanceAction, ListPendingMaintenanceActions and ApplyPendingMaintenanceAction - -## __Tax Settings__ - - ### Features - - Add support for supplemental tax registrations via these new APIs: PutSupplementalTaxRegistration, ListSupplementalTaxRegistrations, and DeleteSupplementalTaxRegistration. - -# __2.29.5__ __2024-10-31__ -## __AWS Batch__ - - ### Features - - Add `podNamespace` to `EksAttemptDetail` and `containerID` to `EksAttemptContainerDetail`. - -## __AWS Glue__ - - ### Features - - Add schedule support for AWS Glue column statistics - -## __AWS SDK for Java v2__ - - ### Features - - Updated endpoint and partition metadata. - - - ### Bugfixes - - Fix an issue where the SDK does not properly unmarshall an evenstream exception to the expected exception type. - -## __Amazon Prometheus Service__ +## __Amazon API Gateway__ - ### Features - - Added support for UpdateScraper API, to enable updating collector configuration in-place + - Documentation updates for Amazon API Gateway -## __Amazon SageMaker Service__ +## __Amazon Cognito Identity__ - ### Features - - SageMaker HyperPod adds scale-down at instance level via BatchDeleteClusterNodes API and group level via UpdateCluster API. SageMaker Training exposes secondary job status in TrainingJobSummary from ListTrainingJobs API. SageMaker now supports G6, G6e, P5e instances for HyperPod and Training. + - corrects the dual-stack endpoint configuration ## __Amazon Simple Email Service__ - ### Features - - This release enables customers to provide the email template content in the SESv2 SendEmail and SendBulkEmail APIs instead of the name or the ARN of a stored email template. - -## __Auto Scaling__ - - ### Features - - Adds bake time for Auto Scaling group Instance Refresh - -## __Elastic Load Balancing__ - - ### Features - - Add UDP support for AWS PrivateLink and dual-stack Network Load Balancers - -# __2.29.4__ __2024-10-30__ -## __AWS AppSync__ - - ### Features - - This release adds support for AppSync Event APIs. - -## __AWS DataSync__ - - ### Features - - AWS DataSync now supports Enhanced mode tasks. This task mode supports transfer of virtually unlimited numbers of objects with enhanced metrics, more detailed logs, and higher performance than Basic mode. This mode currently supports transfers between Amazon S3 locations. - -## __AWS Network Firewall__ - - ### Features - - AWS Network Firewall now supports configuring TCP idle timeout - -## __AWS SDK for Java v2__ - - ### Features - - Adds support for tracking feature usage in a new user agent metadata section and adds a base set of features. Where features were already a part of the user agent string, they are now converted to the new format where a feature is represented as a Base64 encoded string. For example, using DynamoDb Enhanced Client was previously recorded as 'hll/ddb-enh' in the user agent, but is now a 'd' in the business metrics metadata section 'm/'. - - Updated endpoint and partition metadata. - -## __Amazon Connect Service__ - - ### Features - - Updated the public documentation for the UserIdentityInfo object to accurately reflect the character limits for the FirstName and LastName fields, which were previously listed as 1-100 characters. - -## __Amazon EC2 Container Service__ - - ### Features - - This release supports service deployments and service revisions which provide a comprehensive view of your Amazon ECS service history. - -## __Amazon Elastic Compute Cloud__ - - ### Features - - This release adds two new capabilities to VPC Security Groups: Security Group VPC Associations and Shared Security Groups. - -## __Amazon Keyspaces__ - - ### Features - - Adds support for interacting with user-defined types (UDTs) through the following new operations: Create-Type, Delete-Type, List-Types, Get-Type. - -## __Amazon Location Service Maps V2__ - - ### Features - - Release of Amazon Location Maps API. Maps enables you to build digital maps that showcase your locations, visualize your data, and unlock insights to drive your business - -## __Amazon Location Service Places V2__ - - ### Features - - Release of Amazon Location Places API. Places enables you to quickly search, display, and filter places, businesses, and locations based on proximity, category, and name - -## __Amazon Location Service Routes V2__ - - ### Features - - Release of Amazon Location Routes API. Routes enables you to plan efficient routes and streamline deliveries by leveraging real-time traffic, vehicle restrictions, and turn-by-turn directions. - -## __Amazon OpenSearch Service__ - - ### Features - - This release introduces the new OpenSearch user interface (Dashboards), a new web-based application that can be associated with multiple data sources across OpenSearch managed clusters, serverless collections, and Amazon S3, so that users can gain a comprehensive insights in an unified interface. - -## __Amazon Redshift__ - - ### Features - - This release launches S3 event integrations to create and manage integrations from an Amazon S3 source into an Amazon Redshift database. - -## __Amazon Route 53__ - - ### Features - - This release adds support for TLSA, SSHFP, SVCB, and HTTPS record types. - -## __Amazon SageMaker Service__ - - ### Features - - Added support for Model Registry Staging construct. Users can define series of stages that models can progress through for model workflows and lifecycle. This simplifies tracking and managing models as they transition through development, testing, and production stages. - -## __Amazon WorkMail__ - - ### Features - - This release adds support for Multi-Factor Authentication (MFA) and Personal Access Tokens through integration with AWS IAM Identity Center. - -## __OpenSearch Service Serverless__ - - ### Features - - Neo Integration via IAM Identity Center (IdC) - -## __Redshift Serverless__ - - ### Features - - Adds and updates API members for the Redshift Serverless AI-driven scaling and optimization feature using the price-performance target setting. - -# __2.29.3__ __2024-10-29__ -## __AWS Clean Rooms Service__ - - ### Features - - This release adds the option for customers to configure analytics engine when creating a collaboration, and introduces the new SPARK analytics engine type in addition to maintaining the legacy CLEAN_ROOMS_SQL engine type. - -## __AWS IoT FleetWise__ - - ### Features - - Updated BatchCreateVehicle and BatchUpdateVehicle APIs: LimitExceededException has been added and the maximum number of vehicles in a batch has been set to 10 explicitly - -## __AWS SDK for Java v2__ - - ### Features - - Updated endpoint and partition metadata. - -## __Amazon Bedrock__ - - ### Features - - Update Application Inference Profile - -## __Amazon Bedrock Runtime__ - - ### Features - - Update Application Inference Profile - -## __Amazon CloudWatch Logs__ - - ### Features - - Added support for new optional baseline parameter in the UpdateAnomaly API. For UpdateAnomaly requests with baseline set to True, The anomaly behavior is then treated as baseline behavior. However, more severe occurrences of this behavior will still be reported as anomalies. - -## __Amazon SageMaker Service__ - - ### Features - - Adding `notebook-al2-v3` as allowed value to SageMaker NotebookInstance PlatformIdentifier attribute - -## __Redshift Data API Service__ - - ### Features - - Adding a new API GetStatementResultV2 that supports CSV formatted results from ExecuteStatement and BatchExecuteStatement calls. - -# __2.29.2__ __2024-10-28__ -## __AWS Elemental MediaPackage v2__ - - ### Features - - MediaPackage V2 Live to VOD Harvester is a MediaPackage V2 feature, which is used to export content from an origin endpoint to a S3 bucket. + - This release introduces a new recommendation in Virtual Deliverability Manager Advisor, which detects elevated complaint rates for customer sending identities. -## __AWS SDK for Java v2__ +## __Amazon Simple Storage Service__ - ### Features - - Updated endpoint and partition metadata. + - This change enhances integrity protections for new SDK requests to S3. S3 SDKs now support the CRC64NVME checksum algorithm, full object checksums for multipart S3 objects, and new default integrity protections for S3 requests. -## __AWS Storage Gateway__ +## __Amazon WorkSpaces__ - ### Features - - Documentation update: Amazon FSx File Gateway will no longer be available to new customers. + - Added GeneralPurpose.4xlarge & GeneralPurpose.8xlarge ComputeTypes. -## __Amazon OpenSearch Service__ +## __Amazon WorkSpaces Thin Client__ - ### Features - - Adds support for provisioning dedicated coordinator nodes. Coordinator nodes can be specified using the new NodeOptions parameter in ClusterConfig. + - Mark type in MaintenanceWindow as required. -## __Amazon Relational Database Service__ +## __Partner Central Selling API__ - ### Features - - This release adds support for Enhanced Monitoring and Performance Insights when restoring Aurora Limitless Database DB clusters. It also adds support for the os-upgrade pending maintenance action. + - Add Tagging support for ResourceSnapshotJob resources -## __Amazon S3__ +## __S3 Event Notification__ - ### Bugfixes - - Update the S3 client to correctly handle redirect cases for opt-in regions when crossRegionAccessEnabled is used. - -# __2.29.1__ __2024-10-25__ -## __AWS CodeBuild__ - - ### Features - - AWS CodeBuild now supports automatically retrying failed builds - -## __AWS Lambda__ - - ### Features - - Add TagsError field in Lambda GetFunctionResponse. The TagsError field contains details related to errors retrieving tags. - -## __AWS SDK for Java v2__ - - ### Features - - Updated endpoint and partition metadata. - -## __AWS Supply Chain__ - - ### Features - - API doc updates, and also support showing error message on a failed instance - -## __Agents for Amazon Bedrock__ - - ### Features - - Add support of new model types for Bedrock Agents, Adding inference profile support for Flows and Prompt Management, Adding new field to configure additional inference configurations for Flows and Prompt Management + - add static modifier to fromJson(InputStream) method of S3EventNotification -## __Amazon CloudWatch Logs__ - - ### Features - - Adding inferred token name for dynamic tokens in Anomalies. - -# __2.29.0__ __2024-10-24__ -## __AWS Parallel Computing Service__ - - ### Features - - Documentation update: added the default value of the Slurm configuration parameter scaleDownIdleTimeInSeconds to its description. - -## __AWS SDK for Java v2__ - - ### Features - - The SDK now defaults to Java built-in CRC32 and CRC32C(if it's Java 9+) implementations, resulting in improved performance. - - Updated endpoint and partition metadata. - - - ### Deprecations - - Deprecate internal checksum algorithm classes. - -## __Amazon AppConfig__ - - ### Features - - This release improves deployment safety by granting customers the ability to REVERT completed deployments, to the last known good state.In the StopDeployment API revert case the status of a COMPLETE deployment will be REVERTED. AppConfig only allows a revert within 72 hours of deployment completion. - -## __Amazon EC2 Container Service__ - - ### Features - - This release adds support for EBS volumes attached to Amazon ECS Windows tasks running on EC2 instances. - -## __Amazon Elastic Compute Cloud__ - - ### Features - - This release includes a new API to describe some details of the Amazon Machine Images (AMIs) that were used to launch EC2 instances, even if those AMIs are no longer available for use. - -## __QBusiness__ +## __Security Incident Response__ - ### Features - - Add a new field in chat response. This field can be used to support nested schemas in array fields + - Increase minimum length of Threat Actor IP 'userAgent' to 1. diff --git a/README.md b/README.md index 265782925d04..0486ae5541da 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ To automatically manage module versions (currently all modules have the same ver software.amazon.awssdk bom - 2.29.52 + 2.30.0 pom import @@ -85,12 +85,12 @@ Alternatively you can add dependencies for the specific services you use only: software.amazon.awssdk ec2 - 2.29.52 + 2.30.0 software.amazon.awssdk s3 - 2.29.52 + 2.30.0 ``` @@ -102,7 +102,7 @@ You can import the whole SDK into your project (includes *ALL* services). Please software.amazon.awssdk aws-sdk-java - 2.29.52 + 2.30.0 ``` diff --git a/archetypes/archetype-app-quickstart/pom.xml b/archetypes/archetype-app-quickstart/pom.xml index 0f9fb8717561..ff51292e33f9 100644 --- a/archetypes/archetype-app-quickstart/pom.xml +++ b/archetypes/archetype-app-quickstart/pom.xml @@ -20,7 +20,7 @@ archetypes software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 diff --git a/archetypes/archetype-lambda/pom.xml b/archetypes/archetype-lambda/pom.xml index 0fcb4f185daa..71fe5a3d9f57 100644 --- a/archetypes/archetype-lambda/pom.xml +++ b/archetypes/archetype-lambda/pom.xml @@ -20,7 +20,7 @@ archetypes software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 archetype-lambda diff --git a/archetypes/archetype-tools/pom.xml b/archetypes/archetype-tools/pom.xml index d2be3fe03e36..3d06e9e2cd5a 100644 --- a/archetypes/archetype-tools/pom.xml +++ b/archetypes/archetype-tools/pom.xml @@ -20,7 +20,7 @@ archetypes software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 diff --git a/archetypes/pom.xml b/archetypes/pom.xml index 31e1f4c0b903..d849e7ad3d4a 100644 --- a/archetypes/pom.xml +++ b/archetypes/pom.xml @@ -20,7 +20,7 @@ aws-sdk-java-pom software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 archetypes diff --git a/aws-sdk-java/pom.xml b/aws-sdk-java/pom.xml index 6d6d8f29de36..a196fece0049 100644 --- a/aws-sdk-java/pom.xml +++ b/aws-sdk-java/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk aws-sdk-java-pom - 2.29.52 + 2.30.0 ../pom.xml aws-sdk-java diff --git a/bom-internal/pom.xml b/bom-internal/pom.xml index 71fc190f78df..e83fd6b80444 100644 --- a/bom-internal/pom.xml +++ b/bom-internal/pom.xml @@ -20,7 +20,7 @@ aws-sdk-java-pom software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 diff --git a/bom/pom.xml b/bom/pom.xml index 55624807da84..07077639c480 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk aws-sdk-java-pom - 2.29.52 + 2.30.0 ../pom.xml bom diff --git a/bundle-logging-bridge/pom.xml b/bundle-logging-bridge/pom.xml index 8fab4b9b7547..2f00c0a7c315 100644 --- a/bundle-logging-bridge/pom.xml +++ b/bundle-logging-bridge/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk aws-sdk-java-pom - 2.29.52 + 2.30.0 bundle-logging-bridge jar diff --git a/bundle-sdk/pom.xml b/bundle-sdk/pom.xml index 1a92c67cada0..03cc864a7a9b 100644 --- a/bundle-sdk/pom.xml +++ b/bundle-sdk/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk aws-sdk-java-pom - 2.29.52 + 2.30.0 bundle-sdk jar diff --git a/bundle/pom.xml b/bundle/pom.xml index bd940e1040e7..0ec6187aa7e1 100644 --- a/bundle/pom.xml +++ b/bundle/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk aws-sdk-java-pom - 2.29.52 + 2.30.0 bundle jar diff --git a/changelogs/2.29.x-CHANGELOG.md b/changelogs/2.29.x-CHANGELOG.md new file mode 100644 index 000000000000..f1f72bc25fb4 --- /dev/null +++ b/changelogs/2.29.x-CHANGELOG.md @@ -0,0 +1,1876 @@ + #### 👋 _Looking for changelogs for older versions? You can find them in the [changelogs](./changelogs) directory._ +# __2.29.52__ __2025-01-14__ +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __Amazon GameLift__ + - ### Features + - Amazon GameLift releases a new game session placement feature: PriorityConfigurationOverride. You can now override how a game session queue prioritizes placement locations for a single StartGameSessionPlacement request. + +## __Amazon Route 53__ + - ### Features + - Amazon Route 53 now supports the Mexico (Central) Region (mx-central-1) for latency records, geoproximity records, and private DNS for Amazon VPCs in that region + +# __2.29.51__ __2025-01-13__ +## __AWS Artifact__ + - ### Features + - Support resolving regional API calls to partition's leader region endpoint. + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __Amazon Bedrock__ + - ### Features + - With this release, Bedrock Evaluation will now support latency-optimized inference for foundation models. + +## __Amazon Elastic Compute Cloud__ + - ### Features + - Add support for DisconnectOnSessionTimeout flag in CreateClientVpnEndpoint and ModifyClientVpnEndpoint requests and DescribeClientVpnEndpoints responses + +## __Amazon Transcribe Service__ + - ### Features + - This update provides tagging support for Transcribe's Call Analytics Jobs and Call Analytics Categories. + +## __Managed Streaming for Kafka Connect__ + - ### Features + - Support updating connector configuration via UpdateConnector API. Release Operations API to monitor the status of the connector operation. + +# __2.29.50__ __2025-01-10__ +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __AWS Security Token Service__ + - ### Features + - Fixed typos in the descriptions. + +## __Amazon Redshift__ + - ### Features + - Additions to the PubliclyAccessible and Encrypted parameters clarifying what the defaults are. + +## __Amazon Security Lake__ + - ### Features + - Doc only update for ServiceName that fixes several customer-reported issues + +# __2.29.49__ __2025-01-09__ +## __AWS CodeBuild__ + - ### Features + - AWS CodeBuild Now Supports BuildBatch in Reserved Capacity and Lambda + +## __AWS Compute Optimizer__ + - ### Features + - This release expands AWS Compute Optimizer rightsizing recommendation support for Amazon EC2 Auto Scaling groups to include those with scaling policies and multiple instance types. + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __Firewall Management Service__ + - ### Features + - AWS Firewall Manager now lets you combine multiple resource tags using the logical AND operator or the logical OR operator. + +## __S3 Transfer Manager__ + - ### Bugfixes + - Fix an issue where if the request transformation function given to UploadDirectoryRequest throws an error when it is invoked, the error would be silently swallowed. Now, the completion future will be completed exceptionally if the function throws. + +# __2.29.48__ __2025-01-08__ +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __Amazon Relational Database Service__ + - ### Features + - Updates Amazon RDS documentation to clarify the RestoreDBClusterToPointInTime description. + +## __Amazon Route 53__ + - ### Features + - Amazon Route 53 now supports the Asia Pacific (Thailand) Region (ap-southeast-7) for latency records, geoproximity records, and private DNS for Amazon VPCs in that region + +## __Amazon SageMaker Service__ + - ### Features + - Adds support for IPv6 for SageMaker HyperPod cluster nodes. + +# __2.29.47__ __2025-01-07__ +## __AWS CloudHSM V2__ + - ### Features + - Adds support to ModifyCluster for modifying a Cluster's Hsm Type. + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __Amazon DynamoDB__ + - ### Features + - This release makes Amazon DynamoDB point-in-time-recovery (PITR) to be configurable. You can set PITR recovery period for each table individually to between 1 and 35 days. + +## __EC2 Image Builder__ + - ### Features + - This release adds support for importing images from ISO disk files. Added new ImportDiskImage API operation. + +# __2.29.46__ __2025-01-06__ +## __AWS IoT Secure Tunneling__ + - ### Features + - Adds dualstack endpoint support for IoT Secure Tunneling + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __AWS Supply Chain__ + - ### Features + - Allow vanity DNS domain when creating a new ASC instance + +## __S3 Event Notifications__ + - ### Bugfixes + - Fixed a bug where null values are not handled properly when `S3EventNotification#fromJson` is invoked, throwing `IllegalArgumentException`. See [#5730](https://github.com/aws/aws-sdk-java-v2/issues/5730) + +# __2.29.45__ __2025-01-03__ +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __Amazon EC2 Container Service__ + - ### Features + - Adding SDK reference examples for Amazon ECS operations. + +## __Amazon Route 53 Domains__ + - ### Features + - Doc only update for Route 53 Domains that fixes several customer-reported issues + +## __Amazon Simple Storage Service__ + - ### Features + - This change is only for updating the model regexp of CopySource which is not for validation but only for documentation and user guide change. + +# __2.29.44__ __2025-01-02__ +## __AWS AppSync__ + - ### Features + - Modify UpdateGraphQLAPI operation and flag authenticationType as required. + +## __AWS Elemental MediaConvert__ + - ### Features + - This release adds support for the AVC3 codec and fixes an alignment issue with Japanese vertical captions. + +## __AWS MediaConnect__ + - ### Features + - AWS Elemental MediaConnect now supports Content Quality Analysis for enhanced source stream monitoring. This enables you to track specific audio and video metrics in transport stream source flows, ensuring your content meets quality standards. + +## __AWS Organizations__ + - ### Features + - Added ALL_FEATURES_MIGRATION_ORGANIZATION_SIZE_LIMIT_EXCEEDED to ConstraintViolationException for the EnableAllFeatures operation. + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __Amazon GameLift__ + - ### Features + - Amazon GameLift releases a new game session shutdown feature. Use the Amazon GameLift console or AWS CLI to terminate an in-progress game session that's entered a bad state or is no longer needed. + +## __Amazon SageMaker Service__ + - ### Features + - Adding ETag information with Model Artifacts for Model Registry + +## __Amazon Simple Queue Service__ + - ### Features + - In-flight message typo fix from 20k to 120k. + +# __2.29.43__ __2024-12-27__ +## __Amazon Elastic Container Registry__ + - ### Features + - Restoring custom endpoint functionality for ECR + +## __Amazon Elastic Container Registry Public__ + - ### Features + - Restoring custom endpoint functionality for ECR Public + +# __2.29.42__ __2024-12-27__ +## __Amazon Relational Database Service__ + - ### Features + - Updates Amazon RDS documentation to correct various descriptions. + +# __2.29.41__ __2024-12-26__ +## __AWS Billing and Cost Management Pricing Calculator__ + - ### Features + - Added ConflictException to DeleteBillEstimate. + +## __AWS Network Firewall__ + - ### Features + - Dual-stack endpoints are now supported. + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __AWS SecurityHub__ + - ### Features + - Documentation updates for AWS Security Hub + +## __Amazon Elastic Container Registry__ + - ### Features + - Add support for Dualstack Endpoints + +# __2.29.40__ __2024-12-23__ +## __AWS Glue__ + - ### Features + - Add IncludeRoot parameters to GetCatalogs API to return root catalog. + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __Amazon Elastic Container Registry__ + - ### Features + - Documentation update for ECR GetAccountSetting and PutAccountSetting APIs. + +## __Amazon Elastic Container Registry Public__ + - ### Features + - Add support for Dualstack endpoints + +## __Amazon Elastic Kubernetes Service__ + - ### Features + - This release adds support for DescribeClusterVersions API that provides important information about Kubernetes versions along with end of support dates + +# __2.29.39__ __2024-12-20__ +## __AWS Billing__ + - ### Features + - Added new API's for defining and fetching Billing Views. + +## __AWS Cost Explorer Service__ + - ### Features + - Support for retrieving cost, usage, and forecast for billing view. + +## __AWS Outposts__ + - ### Features + - Add CS8365C as a supported power connector for Outpost sites. + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __Agents for Amazon Bedrock__ + - ### Features + - Support for custom user agent and max web pages crawled for web connector. Support app only credentials for SharePoint connector. Increase agents memory duration limit to 365 days. Support to specify max number of session summaries to include in agent invocation context. + +## __Agents for Amazon Bedrock Runtime__ + - ### Features + - bedrock agents now supports long term memory and performance configs. Invokeflow supports performance configs. RetrieveAndGenerate performance configs + +## __Amazon Connect Service__ + - ### Features + - This release supports adding NotAttributeCondition and Range to the RoutingCriteria object. + +## __Amazon DocumentDB with MongoDB compatibility__ + - ### Features + - Support AWS Secret Manager managed password for AWS DocumentDB instance-based cluster. + +## __Amazon Elastic Kubernetes Service__ + - ### Features + - This release expands the catalog of upgrade insight checks + +## __Amazon Macie 2__ + - ### Features + - This release adds support for identifying S3 general purpose buckets that exceed the Amazon Macie quota for preventative control monitoring. + +## __Amazon SageMaker Service__ + - ### Features + - This release adds support for c6i, m6i and r6i instance on SageMaker Hyperpod and trn1 instances in batch + +## __Data Automation for Amazon Bedrock__ + - ### Features + - Documentation update for Amazon Bedrock Data Automation + +## __Runtime for Amazon Bedrock Data Automation__ + - ### Features + - Documentation update for Amazon Bedrock Data Automation Runtime + +# __2.29.38__ __2024-12-19__ +## __AWS Elemental MediaConvert__ + - ### Features + - This release adds support for inserting timecode tracks into MP4 container outputs. + +## __AWS Elemental MediaLive__ + - ### Features + - MediaLive is releasing ListVersions api + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __AWS Systems Manager for SAP__ + - ### Features + - AWS Systems Manager for SAP added support for registration and discovery of distributed ABAP applications + +## __Amazon AppStream__ + - ### Features + - Added support for Rocky Linux 8 on Amazon AppStream 2.0 + +## __Amazon Q Connect__ + - ### Features + - Amazon Q in Connect enables agents to ask Q for assistance in multiple languages and Q will provide answers and recommended step-by-step guides in those languages. Qs default language is English (United States) and you can switch this by setting the locale configuration on the AI Agent. + +## __Amazon WorkSpaces__ + - ### Features + - Added AWS Global Accelerator (AGA) support for WorkSpaces Personal. + +# __2.29.37__ __2024-12-18__ +## __AWS Amplify__ + - ### Features + - Added WAF Configuration to Amplify Apps + +## __AWS Budgets__ + - ### Features + - Releasing minor partition endpoint updates + +## __AWS DataSync__ + - ### Features + - AWS DataSync introduces the ability to update attributes for in-cloud locations. + +## __AWS IoT__ + - ### Features + - Release connectivity status query API which is a dedicated high throughput(TPS) API to query a specific device's most recent connectivity state and metadata. + +## __AWS Resilience Hub__ + - ### Features + - AWS Resilience Hub now automatically detects already configured CloudWatch alarms and FIS experiments as part of the assessment process and returns the discovered resources in the corresponding list API responses. It also allows you to include or exclude test recommendations for an AppComponent. + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __AWS Transfer Family__ + - ### Features + - Added AS2 agreement configurations to control filename preservation and message signing enforcement. Added AS2 connector configuration to preserve content type from S3 objects. + +## __Amazon Connect Participant Service__ + - ### Features + - This release adds support for the GetAuthenticationUrl and CancelParticipantAuthentication APIs used for customer authentication within Amazon Connect chats. There are also minor updates to the GetAttachment API. + +## __Amazon Connect Service__ + - ### Features + - This release adds support for the UpdateParticipantAuthentication API used for customer authentication within Amazon Connect chats. + +## __Amazon QuickSight__ + - ### Features + - Add support for PerformanceConfiguration attribute to Dataset entity. Allow PerformanceConfiguration specification in CreateDataset and UpdateDataset APIs. + +## __AmazonMWAA__ + - ### Features + - Added support for Apache Airflow version 2.10.3 to MWAA. + +# __2.29.36__ __2024-12-17__ +## __AWS Account__ + - ### Features + - Update endpoint configuration. + +## __AWS Backup__ + - ### Features + - Add Support for Backup Indexing + +## __AWS Backup Search__ + - ### Features + - Add support for searching backups + +## __AWS Batch__ + - ### Features + - This feature allows AWS Batch on Amazon EKS to support configuration of Pod Annotations, overriding Namespace on which the Batch job's Pod runs on, and allows Subpath and Persistent Volume claim to be set for AWS Batch on Amazon EKS jobs. + +## __AWS Clean Rooms ML__ + - ### Features + - Add support for SQL compute configuration for StartAudienceGenerationJob API. + +## __AWS CodePipeline__ + - ### Features + - AWS CodePipeline V2 type pipelines now support Managed Compute Rule. + +## __AWS SDK for Java v2__ + - ### Features + - Added `AWS_METADATA_SERVICE_TIMEOUT` environment variable, System property and `metadata_service_timeout` Profile property to configure connection and read timeouts (in seconds) for both InstanceProfileCredentialsProvider and IMDS client. + - Updated endpoint and partition metadata. + +## __AWSMainframeModernization__ + - ### Features + - This release adds support for AWS Mainframe Modernization(M2) Service to allow specifying network type(ipv4, dual) for the environment instances. For dual network type, m2 environment applications will serve both IPv4 and IPv6 requests, whereas for ipv4 it will serve only IPv4 requests. + +## __Amazon CloudFront__ + - ### Features + - Adds support for OriginReadTimeout and OriginKeepaliveTimeout to create CloudFront Distributions with VPC Origins. + +## __Amazon EC2 Container Service__ + - ### Features + - Added support for enableFaultInjection task definition parameter which can be used to enable Fault Injection feature on ECS tasks. + +## __Synthetics__ + - ### Features + - Add support to toggle outbound IPv6 traffic on canaries connected to dualstack subnets. This behavior can be controlled via the new Ipv6AllowedForDualStack parameter of the VpcConfig input object in CreateCanary and UpdateCanary APIs. + +# __2.29.35__ __2024-12-16__ +## __AWS Cloud9__ + - ### Features + - Added information about Ubuntu 18.04 will be removed from the available imageIds for Cloud9 because Ubuntu 18.04 has ended standard support on May 31, 2023. + +## __AWS Elemental MediaLive__ + - ### Features + - AWS Elemental MediaLive adds three new features: MediaPackage v2 endpoint support for live stream delivery, KLV metadata passthrough in CMAF Ingest output groups, and Metadata Name Modifier in CMAF Ingest output groups for customizing metadata track names in output streams. + +## __AWS IoT Greengrass V2__ + - ### Features + - Add support for runtime in GetCoreDevice and ListCoreDevices APIs. + +## __Amazon Data Lifecycle Manager__ + - ### Features + - This release adds support for Local Zones in Amazon Data Lifecycle Manager EBS snapshot lifecycle policies. + +## __Amazon Elastic Compute Cloud__ + - ### Features + - This release adds support for EBS local snapshots in AWS Dedicated Local Zones, which allows you to store snapshots of EBS volumes locally in Dedicated Local Zones. + +## __Amazon Relational Database Service__ + - ### Features + - This release adds support for the "MYSQL_CACHING_SHA2_PASSWORD" enum value for RDS Proxy ClientPasswordAuthType. + +# __2.29.34__ __2024-12-13__ +## __AWS Cloud Map__ + - ### Features + - AWS Cloud Map now supports service-level attributes, allowing you to associate custom metadata directly with services. These attributes can be retrieved, updated, and deleted using the new GetServiceAttributes, UpdateServiceAttributes, and DeleteServiceAttributes API calls. + +## __AWS CloudHSM V2__ + - ### Features + - Add support for Dual-Stack hsm2m.medium clusters. The customers will now be able to create hsm2m.medium clusters having both IPv4 and IPv6 connection capabilities by specifying a new param called NetworkType=DUALSTACK during cluster creation. + +## __AWS MediaConnect__ + - ### Features + - AWS Elemental MediaConnect Gateway now supports Source Specific Multicast (SSM) for ingress bridges. This enables you to specify a source IP address in addition to a multicast IP when creating or updating an ingress bridge source. + +## __AWS Network Manager__ + - ### Features + - There was a sentence fragment in UpdateDirectConnectGatewayAttachment that was causing customer confusion as to whether it's an incomplete sentence or if it was a typo. Removed the fragment. + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __Amazon CloudWatch Logs__ + - ### Features + - Limit PutIntegration IntegrationName and ListIntegrations IntegrationNamePrefix parameters to 50 characters + +## __Amazon Elastic Compute Cloud__ + - ### Features + - This release adds GroupId to the response for DeleteSecurityGroup. + +## __Amazon Elastic Kubernetes Service__ + - ### Features + - Add NodeRepairConfig in CreateNodegroupRequest and UpdateNodegroupConfigRequest + +# __2.29.33__ __2024-12-12__ +## __AWS Database Migration Service__ + - ### Features + - Add parameters to support for kerberos authentication. Add parameter for disabling the Unicode source filter with PostgreSQL settings. Add parameter to use large integer value with Kinesis/Kafka settings. + +## __AWS Glue__ + - ### Features + - To support customer-managed encryption in Data Quality to allow customers encrypt data with their own KMS key, we will add a DataQualityEncryption field to the SecurityConfiguration API where customers can provide their KMS keys. + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __Amazon Connect Service__ + - ### Features + - Configure holidays and other overrides to hours of operation in advance. During contact handling, Amazon Connect automatically checks for overrides and provides customers with an appropriate flow path. After an override period passes call center automatically reverts to standard hours of operation. + +## __Amazon GuardDuty__ + - ### Features + - Improved descriptions for certain APIs. + +## __Amazon Route 53 Domains__ + - ### Features + - This release includes the following API updates: added the enumeration type RESTORE_DOMAIN to the OperationType; constrained the Price attribute to non-negative values; updated the LangCode to allow 2 or 3 alphabetical characters. + +# __2.29.32__ __2024-12-11__ +## __AWS Artifact__ + - ### Features + - Add support for listing active customer agreements for the calling AWS Account. + +## __AWS CloudTrail__ + - ### Features + - Doc-only updates for CloudTrail. + +## __AWS Control Catalog__ + - ### Features + - Minor documentation updates to the content of ImplementationDetails object part of the Control Catalog GetControl API + +## __AWS Migration Hub__ + - ### Features + - API and documentation updates for AWS MigrationHub related to adding support for listing migration task updates and associating, disassociating and listing source resources + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __Amazon Cognito Identity Provider__ + - ### Features + - Updated descriptions for some API operations and parameters, corrected some errors in Cognito user pools + +## __Amazon Simple Email Service__ + - ### Features + - Introduces support for multi-region endpoint. + +## __EMR Serverless__ + - ### Features + - This release adds support for accessing system profile logs in Lake Formation-enabled jobs. + +## __Timestream InfluxDB__ + - ### Features + - Adds networkType parameter to CreateDbInstance API which allows IPv6 support to the InfluxDB endpoint + +# __2.29.31__ __2024-12-10__ +## __AWS Billing and Cost Management Pricing Calculator__ + - ### Features + - Updated condition key inference from Workload Estimate, Bill Scenario, and Bill Estimate resources. Updated documentation links. + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __Amazon Aurora DSQL__ + - ### Features + - Doc only update to examples for DeleteMultiRegionClusters & CreateMultiRegionClusters + +## __Amazon Connect Service__ + - ### Features + - Add support for Push Notifications for Amazon Connect chat. With Push Notifications enabled an alert could be sent to customers about new messages even when they aren't actively using the mobile application. + +## __Amazon Interactive Video Service RealTime__ + - ### Features + - IVS Real-Time now offers customers the ability to customize thumbnails recording mode and interval for both Individual Participant Recording (IPR) and Server-Side Compositions (SSC). + +## __Amazon Simple Email Service__ + - ### Features + - Introduces support for creating DEED (Deterministic Easy-DKIM) identities. + +## __Application Auto Scaling__ + - ### Features + - Doc only update for AAS Predictive Scaling policy configuration API. + +## __FinSpace User Environment Management service__ + - ### Features + - Update KxCommandLineArgument value parameter regex to allow for spaces and semicolons + +# __2.29.30__ __2024-12-09__ +## __AWS AppSync__ + - ### Features + - Provides description of new Amazon Bedrock runtime datasource. + +## __AWS Elemental MediaLive__ + - ### Features + - H265 outputs now support disabling the deblocking filter. + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __Amazon Cognito Identity Provider__ + - ### Features + - Change `CustomDomainConfig` from a required to an optional parameter for the `UpdateUserPoolDomain` operation. + +## __Amazon EC2 Container Service__ + - ### Features + - This is a documentation only update to address various tickets for Amazon ECS. + +## __Amazon Elastic Compute Cloud__ + - ### Features + - This release includes a new API for modifying instance network-performance-options after launch. + +## __Amazon Keyspaces__ + - ### Features + - Amazon Keyspaces: adding the list of IAM actions required by the UpdateKeyspace API. + +## __Amazon WorkSpaces__ + - ### Features + - Added text to clarify case-sensitivity + +# __2.29.29__ __2024-12-04__ +## __Partner Central Selling API__ + - ### Features + - Introducing the preview of new partner central selling APIs designed to transform how AWS partners collaborate and co-sell with multiple partners. This enables multiple partners to seamlessly engage and jointly pursue customer opportunities, fostering a new era of collaborative selling. + +## __QBusiness__ + - ### Features + - This release removes the deprecated UserId and UserGroups fields from SearchRelevantContent api's request parameters. + +# __2.29.28__ __2024-12-04__ +## __AWS SDK for Java v2__ + - ### Bugfixes + - Add default retry predicates on top of user-provided ones + +## __AWSKendraFrontendService__ + - ### Features + - This release adds GenAI Index in Amazon Kendra for Retrieval Augmented Generation (RAG) and intelligent search. With the Kendra GenAI Index, customers get high retrieval accuracy powered by the latest information retrieval technologies and semantic models. + +## __Agents for Amazon Bedrock__ + - ### Features + - This release introduces the ability to generate SQL using natural language, through a new GenerateQuery API (with native integration into Knowledge Bases); ability to ingest and retrieve images through Bedrock Data Automation; and ability to create a Knowledge Base backed by Kendra GenAI Index. + +## __Agents for Amazon Bedrock Runtime__ + - ### Features + - This release introduces the ability to generate SQL using natural language, through a new GenerateQuery API (with native integration into Knowledge Bases); ability to ingest and retrieve images through Bedrock Data Automation; and ability to create a Knowledge Base backed by Kendra GenAI Index. + +## __Amazon Bedrock__ + - ### Features + - Introduced two APIs ListPromptRouters and GetPromptRouter for Intelligent Prompt Router feature. Add support for Bedrock Guardrails image content filter. New Bedrock Marketplace feature enabling a wider range of bedrock compatible models with self-hosted capability. + +## __Amazon Bedrock Runtime__ + - ### Features + - Added support for Intelligent Prompt Router in Invoke, InvokeStream, Converse and ConverseStream. Add support for Bedrock Guardrails image content filter. New Bedrock Marketplace feature enabling a wider range of bedrock compatible models with self-hosted capability. + +## __Amazon SageMaker Service__ + - ### Features + - Amazon SageMaker HyperPod launched task governance to help customers maximize accelerator utilization for model development and flexible training plans to meet training timelines and budget while reducing weeks of training time. AI apps from AWS partner is now available in SageMaker. + +## __DSQL__ + - ### Features + - Add IAM Token Generation Utility for DSQL + - Contributed by: [@APandher](https://github.com/APandher) + +## __Data Automation for Amazon Bedrock__ + - ### Features + - Release Bedrock Data Automation SDK + +## __Runtime for Amazon Bedrock Data Automation__ + - ### Features + - Release Bedrock Data Automation Runtime SDK + +## __Contributors__ +Special thanks to the following contributors to this release: + +[@APandher](https://github.com/APandher) +# __2.29.27__ __2024-12-03__ +## __Amazon Aurora DSQL__ + - ### Features + - Add IAM Token Generation Utility for DSQL. + +# __2.29.26__ __2024-12-03__ +## __AWS Glue__ + - ### Features + - This release includes(1)Zero-ETL integration to ingest data from 3P SaaS and DynamoDB to Redshift/Redlake (2)new properties on Connections to enable reuse; new connection APIs for retrieve/preview metadata (3)support of CRUD operations for Multi-catalog (4)support of automatic statistics collections + +## __AWS Lake Formation__ + - ### Features + - This release added two new LakeFormation Permissions (CREATE_CATALOG, SUPER_USER) and added Id field for CatalogResource. It also added new conditon and expression field. + +## __AWS SDK for Java v2__ + - ### Bugfixes + - Reverted PR https://github.com/aws/aws-sdk-java-v2/pull/5704, which modified all HTTP methods to include the request body entity, as it caused regression issues for some services. + +## __Agents for Amazon Bedrock__ + - ### Features + - Releasing SDK for Multi-Agent Collaboration. + +## __Agents for Amazon Bedrock Runtime__ + - ### Features + - Releasing SDK for multi agent collaboration + +## __Amazon Athena__ + - ### Features + - Add FEDERATED type to CreateDataCatalog. This creates Athena Data Catalog, AWS Lambda connector, and AWS Glue connection. Create/DeleteDataCatalog returns DataCatalog. Add Status, ConnectionType, and Error to DataCatalog and DataCatalogSummary. Add DeleteCatalogOnly to delete Athena Catalog only. + +## __Amazon Aurora DSQL__ + - ### Features + - Add new API operations for Amazon Aurora DSQL. Amazon Aurora DSQL is a serverless, distributed SQL database with virtually unlimited scale, highest availability, and zero infrastructure management. + +## __Amazon Bedrock__ + - ### Features + - Tagging support for Async Invoke resources. Added support for Distillation in CreateModelCustomizationJob API. Support for videoDataDeliveryEnabled flag in invocation logging. + +## __Amazon Bedrock Runtime__ + - ### Features + - Added support for Async Invoke Operations Start, List and Get. Support for invocation logs with `requestMetadata` field in Converse, ConverseStream, Invoke and InvokeStream. Video content blocks in Converse/ConverseStream accept raw bytes or S3 URI. + +## __Amazon CloudWatch__ + - ### Features + - Support for configuring AiOps investigation as alarm action + +## __Amazon DataZone__ + - ### Features + - Adds support for Connections, ProjectProfiles, and JobRuns APIs. Supports the new Lineage feature at GA. Adjusts optionality of a parameter for DataSource and SubscriptionTarget APIs which may adjust types in some clients. + +## __Amazon DynamoDB__ + - ### Features + - This change adds support for global tables with multi-Region strong consistency (in preview). The UpdateTable API now supports a new attribute MultiRegionConsistency to set consistency when creating global tables. The DescribeTable output now optionally includes the MultiRegionConsistency attribute. + +## __Amazon QuickSight__ + - ### Features + - This release includes API needed to support for Unstructured Data in Q in QuickSight Q&A (IDC). + +## __Amazon Redshift__ + - ### Features + - Adds support for Amazon Redshift RegisterNamespace and DeregisterNamespace APIs to share data to AWS Glue Data Catalog. + +## __Amazon S3 Tables__ + - ### Features + - Amazon S3 Tables deliver the first cloud object store with built-in open table format support, and the easiest way to store tabular data at scale. + +## __Amazon Simple Storage Service__ + - ### Features + - Amazon S3 Metadata stores object metadata in read-only, fully managed Apache Iceberg metadata tables that you can query. You can create metadata table configurations for S3 general purpose buckets. + +## __QApps__ + - ### Features + - Add support for 11 new plugins as action cards to help automate repetitive tasks and improve productivity. + +## __QBusiness__ + - ### Features + - Amazon Q Business now supports customization options for your web experience, 11 new Plugins, and QuickSight support. Amazon Q index allows software providers to enrich their native generative AI experiences with their customer's enterprise knowledge and user context spanning multiple applications. + +## __Redshift Serverless__ + - ### Features + - Adds support for the ListManagedWorkgroups API to get an overview of existing managed workgroups. + +# __2.29.25__ __2024-12-02__ +## __AWS End User Messaging Social__ + - ### Features + - Added support for passing role arn corresponding to the supported event destination + +## __AWS S3 Control__ + - ### Features + - It allows customers to pass CRC64NVME as a header in S3 Batch Operations copy requests + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __Amazon Bedrock Runtime__ + - ### Features + - Add an API parameter that allows customers to set performance configuration for invoking a model. + +# __2.29.24__ __2024-12-01__ +## __AWS CRT-based S3 client__ + - ### Bugfixes + - Fixed an issue where an error was not surfaced if request failed halfway for a GetObject operation. See [#5631](https://github.com/aws/aws-sdk-java-v2/issues/5631) + +## __AWS Clean Rooms Service__ + - ### Features + - This release allows customers and their partners to easily collaborate with data stored in Snowflake and Amazon Athena, without having to move or share their underlying data among collaborators. + +## __AWS Invoicing__ + - ### Features + - AWS Invoice Configuration allows you to receive separate AWS invoices based on your organizational needs. You can use the AWS SDKs to manage Invoice Units and programmatically fetch the information of the invoice receiver. + +## __AWS Organizations__ + - ### Features + - Add support for policy operations on the DECLARATIVE_POLICY_EC2 policy type. + +## __AWS S3 Control__ + - ### Features + - Amazon S3 introduces support for AWS Dedicated Local Zones + +## __AWS SecurityHub__ + - ### Features + - Add new Multi Domain Correlation findings. + +## __AWS Transfer Family__ + - ### Features + - AWS Transfer Family now offers Web apps that enables simple and secure access to data stored in Amazon S3. + +## __Agents for Amazon Bedrock__ + - ### Features + - This release introduces APIs to upload documents directly into a Knowledge Base + +## __Agents for Amazon Bedrock Runtime__ + - ### Features + - This release introduces a new Rerank API to leverage reranking models (with integration into Knowledge Bases); APIs to upload documents directly into Knowledge Base; RetrieveAndGenerateStream API for streaming response; Guardrails on Retrieve API; and ability to automatically generate filters + +## __Amazon Bedrock__ + - ### Features + - Add support for Knowledge Base Evaluations & LLM as a judge + +## __Amazon Chime SDK Voice__ + - ### Features + - This release adds supports for enterprises to integrate Amazon Connect with other voice systems. It supports directly transferring voice calls and metadata without using the public telephone network. It also supports real-time and post-call analytics. + +## __Amazon CloudWatch Logs__ + - ### Features + - Adds PutIntegration, GetIntegration, ListIntegrations and DeleteIntegration APIs. Adds QueryLanguage support to StartQuery, GetQueryResults, DescribeQueries, DescribeQueryDefinitions, and PutQueryDefinition APIs. + +## __Amazon Connect Customer Profiles__ + - ### Features + - This release introduces Event Trigger APIs as part of Amazon Connect Customer Profiles service. + +## __Amazon Connect Service__ + - ### Features + - Adds support for WhatsApp Business messaging, IVR call recording, enabling Contact Lens for existing on-premise contact centers and telephony platforms, and enabling telephony and IVR migration to Amazon Connect independent of their contact center agents. + +## __Amazon EC2 Container Service__ + - ### Features + - This release adds support for Container Insights with Enhanced Observability for Amazon ECS. + +## __Amazon Elastic Compute Cloud__ + - ### Features + - Adds support for declarative policies that allow you to enforce desired configuration across an AWS organization through configuring account attributes. Adds support for Allowed AMIs that allows you to limit the use of AMIs in AWS accounts. Adds support for connectivity over non-HTTP protocols. + +## __Amazon Elastic Kubernetes Service__ + - ### Features + - Added support for Auto Mode Clusters, Hybrid Nodes, and specifying computeTypes in the DescribeAddonVersions API. + +## __Amazon EventBridge__ + - ### Features + - Call private APIs by configuring Connections with VPC connectivity through PrivateLink and VPC Lattice + +## __Amazon FSx__ + - ### Features + - FSx API changes to support the public launch of the Amazon FSx Intelligent Tiering for OpenZFS storage class. + +## __Amazon GuardDuty__ + - ### Features + - Add new Multi Domain Correlation findings. + +## __Amazon MemoryDB__ + - ### Features + - Amazon MemoryDB SDK now supports all APIs for Multi-Region. Please refer to the updated Amazon MemoryDB public documentation for detailed information on API usage. + +## __Amazon OpenSearch Service__ + - ### Features + - This feature introduces support for CRUDL APIs, enabling the creation and management of Connected data sources. + +## __Amazon Q Connect__ + - ### Features + - This release adds following capabilities: Configuring safeguards via AIGuardrails for Q in Connect inferencing, and APIs to support Q&A self-service use cases + +## __Amazon Relational Database Service__ + - ### Features + - Amazon RDS supports CloudWatch Database Insights. You can use the SDK to create, modify, and describe the DatabaseInsightsMode for your DB instances and clusters. + +## __Amazon Simple Storage Service__ + - ### Features + - Amazon S3 introduces support for AWS Dedicated Local Zones + +## __Amazon VPC Lattice__ + - ### Features + - Lattice APIs that allow sharing and access of VPC resources across accounts. + +## __AmazonConnectCampaignServiceV2__ + - ### Features + - Amazon Connect Outbound Campaigns V2 / Features : Adds support for Event-Triggered Campaigns. + +## __EC2 Image Builder__ + - ### Features + - Added support for EC2 Image Builder's integration with AWS Marketplace for Marketplace components. + +## __Network Flow Monitor__ + - ### Features + - This release adds documentation for a new feature in Amazon CloudWatch called Network Flow Monitor. You can use Network Flow Monitor to get near real-time metrics, including retransmissions and data transferred, for your actual workloads. + +## __QBusiness__ + - ### Features + - Amazon Q Business now supports capabilities to extract insights and answer questions from visual elements embedded within documents, a browser extension for Google Chrome, Mozilla Firefox, and Microsoft Edge, and attachments across conversations. + +## __Security Incident Response__ + - ### Features + - AWS Security Incident Response is a purpose-built security incident solution designed to help customers prepare for, respond to, and recover from security incidents. + +# __2.29.23__ __2024-11-27__ +## __AWS Config__ + - ### Features + - AWS Config adds support for service-linked recorders, a new type of Config recorder managed by AWS services to record specific subsets of resource configuration data and functioning independently from customer managed AWS Config recorders. + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __Agents for Amazon Bedrock__ + - ### Features + - Add support for specifying embeddingDataType, either FLOAT32 or BINARY + +## __Amazon FSx__ + - ### Features + - This release adds EFA support to increase FSx for Lustre file systems' throughput performance to a single client instance. This can be done by specifying EfaEnabled=true at the time of creation of Persistent_2 file systems. + +## __CloudWatch Observability Admin Service__ + - ### Features + - Amazon CloudWatch Observability Admin adds the ability to audit telemetry configuration for AWS resources in customers AWS Accounts and Organizations. The release introduces new APIs to turn on/off the new experience, which supports discovering supported AWS resources and their state of telemetry. + +## __DynamoDB Enhanced Client__ + - ### Bugfixes + - Fix a bug where DurationAttributeConverter was considering any number past the decimal point as a nanosecond during deserialization + +# __2.29.22__ __2024-11-26__ +## __AWS SDK for Java v2__ + - ### Bugfixes + - Fix ApacheHttpClient's handling of request bodies on DELETE, GET, HEAD & OPTIONS requests + - Contributed by: [@Xtansia](https://github.com/Xtansia) + +## __Agents for Amazon Bedrock__ + - ### Features + - Custom Orchestration API release for AWSBedrockAgents. + +## __Agents for Amazon Bedrock Runtime__ + - ### Features + - Custom Orchestration and Streaming configurations API release for AWSBedrockAgents. + +## __Amazon Connect Service__ + - ### Features + - Enables access to ValueMap and ValueInteger types for SegmentAttributes and fixes deserialization bug for DescribeContactFlow in AmazonConnect Public API + +## __Amazon Elastic Compute Cloud__ + - ### Features + - Adds support for Time-based Copy for EBS Snapshots and Cross Region PrivateLink. Time-based Copy ensures that EBS Snapshots are copied within and across AWS Regions in a specified timeframe. Cross Region PrivateLink enables customers to connect to VPC endpoint services hosted in other AWS Regions. + +## __QApps__ + - ### Features + - Private sharing, file upload and data collection feature support for Q Apps + +## __Contributors__ +Special thanks to the following contributors to this release: + +[@Xtansia](https://github.com/Xtansia) +# __2.29.21__ __2024-11-25__ +## __AWS Direct Connect__ + - ### Features + - Update DescribeDirectConnectGatewayAssociations API to return associated core network information if a Direct Connect gateway is attached to a Cloud WAN core network. + +## __AWS Network Manager__ + - ### Features + - This release adds native Direct Connect integration on Cloud WAN enabling customers to directly attach their Direct Connect gateways to Cloud WAN without the need for an intermediate Transit Gateway. + +## __Amazon Simple Storage Service__ + - ### Features + - Amazon Simple Storage Service / Features: Add support for ETag based conditional writes in PutObject and CompleteMultiPartUpload APIs to prevent unintended object modifications. + +## __v2-migration OpenRewrite recipe__ + - ### Bugfixes + - This fixes a ConcurrentModificationException - just by replacing a HashMap with ConcurrentHashMap + - Contributed by: [@sk-br](https://github.com/sk-br) + +## __Contributors__ +Special thanks to the following contributors to this release: + +[@sk-br](https://github.com/sk-br) +# __2.29.20__ __2024-11-22__ +## __AWS Billing and Cost Management Pricing Calculator__ + - ### Features + - Initial release of the AWS Billing and Cost Management Pricing Calculator API. + +## __AWS Chatbot__ + - ### Features + - Adds support for programmatic management of custom actions and aliases which can be associated with channel configurations. + +## __AWS CodePipeline__ + - ### Features + - AWS CodePipeline V2 type pipelines now support ECRBuildAndPublish and InspectorScan actions. + +## __AWS Cost Explorer Service__ + - ### Features + - This release adds the Impact field(contains Contribution field) to the GetAnomalies API response under RootCause + +## __AWS Lambda__ + - ### Features + - Add ProvisionedPollerConfig to Lambda event-source-mapping API. + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __AWS Step Functions__ + - ### Features + - Add support for variables and JSONata in TestState, GetExecutionHistory, DescribeStateMachine, and DescribeStateMachineForExecution + +## __Agents for Amazon Bedrock Runtime__ + - ### Features + - InvokeInlineAgent API release to help invoke runtime agents without any dependency on preconfigured agents. + +## __Amazon Cognito Identity Provider__ + - ### Features + - Add support for users to sign up and sign in without passwords, using email and SMS OTPs and Passkeys. Add support for Passkeys based on WebAuthn. Add support for enhanced branding customization for hosted authentication pages with Amazon Cognito Managed Login. Add feature tiers with new pricing. + +## __Amazon Connect Service__ + - ### Features + - Amazon Connect Service Feature: Add APIs for Amazon Connect Email Channel + +## __Amazon EMR__ + - ### Features + - Advanced Scaling in Amazon EMR Managed Scaling + +## __Amazon Neptune Graph__ + - ### Features + - Add 4 new APIs to support new Export features, allowing Parquet and CSV formats. Add new arguments in Import APIs to support Parquet import. Add a new query "neptune.read" to run algorithms without loading data into database + +## __Amazon Omics__ + - ### Features + - This release adds support for resource policy based cross account S3 access to sequence store read sets. + +## __Amazon QuickSight__ + - ### Features + - This release includes: Update APIs to support Image, Layer Map, font customization, and Plugin Visual. Add Identity center related information in ListNamsespace API. Update API for restrictedFolder support in topics and add API for SearchTopics, Describe/Update DashboardsQA Configration. + +## __Amazon SageMaker Service__ + - ### Features + - This release adds APIs for new features for SageMaker endpoint to scale down to zero instances, native support for multi-adapter inference, and endpoint scaling improvements. + +## __Amazon Simple Email Service__ + - ### Features + - This release adds support for starting email contacts in your Amazon Connect instance as an email receiving action. + +## __Amazon Simple Notification Service__ + - ### Features + - ArchivePolicy attribute added to Archive and Replay feature + +## __Amazon WorkSpaces__ + - ### Features + - While integrating WSP-DCV rebrand, a few mentions were erroneously renamed from WSP to DCV. This release reverts those mentions back to WSP. + +## __Auto Scaling__ + - ### Features + - Now, Amazon EC2 Auto Scaling customers can enable target tracking policies to take quicker scaling decisions, enhancing their application performance and EC2 utilization. To get started, specify target tracking to monitor a metric that is available on Amazon CloudWatch at seconds-level interval. + +## __Elastic Load Balancing__ + - ### Features + - This release adds support for advertising trusted CA certificate names in associated trust stores. + +## __Inspector2__ + - ### Features + - Extend inspector2 service model to include ServiceQuotaExceededException. + +## __MailManager__ + - ### Features + - Added new "DeliverToQBusiness" rule action to MailManager RulesSet for ingesting email data into Amazon Q Business customer applications + +# __2.29.19__ __2024-11-21__ +## __AWS AppSync__ + - ### Features + - Add support for the Amazon Bedrock Runtime. + +## __AWS CloudTrail__ + - ### Features + - This release introduces new APIs for creating and managing CloudTrail Lake dashboards. It also adds support for resource-based policies on CloudTrail EventDataStore and Dashboard resource. + +## __AWS Cost Explorer Service__ + - ### Features + - This release introduces three new APIs that enable you to estimate the cost, coverage, and utilization impact of Savings Plans you plan to purchase. The three APIs are StartCommitmentPurchaseAnalysis, GetCommitmentPurchaseAnalysis, and ListCommitmentPurchaseAnalyses. + +## __AWS Health APIs and Notifications__ + - ### Features + - Adds metadata property to an AffectedEntity. + +## __AWS IoT__ + - ### Features + - General Availability (GA) release of AWS IoT Device Management - Commands, to trigger light-weight remote actions on targeted devices + +## __AWS IoT FleetWise__ + - ### Features + - AWS IoT FleetWise now includes campaign parameters to store and forward data, configure MQTT topic as a data destination, and collect diagnostic trouble code data. It includes APIs for network agnostic data collection using custom decoding interfaces, and monitoring the last known state of vehicles. + +## __AWS IoT Jobs Data Plane__ + - ### Features + - General Availability (GA) release of AWS IoT Device Management - Commands, to trigger light-weight remote actions on targeted devices + +## __AWS Lambda__ + - ### Features + - Adds support for metrics for event source mappings for AWS Lambda + +## __AWS Resilience Hub__ + - ### Features + - AWS Resilience Hub's new summary view visually represents applications' resilience through charts, enabling efficient resilience management. It provides a consolidated view of the app portfolio's resilience state and allows data export for custom stakeholder reporting. + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __AWS Systems Manager QuickSetup__ + - ### Features + - Add methods that retrieve details about deployed configurations: ListConfigurations, GetConfiguration + +## __AWS User Notifications__ + - ### Features + - This release adds support for AWS User Notifications. You can now configure and view notifications from AWS services in a central location using the AWS SDK. + +## __AWS User Notifications Contacts__ + - ### Features + - This release adds support for AWS User Notifications Contacts. You can now configure and view email contacts for AWS User Notifications using the AWS SDK. + +## __AWS X-Ray__ + - ### Features + - AWS X-Ray introduces Transaction Search APIs, enabling span ingestion into CloudWatch Logs for high-scale trace data indexing. These APIs support span-level queries, trace graph generation, and metric correlation for deeper application insights. + +## __Amazon API Gateway__ + - ### Features + - Added support for custom domain names for private APIs. + +## __Amazon CloudFront__ + - ### Features + - Adds support for Origin Selection between EMPv2 origins based on media quality score. + +## __Amazon CloudWatch Logs__ + - ### Features + - Adds "Create field indexes to improve query performance and reduce scan volume" and "Transform logs during ingestion". Updates documentation for "PutLogEvents with Entity". + +## __Amazon ElastiCache__ + - ### Features + - Added support to modify the engine type for existing ElastiCache Users and User Groups. Customers can now modify the engine type from redis to valkey. + +## __Amazon Elastic Compute Cloud__ + - ### Features + - Adds support for requesting future-dated Capacity Reservations with a minimum commitment duration, enabling IPAM for organizational units within AWS Organizations, reserving EC2 Capacity Blocks that start in 30 minutes, and extending the end date of existing Capacity Blocks. + +## __Amazon Simple Storage Service__ + - ### Features + - Add support for conditional deletes for the S3 DeleteObject and DeleteObjects APIs. Add support for write offset bytes option used to append to objects with the S3 PutObject API. + +## __Amazon Simple Systems Manager (SSM)__ + - ### Features + - Added support for providing high-level overviews of managed nodes and previewing the potential impact of a runbook execution. + +## __Application Auto Scaling__ + - ### Features + - Application Auto Scaling now supports Predictive Scaling to proactively increase the desired capacity ahead of predicted demand, ensuring improved availability and responsiveness for customers' applications. This feature is currently only made available for Amazon ECS Service scalable targets. + +## __Elastic Load Balancing__ + - ### Features + - This feature adds support for enabling zonal shift on cross-zone enabled Application Load Balancer, as well as modifying HTTP request and response headers. + +# __2.29.18__ __2024-11-20__ +## __AWS Application Discovery Service__ + - ### Features + - Add support to import data from commercially available discovery tools without file manipulation. + +## __AWS Compute Optimizer__ + - ### Features + - This release enables AWS Compute Optimizer to analyze and generate optimization recommendations for Amazon Aurora database instances. It also enables Compute Optimizer to identify idle Amazon EC2 instances, Amazon EBS volumes, Amazon ECS services running on Fargate, and Amazon RDS databases. + +## __AWS Control Tower__ + - ### Features + - Adds support for child enabled baselines which allow you to see the enabled baseline status for individual accounts. + +## __AWS Elemental MediaConvert__ + - ### Features + - This release adds the ability to reconfigure concurrent job settings for existing queues and create queues with custom concurrent job settings. + +## __AWS Elemental MediaPackage v2__ + - ### Features + - MediaPackage v2 now supports the Media Quality Confidence Score (MQCS) published from MediaLive. Customers can control input switching based on the MQCS and publishing HTTP Headers for the MQCS via the API. + +## __AWS Lambda__ + - ### Features + - Add Node 22.x (node22.x) support to AWS Lambda + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __Agents for Amazon Bedrock Runtime__ + - ### Features + - Releasing new Prompt Optimization to enhance your prompts for improved performance + +## __Amazon CloudFront__ + - ### Features + - Add support for gRPC, VPC origins, and Anycast IP Lists. Allow LoggingConfig IncludeCookies to be set regardless of whether the LoggingConfig is enabled. + +## __Amazon DataZone__ + - ### Features + - This release supports Metadata Enforcement Rule feature for Create Subscription Request action. + +## __Amazon EC2 Container Service__ + - ### Features + - This release adds support for the Availability Zone rebalancing feature on Amazon ECS. + +## __Amazon Elastic Compute Cloud__ + - ### Features + - With this release, customers can express their desire to launch instances only in an ODCR or ODCR group rather than OnDemand capacity. Customers can express their baseline instances' CPU-performance in attribute-based Instance Requirements configuration by referencing an instance family. + +## __Amazon Omics__ + - ### Features + - Enabling call caching feature that allows customers to reuse previously computed results from a set of completed tasks in a new workflow run. + +## __Amazon Recycle Bin__ + - ### Features + - This release adds support for exclusion tags for Recycle Bin, which allows you to identify resources that are to be excluded, or ignored, by a Region-level retention rule. + +## __Amazon Relational Database Service__ + - ### Features + - This release adds support for scale storage on the DB instance using a Blue/Green Deployment. + +## __Amazon Timestream Query__ + - ### Features + - This release adds support for Provisioning Timestream Compute Units (TCUs), a new feature that allows provisioning dedicated compute resources for your queries, providing predictable and cost-effective query performance. + +## __Amazon WorkSpaces__ + - ### Features + - Added support for Rocky Linux 8 on Amazon WorkSpaces Personal. + +## __Amazon WorkSpaces Web__ + - ### Features + - Added data protection settings with support for inline data redaction. + +## __Auto Scaling__ + - ### Features + - With this release, customers can prioritize launching instances into ODCRs using targets from ASGs or Launch Templates. Customers can express their baseline instances' CPU-performance in attribute-based Instance Requirements configuration by referencing an instance family that meets their needs. + +## __Cost Optimization Hub__ + - ### Features + - This release adds action type "Delete" to the GetRecommendation, ListRecommendations and ListRecommendationSummaries APIs to support new EBS and ECS recommendations with action type "Delete". + +## __Elastic Load Balancing__ + - ### Features + - This release adds support for configuring Load balancer Capacity Unit reservations + +# __2.29.17__ __2024-11-19__ +## __AWS B2B Data Interchange__ + - ### Features + - Add new X12 transactions sets and versions + +## __AWS Glue__ + - ### Features + - AWS Glue Data Catalog now enhances managed table optimizations of Apache Iceberg tables that can be accessed only from a specific Amazon Virtual Private Cloud (VPC) environment. + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __Amazon EC2 Container Service__ + - ### Features + - This release introduces support for configuring the version consistency feature for individual containers defined within a task definition. The configuration allows to specify whether ECS should resolve the container image tag specified in the container definition to an image digest. + +## __Amazon Elastic Compute Cloud__ + - ### Features + - This release adds VPC Block Public Access (VPC BPA), a new declarative control which blocks resources in VPCs and subnets that you own in a Region from reaching or being reached from the internet through internet gateways and egress-only internet gateways. + +## __Amazon Elastic File System__ + - ### Features + - Add support for the new parameters in EFS replication APIs + +## __Amazon Keyspaces__ + - ### Features + - Amazon Keyspaces Multi-Region Replication: Adds support to add new regions to multi and single-region keyspaces. + +## __Amazon WorkSpaces__ + - ### Features + - Releasing new ErrorCodes for Image Validation failure during CreateWorkspaceImage process + +## __AmazonMWAA__ + - ### Features + - Amazon MWAA now supports a new environment class, mw1.micro, ideal for workloads requiring fewer resources than mw1.small. This class supports a single instance of each Airflow component: Scheduler, Worker, and Webserver. + +## __Tax Settings__ + - ### Features + - Release Tax Inheritance APIs, Tax Exemption APIs, and functionality update for some existing Tax Registration APIs + +# __2.29.16__ __2024-11-18__ +## __AWS CloudFormation__ + - ### Features + - This release adds a new API, ListHookResults, that allows retrieving CloudFormation Hooks invocation results for hooks invoked during a create change set operation or Cloud Control API operation + +## __AWS IoT SiteWise__ + - ### Features + - The release introduces a generative AI Assistant in AWS IoT SiteWise. It includes: 1) InvokeAssistant API - Invoke the Assistant to get alarm summaries and ask questions. 2) Dataset APIs - Manage knowledge base configuration for the Assistant. 3) Portal APIs enhancement - Manage AI-aware dashboards. + +## __AWS RDS DataService__ + - ### Features + - Add support for the automatic pause/resume feature of Aurora Serverless v2. + +## __Amazon AppConfig__ + - ### Features + - AWS AppConfig has added a new extension action point, AT_DEPLOYMENT_TICK, to support third-party monitors to trigger an automatic rollback during a deployment. + +## __Amazon Connect Customer Profiles__ + - ### Features + - This release introduces Segmentation APIs and new Calculated Attribute Event Filters as part of Amazon Connect Customer Profiles service. + +## __Amazon Connect Service__ + - ### Features + - Adds CreateContactFlowVersion and ListContactFlowVersions APIs to create and view the versions of a contact flow. + +## __Amazon EC2 Container Service__ + - ### Features + - This release adds support for adding VPC Lattice configurations in ECS CreateService/UpdateService APIs. The configuration allows for associating VPC Lattice target groups with ECS Services. + +## __Amazon Elastic Compute Cloud__ + - ### Features + - Adding request and response elements for managed resources. + +## __Amazon Q Connect__ + - ### Features + - This release introduces MessageTemplate as a resource in Amazon Q in Connect, along with APIs to create, read, search, update, and delete MessageTemplate resources. + +## __Amazon Relational Database Service__ + - ### Features + - Add support for the automatic pause/resume feature of Aurora Serverless v2. + +## __Auto Scaling__ + - ### Features + - Amazon EC2 Auto Scaling now supports Amazon Application Recovery Controller (ARC) zonal shift and zonal autoshift to help you quickly recover an impaired application from failures in an Availability Zone (AZ). + +# __2.29.15__ __2024-11-15__ +## __AWS DataSync__ + - ### Features + - Doc-only updates and enhancements related to creating DataSync tasks and describing task executions. + +## __AWS IoT__ + - ### Features + - This release allows AWS IoT Core users to enrich MQTT messages with propagating attributes, to associate a thing to a connection, and to enable Online Certificate Status Protocol (OCSP) stapling for TLS X.509 server certificates through private endpoints. + +## __AWS Outposts__ + - ### Features + - You can now purchase AWS Outposts rack or server capacity for a 5-year term with one of the following payment options: All Upfront, Partial Upfront, and No Upfront. + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __Amazon CloudWatch__ + - ### Features + - Adds support for adding related Entity information to metrics ingested through PutMetricData. + +## __Amazon Elastic Compute Cloud__ + - ### Features + - Remove non-functional enum variants for FleetCapacityReservationUsageStrategy + +## __Amazon Pinpoint SMS Voice V2__ + - ### Features + - Use rule overrides to always allow or always block messages to specific phone numbers. Use message feedback to monitor if a customer interacts with your message. + +## __Amazon Polly__ + - ### Features + - Fixes PutLexicon usage example. + +## __Amazon Route 53 Resolver__ + - ### Features + - Route 53 Resolver DNS Firewall Advanced Rules allows you to monitor and block suspicious DNS traffic based on anomalies detected in the queries, such as DNS tunneling and Domain Generation Algorithms (DGAs). + +## __AmazonConnectCampaignServiceV2__ + - ### Features + - Added Amazon Connect Outbound Campaigns V2 SDK. + +# __2.29.14__ __2024-11-14__ +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __Partner Central Selling API__ + - ### Features + - Announcing AWS Partner Central API for Selling: This service launch Introduces new APIs for co-selling opportunity management and related functions. Key features include notifications, a dynamic sandbox for testing, and streamlined validations. + +# __2.29.13__ __2024-11-14__ +## __AWS Cloud Control API__ + - ### Features + - Added support for CloudFormation Hooks with Cloud Control API. The GetResourceRequestStatus API response now includes an optional HooksProgressEvent and HooksRequestToken parameter for Hooks Invocation Progress as part of resource operation with Cloud Control. + +## __AWS Identity and Access Management__ + - ### Features + - This release includes support for five new APIs and changes to existing APIs that give AWS Organizations customers the ability to use temporary root credentials, targeted to member accounts in the organization. + +## __AWS IoT Wireless__ + - ### Features + - New FuotaTask resource type to enable logging for your FUOTA tasks. A ParticipatingGatewaysforMulticast parameter to choose the list of gateways to receive the multicast downlink message and the transmission interval between them. Descriptor field which will be sent to devices during FUOTA transfer. + +## __AWS License Manager User Subscriptions__ + - ### Features + - New and updated API operations to support License Included User-based Subscription of Microsoft Remote Desktop Services (RDS). + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __AWS Security Token Service__ + - ### Features + - This release introduces the new API 'AssumeRoot', which returns short-term credentials that you can use to perform privileged tasks. + +## __AWSDeadlineCloud__ + - ### Features + - Adds support for select GPU accelerated instance types when creating new service-managed fleets. + +## __Access Analyzer__ + - ### Features + - Expand analyzer configuration capabilities for unused access analyzers. Unused access analyzer configurations now support the ability to exclude accounts and resource tags from analysis providing more granular control over the scope of analysis. + +## __Amazon Interactive Video Service__ + - ### Features + - IVS now offers customers the ability to stream multitrack video to Channels. + +## __Amazon QuickSight__ + - ### Features + - This release adds APIs for Custom Permissions management in QuickSight, and APIs to support QuickSight Branding. + +## __Amazon Redshift__ + - ### Features + - Adds support for Amazon Redshift S3AccessGrants + +## __Amazon SageMaker Service__ + - ### Features + - Add support for Neuron instance types [ trn1/trn1n/inf2 ] on SageMaker Notebook Instances Platform. + +## __Amazon Simple Storage Service__ + - ### Features + - This release updates the ListBuckets API Reference documentation in support of the new 10,000 general purpose bucket default quota on all AWS accounts. To increase your bucket quota from 10,000 to up to 1 million buckets, simply request a quota increase via Service Quotas. + +## __Netty NIO HTTP Client__ + - ### Features + - Update Netty version to `4.1.115.Final`. + +## __Partner Central Selling API__ + - ### Features + - Announcing AWS Partner Central API for Selling: This service launch Introduces new APIs for co-selling opportunity management and related functions. Key features include notifications, a dynamic sandbox for testing, and streamlined validations. + +# __2.29.12__ __2024-11-13__ +## __AWS B2B Data Interchange__ + - ### Features + - This release adds a GenerateMapping API to allow generation of JSONata or XSLT transformer code based on input and output samples. + +## __AWS Billing__ + - ### Features + - Today, AWS announces the general availability of ListBillingViews API in the AWS SDKs, to enable AWS Billing Conductor (ABC) users to create proforma Cost and Usage Reports (CUR) programmatically. + +## __AWS CloudTrail__ + - ### Features + - This release adds a new API GenerateQuery that generates a query from a natural language prompt about the event data in your event data store. This operation uses generative artificial intelligence (generative AI) to produce a ready-to-use SQL query from the prompt. + +## __AWS Elemental MediaConvert__ + - ### Features + - This release adds support for ARN inputs in the Kantar credentials secrets name field and the MSPR field to the manifests for PlayReady DRM protected outputs. + +## __AWS Organizations__ + - ### Features + - Add support for policy operations on the Resource Control Polices. + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __Access Analyzer__ + - ### Features + - This release adds support for policy validation and external access findings for resource control policies (RCP). IAM Access Analyzer helps you author functional and secure RCPs and awareness that a RCP may restrict external access. Updated service API, documentation, and paginators. + +## __Amazon CloudWatch Application Signals__ + - ### Features + - Amazon CloudWatch Application Signals now supports creating Service Level Objectives with burn rates. Users can now create or update SLOs with burn rate configurations to meet their specific business requirements. + +## __Amazon CloudWatch Internet Monitor__ + - ### Features + - Add new query type Routing_Suggestions regarding querying interface + +## __Amazon DynamoDB__ + - ### Features + - This release includes supports the new WarmThroughput feature for DynamoDB. You can now provide an optional WarmThroughput attribute for CreateTable or UpdateTable APIs to pre-warm your table or global secondary index. You can also use DescribeTable to see the latest WarmThroughput value. + +## __Amazon Elastic Compute Cloud__ + - ### Features + - This release adds the source AMI details in DescribeImages API + +# __2.29.11__ __2024-11-12__ +## __AWS CodeBuild__ + - ### Features + - AWS CodeBuild now supports non-containerized Linux and Windows builds on Reserved Capacity. + +## __AWS Control Tower__ + - ### Features + - Added ResetEnabledControl API. + +## __AWS Fault Injection Simulator__ + - ### Features + - This release adds support for generating experiment reports with the experiment report configuration + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __Amazon GameLift__ + - ### Features + - Amazon GameLift releases container fleets support for general availability. Deploy Linux-based containerized game server software for hosting on Amazon GameLift. + +## __Amazon Relational Database Service__ + - ### Features + - Updates Amazon RDS documentation for Amazon RDS Extended Support for Amazon Aurora MySQL. + +## __Payment Cryptography Control Plane__ + - ### Features + - Updated ListAliases API with KeyArn filter. + +# __2.29.10__ __2024-11-11__ +## __AWS Lambda__ + - ### Features + - Add Python 3.13 (python3.13) support to AWS Lambda + +## __AWS Outposts__ + - ### Features + - This release updates StartCapacityTask to allow an active Outpost to be modified. It also adds a new API to list all running EC2 instances on the Outpost. + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + + - ### Bugfixes + - SigV4: Add host header only when not already provided + - Contributed by: [@vsudilov](https://github.com/vsudilov) + +## __Amazon CloudFront__ + - ### Features + - No API changes from previous release. This release migrated the model to Smithy keeping all features unchanged. + +## __Amazon OpenSearch Service__ + - ### Features + - Adds Support for new AssociatePackages and DissociatePackages API in Amazon OpenSearch Service that allows association and dissociation operations to be carried out on multiple packages at the same time. + +## __Inspector2__ + - ### Features + - Adds support for filePath filter. + +## __Contributors__ +Special thanks to the following contributors to this release: + +[@vsudilov](https://github.com/vsudilov) +# __2.29.9__ __2024-11-08__ +## __AWS Batch__ + - ### Features + - This feature allows override LaunchTemplates to be specified in an AWS Batch Compute Environment. + +## __AWS Control Catalog__ + - ### Features + - AWS Control Catalog GetControl public API returns additional data in output, including Implementation and Parameters + +## __AWS Lambda__ + - ### Features + - This release adds support for using AWS KMS customer managed keys to encrypt AWS Lambda .zip deployment packages. + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __Agents for Amazon Bedrock Runtime__ + - ### Features + - This release adds trace functionality to Bedrock Prompt Flows + +## __Amazon Chime SDK Media Pipelines__ + - ### Features + - Added support for Media Capture Pipeline and Media Concatenation Pipeline for customer managed server side encryption. Now Media Capture Pipeline can use IAM sink role to get access to KMS key and encrypt/decrypt recorded artifacts. KMS key ID can also be supplied with encryption context. + +## __Amazon Elastic Kubernetes Service__ + - ### Features + - Adds new error code `Ec2InstanceTypeDoesNotExist` for Amazon EKS managed node groups + +## __Amazon Kinesis Firehose__ + - ### Features + - Amazon Data Firehose / Features : Adds support for a new DeliveryStreamType, DatabaseAsSource. DatabaseAsSource hoses allow customers to stream CDC events from their RDS and Amazon EC2 hosted databases, running MySQL and PostgreSQL database engines, to Iceberg Table destinations. + +## __Amazon Pinpoint SMS Voice V2__ + - ### Features + - Added the RequiresAuthenticationTimestamp field to the RegistrationVersionStatusHistory data type. + +## __QBusiness__ + - ### Features + - Adds S3 path option to pass group member list for PutGroup API. + +# __2.29.8__ __2024-11-07__ +## __AWS Clean Rooms ML__ + - ### Features + - This release introduces support for Custom Models in AWS Clean Rooms ML. + +## __AWS Clean Rooms Service__ + - ### Features + - This release introduces support for Custom Models in AWS Clean Rooms ML. + +## __AWS Resource Explorer__ + - ### Features + - Add GetManagedView, ListManagedViews APIs. + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __Agents for Amazon Bedrock__ + - ### Features + - Add prompt support for chat template configuration and agent generative AI resource. Add support for configuring an optional guardrail in Prompt and Knowledge Base nodes in Prompt Flows. Add API to validate flow definition + +## __Amazon Bedrock Runtime__ + - ### Features + - Add Prompt management support to Bedrock runtime APIs: Converse, ConverseStream, InvokeModel, InvokeModelWithStreamingResponse + +## __Amazon QuickSight__ + - ### Features + - Add Client Credentials based OAuth support for Snowflake and Starburst + +## __Auto Scaling__ + - ### Features + - Auto Scaling groups now support the ability to strictly balance instances across Availability Zones by configuring the AvailabilityZoneDistribution parameter. If balanced-only is configured for a group, launches will always be attempted in the under scaled Availability Zone even if it is unhealthy. + +## __Synthetics__ + - ### Features + - Add support to toggle if a canary will automatically delete provisioned canary resources such as Lambda functions and layers when a canary is deleted. This behavior can be controlled via the new ProvisionedResourceCleanup property exposed in the CreateCanary and UpdateCanary APIs. + +# __2.29.7__ __2024-11-06__ +## __AWS CodeBuild__ + - ### Features + - AWS CodeBuild now adds additional compute types for reserved capacity fleet. + +## __AWS Lake Formation__ + - ### Features + - API changes for new named tag expressions feature. + +## __AWS S3 Control__ + - ### Features + - Fix ListStorageLensConfigurations and ListStorageLensGroups deserialization for Smithy SDKs. + +## __AWS SDK for Java v2__ + - ### Features + - Improve unmarshalling performance of all JSON protocols by unifying parsing with unmarshalling instead of doing one after the other. + + - ### Bugfixes + - Moves setting the default backoff strategies for all retry strategies to the builder as per the javadocs instead of only doing it in the `DefaultRetryStrategy` builder methods. + +## __Amazon GuardDuty__ + - ### Features + - GuardDuty RDS Protection expands support for Amazon Aurora PostgreSQL Limitless Databases. + +## __Amazon Verified Permissions__ + - ### Features + - Adding BatchGetPolicy API which supports the retrieval of multiple policies across multiple policy stores within a single request. + +## __QApps__ + - ### Features + - Introduces category apis in AmazonQApps. Web experience users use Categories to tag and filter library items. + +# __2.29.6__ __2024-11-01__ +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + + - ### Bugfixes + - Load Checksum classes of CRT from Classloader instead of direct references of CRT classes. + +## __Agents for Amazon Bedrock__ + - ### Features + - Amazon Bedrock Knowledge Bases now supports using application inference profiles to increase throughput and improve resilience. + +## __Amazon CloudWatch Logs__ + - ### Features + - This release introduces an improvement in PutLogEvents + +## __Amazon DocumentDB Elastic Clusters__ + - ### Features + - Amazon DocumentDB Elastic Clusters adds support for pending maintenance actions feature with APIs GetPendingMaintenanceAction, ListPendingMaintenanceActions and ApplyPendingMaintenanceAction + +## __Tax Settings__ + - ### Features + - Add support for supplemental tax registrations via these new APIs: PutSupplementalTaxRegistration, ListSupplementalTaxRegistrations, and DeleteSupplementalTaxRegistration. + +# __2.29.5__ __2024-10-31__ +## __AWS Batch__ + - ### Features + - Add `podNamespace` to `EksAttemptDetail` and `containerID` to `EksAttemptContainerDetail`. + +## __AWS Glue__ + - ### Features + - Add schedule support for AWS Glue column statistics + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + + - ### Bugfixes + - Fix an issue where the SDK does not properly unmarshall an evenstream exception to the expected exception type. + +## __Amazon Prometheus Service__ + - ### Features + - Added support for UpdateScraper API, to enable updating collector configuration in-place + +## __Amazon SageMaker Service__ + - ### Features + - SageMaker HyperPod adds scale-down at instance level via BatchDeleteClusterNodes API and group level via UpdateCluster API. SageMaker Training exposes secondary job status in TrainingJobSummary from ListTrainingJobs API. SageMaker now supports G6, G6e, P5e instances for HyperPod and Training. + +## __Amazon Simple Email Service__ + - ### Features + - This release enables customers to provide the email template content in the SESv2 SendEmail and SendBulkEmail APIs instead of the name or the ARN of a stored email template. + +## __Auto Scaling__ + - ### Features + - Adds bake time for Auto Scaling group Instance Refresh + +## __Elastic Load Balancing__ + - ### Features + - Add UDP support for AWS PrivateLink and dual-stack Network Load Balancers + +# __2.29.4__ __2024-10-30__ +## __AWS AppSync__ + - ### Features + - This release adds support for AppSync Event APIs. + +## __AWS DataSync__ + - ### Features + - AWS DataSync now supports Enhanced mode tasks. This task mode supports transfer of virtually unlimited numbers of objects with enhanced metrics, more detailed logs, and higher performance than Basic mode. This mode currently supports transfers between Amazon S3 locations. + +## __AWS Network Firewall__ + - ### Features + - AWS Network Firewall now supports configuring TCP idle timeout + +## __AWS SDK for Java v2__ + - ### Features + - Adds support for tracking feature usage in a new user agent metadata section and adds a base set of features. Where features were already a part of the user agent string, they are now converted to the new format where a feature is represented as a Base64 encoded string. For example, using DynamoDb Enhanced Client was previously recorded as 'hll/ddb-enh' in the user agent, but is now a 'd' in the business metrics metadata section 'm/'. + - Updated endpoint and partition metadata. + +## __Amazon Connect Service__ + - ### Features + - Updated the public documentation for the UserIdentityInfo object to accurately reflect the character limits for the FirstName and LastName fields, which were previously listed as 1-100 characters. + +## __Amazon EC2 Container Service__ + - ### Features + - This release supports service deployments and service revisions which provide a comprehensive view of your Amazon ECS service history. + +## __Amazon Elastic Compute Cloud__ + - ### Features + - This release adds two new capabilities to VPC Security Groups: Security Group VPC Associations and Shared Security Groups. + +## __Amazon Keyspaces__ + - ### Features + - Adds support for interacting with user-defined types (UDTs) through the following new operations: Create-Type, Delete-Type, List-Types, Get-Type. + +## __Amazon Location Service Maps V2__ + - ### Features + - Release of Amazon Location Maps API. Maps enables you to build digital maps that showcase your locations, visualize your data, and unlock insights to drive your business + +## __Amazon Location Service Places V2__ + - ### Features + - Release of Amazon Location Places API. Places enables you to quickly search, display, and filter places, businesses, and locations based on proximity, category, and name + +## __Amazon Location Service Routes V2__ + - ### Features + - Release of Amazon Location Routes API. Routes enables you to plan efficient routes and streamline deliveries by leveraging real-time traffic, vehicle restrictions, and turn-by-turn directions. + +## __Amazon OpenSearch Service__ + - ### Features + - This release introduces the new OpenSearch user interface (Dashboards), a new web-based application that can be associated with multiple data sources across OpenSearch managed clusters, serverless collections, and Amazon S3, so that users can gain a comprehensive insights in an unified interface. + +## __Amazon Redshift__ + - ### Features + - This release launches S3 event integrations to create and manage integrations from an Amazon S3 source into an Amazon Redshift database. + +## __Amazon Route 53__ + - ### Features + - This release adds support for TLSA, SSHFP, SVCB, and HTTPS record types. + +## __Amazon SageMaker Service__ + - ### Features + - Added support for Model Registry Staging construct. Users can define series of stages that models can progress through for model workflows and lifecycle. This simplifies tracking and managing models as they transition through development, testing, and production stages. + +## __Amazon WorkMail__ + - ### Features + - This release adds support for Multi-Factor Authentication (MFA) and Personal Access Tokens through integration with AWS IAM Identity Center. + +## __OpenSearch Service Serverless__ + - ### Features + - Neo Integration via IAM Identity Center (IdC) + +## __Redshift Serverless__ + - ### Features + - Adds and updates API members for the Redshift Serverless AI-driven scaling and optimization feature using the price-performance target setting. + +# __2.29.3__ __2024-10-29__ +## __AWS Clean Rooms Service__ + - ### Features + - This release adds the option for customers to configure analytics engine when creating a collaboration, and introduces the new SPARK analytics engine type in addition to maintaining the legacy CLEAN_ROOMS_SQL engine type. + +## __AWS IoT FleetWise__ + - ### Features + - Updated BatchCreateVehicle and BatchUpdateVehicle APIs: LimitExceededException has been added and the maximum number of vehicles in a batch has been set to 10 explicitly + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __Amazon Bedrock__ + - ### Features + - Update Application Inference Profile + +## __Amazon Bedrock Runtime__ + - ### Features + - Update Application Inference Profile + +## __Amazon CloudWatch Logs__ + - ### Features + - Added support for new optional baseline parameter in the UpdateAnomaly API. For UpdateAnomaly requests with baseline set to True, The anomaly behavior is then treated as baseline behavior. However, more severe occurrences of this behavior will still be reported as anomalies. + +## __Amazon SageMaker Service__ + - ### Features + - Adding `notebook-al2-v3` as allowed value to SageMaker NotebookInstance PlatformIdentifier attribute + +## __Redshift Data API Service__ + - ### Features + - Adding a new API GetStatementResultV2 that supports CSV formatted results from ExecuteStatement and BatchExecuteStatement calls. + +# __2.29.2__ __2024-10-28__ +## __AWS Elemental MediaPackage v2__ + - ### Features + - MediaPackage V2 Live to VOD Harvester is a MediaPackage V2 feature, which is used to export content from an origin endpoint to a S3 bucket. + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __AWS Storage Gateway__ + - ### Features + - Documentation update: Amazon FSx File Gateway will no longer be available to new customers. + +## __Amazon OpenSearch Service__ + - ### Features + - Adds support for provisioning dedicated coordinator nodes. Coordinator nodes can be specified using the new NodeOptions parameter in ClusterConfig. + +## __Amazon Relational Database Service__ + - ### Features + - This release adds support for Enhanced Monitoring and Performance Insights when restoring Aurora Limitless Database DB clusters. It also adds support for the os-upgrade pending maintenance action. + +## __Amazon S3__ + - ### Bugfixes + - Update the S3 client to correctly handle redirect cases for opt-in regions when crossRegionAccessEnabled is used. + +# __2.29.1__ __2024-10-25__ +## __AWS CodeBuild__ + - ### Features + - AWS CodeBuild now supports automatically retrying failed builds + +## __AWS Lambda__ + - ### Features + - Add TagsError field in Lambda GetFunctionResponse. The TagsError field contains details related to errors retrieving tags. + +## __AWS SDK for Java v2__ + - ### Features + - Updated endpoint and partition metadata. + +## __AWS Supply Chain__ + - ### Features + - API doc updates, and also support showing error message on a failed instance + +## __Agents for Amazon Bedrock__ + - ### Features + - Add support of new model types for Bedrock Agents, Adding inference profile support for Flows and Prompt Management, Adding new field to configure additional inference configurations for Flows and Prompt Management + +## __Amazon CloudWatch Logs__ + - ### Features + - Adding inferred token name for dynamic tokens in Anomalies. + +# __2.29.0__ __2024-10-24__ +## __AWS Parallel Computing Service__ + - ### Features + - Documentation update: added the default value of the Slurm configuration parameter scaleDownIdleTimeInSeconds to its description. + +## __AWS SDK for Java v2__ + - ### Features + - The SDK now defaults to Java built-in CRC32 and CRC32C(if it's Java 9+) implementations, resulting in improved performance. + - Updated endpoint and partition metadata. + + - ### Deprecations + - Deprecate internal checksum algorithm classes. + +## __Amazon AppConfig__ + - ### Features + - This release improves deployment safety by granting customers the ability to REVERT completed deployments, to the last known good state.In the StopDeployment API revert case the status of a COMPLETE deployment will be REVERTED. AppConfig only allows a revert within 72 hours of deployment completion. + +## __Amazon EC2 Container Service__ + - ### Features + - This release adds support for EBS volumes attached to Amazon ECS Windows tasks running on EC2 instances. + +## __Amazon Elastic Compute Cloud__ + - ### Features + - This release includes a new API to describe some details of the Amazon Machine Images (AMIs) that were used to launch EC2 instances, even if those AMIs are no longer available for use. + +## __QBusiness__ + - ### Features + - Add a new field in chat response. This field can be used to support nested schemas in array fields + diff --git a/codegen-lite-maven-plugin/pom.xml b/codegen-lite-maven-plugin/pom.xml index efccce2c015b..18585d9e96bd 100644 --- a/codegen-lite-maven-plugin/pom.xml +++ b/codegen-lite-maven-plugin/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk aws-sdk-java-pom - 2.29.52 + 2.30.0 ../pom.xml codegen-lite-maven-plugin diff --git a/codegen-lite/pom.xml b/codegen-lite/pom.xml index 756ad87eaf56..d7ef49c07f47 100644 --- a/codegen-lite/pom.xml +++ b/codegen-lite/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk aws-sdk-java-pom - 2.29.52 + 2.30.0 codegen-lite AWS Java SDK :: Code Generator Lite diff --git a/codegen-maven-plugin/pom.xml b/codegen-maven-plugin/pom.xml index 8e5ce571397e..63278504345b 100644 --- a/codegen-maven-plugin/pom.xml +++ b/codegen-maven-plugin/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk aws-sdk-java-pom - 2.29.52 + 2.30.0 ../pom.xml codegen-maven-plugin diff --git a/codegen/pom.xml b/codegen/pom.xml index bc5a7746734e..43de5309fc7f 100644 --- a/codegen/pom.xml +++ b/codegen/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk aws-sdk-java-pom - 2.29.52 + 2.30.0 codegen AWS Java SDK :: Code Generator @@ -162,6 +162,16 @@ json-utils ${awsjavasdk.version} + + software.amazon.awssdk + checksums + ${awsjavasdk.version} + + + software.amazon.awssdk + checksums-spi + ${awsjavasdk.version} + org.eclipse.jdt.core diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/UnusedImportRemover.java b/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/UnusedImportRemover.java index 0ecdaf7b7907..5de2fb6fa877 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/UnusedImportRemover.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/emitters/UnusedImportRemover.java @@ -26,7 +26,8 @@ import java.util.regex.Pattern; public class UnusedImportRemover implements CodeTransformer { - private static Pattern IMPORT_PATTERN = Pattern.compile("import(?:\\s+)(?:static\\s+)?(.*)(?:\\s*);"); + private static final Pattern IMPORT_PATTERN = Pattern.compile("^import(?:\\s+)(?:static\\s+)?(.*)(?:\\s*);", + Pattern.MULTILINE); @Override public String apply(String content) { @@ -52,7 +53,8 @@ private List findImports(String content) { } private String removeAllImports(String content) { - return content.replaceAll(IMPORT_PATTERN.pattern(), ""); + Matcher matcher = IMPORT_PATTERN.matcher(content); + return matcher.replaceAll(""); } private Predicate isUnused(String content) { diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/model/config/customization/ServiceConfig.java b/codegen/src/main/java/software/amazon/awssdk/codegen/model/config/customization/ServiceConfig.java index b0c0db862df2..cfb6e03cb163 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/model/config/customization/ServiceConfig.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/model/config/customization/ServiceConfig.java @@ -49,6 +49,8 @@ public class ServiceConfig { private boolean hasCrossRegionAccessEnabledProperty = false; + private boolean hasChecksumValidationEnabledProperty = false; + public String getClassName() { return className; } @@ -112,4 +114,12 @@ public boolean hasAccelerateModeEnabledProperty() { public void setHasAccelerateModeEnabledProperty(boolean hasAccelerateModeEnabledProperty) { this.hasAccelerateModeEnabledProperty = hasAccelerateModeEnabledProperty; } + + public boolean hasChecksumValidationEnabledProperty() { + return hasChecksumValidationEnabledProperty; + } + + public void setHasChecksumValidationEnabledProperty(boolean hasChecksumValidationEnabledProperty) { + this.hasChecksumValidationEnabledProperty = hasChecksumValidationEnabledProperty; + } } diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/PoetUtils.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/PoetUtils.java index b2e3f50ba358..49ff8d610f74 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/PoetUtils.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/PoetUtils.java @@ -108,5 +108,4 @@ public static JavaFile buildJavaFile(ClassSpec spec) { spec.staticImports().forEach(i -> i.memberNames().forEach(m -> builder.addStaticImport(i.className(), m))); return builder.build(); } - } diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderClass.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderClass.java index 25269518b7b2..e1a37e35dea9 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderClass.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderClass.java @@ -18,6 +18,8 @@ import static javax.lang.model.element.Modifier.FINAL; import static javax.lang.model.element.Modifier.PRIVATE; import static javax.lang.model.element.Modifier.PROTECTED; +import static software.amazon.awssdk.codegen.poet.client.traits.HttpChecksumTrait.hasRequestAlgorithmMember; +import static software.amazon.awssdk.codegen.poet.client.traits.HttpChecksumTrait.hasResponseAlgorithms; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.CodeBlock; @@ -59,6 +61,10 @@ import software.amazon.awssdk.codegen.poet.rules.EndpointRulesSpecUtils; import software.amazon.awssdk.codegen.utils.AuthUtils; import software.amazon.awssdk.core.SdkPlugin; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculationResolver; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidation; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidationResolver; import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption; import software.amazon.awssdk.core.client.config.SdkClientConfiguration; import software.amazon.awssdk.core.client.config.SdkClientOption; @@ -157,6 +163,14 @@ public TypeSpec poetSpec() { builder.addMethod(authSchemesMethod()); } + if (hasRequestAlgorithmMember(model)) { + builder.addMethod(requestChecksumCalculationMethod()); + } + + if (hasResponseAlgorithms(model)) { + builder.addMethod(responseChecksumValidationMethod()); + } + if (hasClientContextParams()) { model.getClientContextParams().forEach((n, m) -> { builder.addMethod(clientContextParamSetter(n, m)); @@ -189,6 +203,14 @@ public TypeSpec poetSpec() { endpointParamsKnowledgeIndex.resolveAccountIdEndpointModeMethod().ifPresent(builder::addMethod); + if (hasRequestAlgorithmMember(model)) { + builder.addMethod(resolveRequestChecksumCalculationMethod()); + } + + if (hasResponseAlgorithms(model)) { + builder.addMethod(resolveResponseChecksumValidationMethod()); + } + builder.addMethod(validateClientOptionsMethod()); return builder.build(); @@ -487,6 +509,19 @@ private MethodSpec finalizeServiceConfigurationMethod() { } } + if (hasRequestAlgorithmMember(model) || hasResponseAlgorithms(model)) { + builder.addStatement("$T clientConfig = config", SdkClientConfiguration.class); + + if (hasRequestAlgorithmMember(model)) { + builder.addStatement("builder.lazyOption($T.REQUEST_CHECKSUM_CALCULATION, " + + "c -> resolveRequestChecksumCalculation(clientConfig))", SdkClientOption.class); + } + if (hasResponseAlgorithms(model)) { + builder.addStatement("builder.lazyOption($T.RESPONSE_CHECKSUM_VALIDATION, " + + "c -> resolveResponseChecksumValidation(clientConfig))", SdkClientOption.class); + } + } + builder.addStatement("return builder.build()"); return builder.build(); } @@ -576,6 +611,51 @@ private void mergeServiceConfiguration(MethodSpec.Builder builder, String client .addCode("}"); } + boolean hasRequestAlgorithmMember = hasRequestAlgorithmMember(model); + boolean hasResponseAlgorithms = hasResponseAlgorithms(model); + if (model.getCustomizationConfig().getServiceConfig().hasChecksumValidationEnabledProperty() + && (hasRequestAlgorithmMember || hasResponseAlgorithms)) { + builder.addStatement("$T checksumValidationEnabled = serviceConfigBuilder.checksumValidationEnabled()", Boolean.class) + .beginControlFlow("if (checksumValidationEnabled != null)"); + if (hasRequestAlgorithmMember) { + builder.addCode("$T.validState(config.option($T.REQUEST_CHECKSUM_CALCULATION) == null, ", + Validate.class, SdkClientOption.class) + .addStatement("\"Checksum behavior has been configured on both $L and the client/global level. Please " + + "limit checksum behavior configuration to one location.\")", clientConfigClassName); + } + if (hasResponseAlgorithms) { + builder.addCode("$T.validState(config.option($T.RESPONSE_CHECKSUM_VALIDATION) == null, ", + Validate.class, SdkClientOption.class) + .addStatement("\"Checksum behavior has been configured on both $L and the client/global level. Please " + + "limit checksum behavior configuration to one location.\")", clientConfigClassName); + } + builder.beginControlFlow("if (checksumValidationEnabled)") + .addCode("config = config.toBuilder()"); + if (hasRequestAlgorithmMember) { + builder.addCode(".option($T.REQUEST_CHECKSUM_CALCULATION, $T.WHEN_SUPPORTED)", + SdkClientOption.class, RequestChecksumCalculation.class); + } + if (hasResponseAlgorithms) { + builder.addCode(".option($T.RESPONSE_CHECKSUM_VALIDATION, $T.WHEN_SUPPORTED)", + SdkClientOption.class, ResponseChecksumValidation.class); + } + builder.addStatement(".build()") + .nextControlFlow("else") + .addCode("config = config.toBuilder()"); + + if (hasRequestAlgorithmMember) { + builder.addCode(".option($T.REQUEST_CHECKSUM_CALCULATION, $T.WHEN_REQUIRED)", + SdkClientOption.class, RequestChecksumCalculation.class); + } + if (hasResponseAlgorithms) { + builder.addCode(".option($T.RESPONSE_CHECKSUM_VALIDATION, $T.WHEN_REQUIRED)", + SdkClientOption.class, ResponseChecksumValidation.class); + } + builder.addStatement(".build()") + .endControlFlow() + .endControlFlow(); + } + builder.addStatement("$T finalServiceConfig = serviceConfigBuilder.build()", clientConfigClass); if (model.getCustomizationConfig().getServiceConfig().hasUseArnRegionProperty()) { @@ -740,6 +820,28 @@ private MethodSpec putAuthSchemeMethod() { .build(); } + private MethodSpec requestChecksumCalculationMethod() { + return MethodSpec.methodBuilder("requestChecksumCalculation") + .addModifiers(Modifier.PUBLIC) + .returns(TypeVariableName.get("B")) + .addParameter(RequestChecksumCalculation.class, "requestChecksumCalculation") + .addStatement("clientConfiguration.option($T.REQUEST_CHECKSUM_CALCULATION, requestChecksumCalculation)", + SdkClientOption.class) + .addStatement("return thisBuilder()") + .build(); + } + + private MethodSpec responseChecksumValidationMethod() { + return MethodSpec.methodBuilder("responseChecksumValidation") + .addModifiers(Modifier.PUBLIC) + .returns(TypeVariableName.get("B")) + .addParameter(ResponseChecksumValidation.class, "responseChecksumValidation") + .addStatement("clientConfiguration.option($T.RESPONSE_CHECKSUM_VALIDATION, responseChecksumValidation)", + SdkClientOption.class) + .addStatement("return thisBuilder()") + .build(); + } + private MethodSpec clientContextParamSetter(String name, ClientContextParam param) { String setterName = endpointRulesSpecUtils.paramMethodName(name); String keyName = model.getNamingStrategy().getEnumValueName(name); @@ -854,6 +956,50 @@ private MethodSpec internalPluginsMethod() { return builder.build(); } + private MethodSpec resolveRequestChecksumCalculationMethod() { + + MethodSpec.Builder builder = MethodSpec.methodBuilder("resolveRequestChecksumCalculation") + .addModifiers(PRIVATE) + .addParameter(SdkClientConfiguration.class, "config") + .returns(RequestChecksumCalculation.class); + + builder.addStatement("$T configuredChecksumCalculation = config.option($T.REQUEST_CHECKSUM_CALCULATION)", + RequestChecksumCalculation.class, SdkClientOption.class); + + builder.beginControlFlow("if (configuredChecksumCalculation == null)"); + builder.addCode("configuredChecksumCalculation = $T.create()", RequestChecksumCalculationResolver.class); + builder.addCode(".profileFile(config.option($T.PROFILE_FILE_SUPPLIER))", SdkClientOption.class); + builder.addCode(".profileName(config.option($T.PROFILE_NAME))", SdkClientOption.class); + builder.addCode(".defaultChecksumCalculation($T.WHEN_SUPPORTED)", RequestChecksumCalculation.class); + builder.addStatement(".resolve()"); + builder.endControlFlow(); + + builder.addStatement("return configuredChecksumCalculation"); + return builder.build(); + } + + private MethodSpec resolveResponseChecksumValidationMethod() { + + MethodSpec.Builder builder = MethodSpec.methodBuilder("resolveResponseChecksumValidation") + .addModifiers(PRIVATE) + .addParameter(SdkClientConfiguration.class, "config") + .returns(ResponseChecksumValidation.class); + + builder.addStatement("$T configuredChecksumValidation = config.option($T.RESPONSE_CHECKSUM_VALIDATION)", + ResponseChecksumValidation.class, SdkClientOption.class); + + builder.beginControlFlow("if (configuredChecksumValidation == null)"); + builder.addCode("configuredChecksumValidation = $T.create()", ResponseChecksumValidationResolver.class); + builder.addCode(".profileFile(config.option($T.PROFILE_FILE_SUPPLIER))", SdkClientOption.class); + builder.addCode(".profileName(config.option($T.PROFILE_NAME))", SdkClientOption.class); + builder.addCode(".defaultChecksumValidation($T.WHEN_SUPPORTED)", ResponseChecksumValidation.class); + builder.addStatement(".resolve()"); + builder.endControlFlow(); + + builder.addStatement("return configuredChecksumValidation"); + return builder.build(); + } + private String internalPluginClass(String internalPlugin) { int openParenthesisIndex = internalPlugin.indexOf('('); if (openParenthesisIndex == -1) { diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderInterface.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderInterface.java index 7cc43e51a587..2f1b735fa939 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderInterface.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/builder/BaseClientBuilderInterface.java @@ -39,6 +39,8 @@ import software.amazon.awssdk.codegen.poet.rules.EndpointParamsKnowledgeIndex; import software.amazon.awssdk.codegen.poet.rules.EndpointRulesSpecUtils; import software.amazon.awssdk.codegen.utils.AuthUtils; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidation; import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption; import software.amazon.awssdk.identity.spi.IdentityProvider; import software.amazon.awssdk.identity.spi.TokenIdentity; @@ -106,6 +108,14 @@ public TypeSpec poetSpec() { builder.addMethod(tokenIdentityProviderMethod()); } + if (hasRequestAlgorithmMember(model)) { + builder.addMethod(requestChecksumCalculationMethod()); + } + + if (hasResponseAlgorithms(model)) { + builder.addMethod(responseChecksumValidationMethod()); + } + return builder.build(); } @@ -183,6 +193,26 @@ private MethodSpec authSchemeProviderMethod() { .build(); } + private MethodSpec requestChecksumCalculationMethod() { + return MethodSpec.methodBuilder("requestChecksumCalculation") + .addModifiers(Modifier.PUBLIC, Modifier.DEFAULT) + .addParameter(RequestChecksumCalculation.class, "requestChecksumCalculation") + .addJavadoc("Configures the client behavior for request checksum calculation.") + .returns(TypeVariableName.get("B")) + .addStatement("throw new $T()", UnsupportedOperationException.class) + .build(); + } + + private MethodSpec responseChecksumValidationMethod() { + return MethodSpec.methodBuilder("responseChecksumValidation") + .addModifiers(Modifier.PUBLIC, Modifier.DEFAULT) + .addParameter(ResponseChecksumValidation.class, "responseChecksumValidation") + .addJavadoc("Configures the client behavior for response checksum validation.") + .returns(TypeVariableName.get("B")) + .addStatement("throw new $T()", UnsupportedOperationException.class) + .build(); + } + private MethodSpec clientContextParamSetter(String name, ClientContextParam param) { String setterName = Utils.unCapitalize(CodegenNamingUtils.pascalCase(name)); TypeName type = endpointRulesSpecUtils.toJavaType(param.getType()); @@ -255,4 +285,16 @@ private boolean hasSdkClientContextParams() { && model.getCustomizationConfig().getCustomClientContextParams() != null && !model.getCustomizationConfig().getCustomClientContextParams().isEmpty(); } + + private boolean hasRequestAlgorithmMember(IntermediateModel model) { + return model.getOperations().values().stream() + .anyMatch(opModel -> opModel.getHttpChecksum() != null + && opModel.getHttpChecksum().getRequestAlgorithmMember() != null); + } + + private boolean hasResponseAlgorithms(IntermediateModel model) { + return model.getOperations().values().stream() + .anyMatch(opModel -> opModel.getHttpChecksum() != null + && opModel.getHttpChecksum().getResponseAlgorithms() != null); + } } diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/traits/HttpChecksumTrait.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/traits/HttpChecksumTrait.java index 6806b40ca927..4e6768e45301 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/traits/HttpChecksumTrait.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/traits/HttpChecksumTrait.java @@ -16,23 +16,40 @@ package software.amazon.awssdk.codegen.poet.client.traits; import com.squareup.javapoet.CodeBlock; +import java.util.ArrayList; +import java.util.Comparator; import java.util.List; -import java.util.stream.Collectors; +import java.util.Locale; +import java.util.Map; +import java.util.function.Predicate; +import software.amazon.awssdk.checksums.DefaultChecksumAlgorithm; +import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel; import software.amazon.awssdk.codegen.model.intermediate.MemberModel; import software.amazon.awssdk.codegen.model.intermediate.OperationModel; import software.amazon.awssdk.core.client.handler.ClientExecutionParams; import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute; import software.amazon.awssdk.core.interceptor.trait.HttpChecksum; +import software.amazon.awssdk.core.protocol.MarshallLocation; +import software.amazon.awssdk.utils.CollectionUtils; +import software.amazon.awssdk.utils.ImmutableMap; /** * The logic for handling the Flexible "httpChecksum" trait within the code generator. */ public class HttpChecksumTrait { + private static final Map CHECKSUM_ALGORITHM_PRIORITY = + ImmutableMap.builder() + .put(DefaultChecksumAlgorithm.CRC32C.algorithmId(), 1) + .put(DefaultChecksumAlgorithm.CRC32.algorithmId(), 2) + .put(DefaultChecksumAlgorithm.CRC64NVME.algorithmId(), 3) + .put(DefaultChecksumAlgorithm.SHA1.algorithmId(), 4) + .put(DefaultChecksumAlgorithm.SHA256.algorithmId(), 5) + .build(); + private HttpChecksumTrait() { } - /** * Generate a ".putExecutionAttribute(...)" code-block for the provided operation model. This should be used within the * context of initializing {@link ClientExecutionParams}. @@ -40,58 +57,130 @@ private HttpChecksumTrait() { */ public static CodeBlock create(OperationModel operationModel) { - if (operationModel.getHttpChecksum() != null) { - - CodeBlock.Builder codeBuilder = CodeBlock.builder(); - codeBuilder.add(CodeBlock.of(".putExecutionAttribute($T.HTTP_CHECKSUM, $T.builder().requestChecksumRequired($L)", - SdkInternalExecutionAttribute.class, HttpChecksum.class, - operationModel.getHttpChecksum().isRequestChecksumRequired())); - - addFluentGetterToBuilder(operationModel, - codeBuilder, - operationModel.getHttpChecksum().getRequestAlgorithmMember(), - "requestAlgorithm"); - - addFluentGetterToBuilder(operationModel, - codeBuilder, - operationModel.getHttpChecksum().getRequestValidationModeMember(), - "requestValidationMode"); - - // loop to get the comma separated strings \"literals\" - List responseAlgorithms = operationModel.getHttpChecksum().getResponseAlgorithms(); - if (responseAlgorithms != null && !responseAlgorithms.isEmpty()) { - - codeBuilder.add(CodeBlock.of(".responseAlgorithms(")) - .add( - CodeBlock.of("$L", - responseAlgorithms.stream().collect( - Collectors.joining("\", \"", "\"", "\"")))) - .add(CodeBlock.of(")")); - } - codeBuilder.add(CodeBlock.of(".isRequestStreaming($L)", operationModel.getInputShape().isHasStreamingMember())); - return codeBuilder.add(CodeBlock.of(".build())")).build(); - } else { + software.amazon.awssdk.codegen.checksum.HttpChecksum httpChecksum = operationModel.getHttpChecksum(); + + if (httpChecksum == null) { return CodeBlock.of(""); } + + CodeBlock.Builder codeBuilder = CodeBlock.builder(); + codeBuilder.add(CodeBlock.of(".putExecutionAttribute($T.HTTP_CHECKSUM, $T.builder()" + + ".requestChecksumRequired($L).isRequestStreaming($L)", + SdkInternalExecutionAttribute.class, HttpChecksum.class, + httpChecksum.isRequestChecksumRequired(), + operationModel.getInputShape().isHasStreamingMember())); + + + String requestAlgorithmMember = httpChecksum.getRequestAlgorithmMember(); + if (requestAlgorithmMember != null) { + configureRequestChecksumCalculation(operationModel, requestAlgorithmMember, codeBuilder); + } + + String responseValidationModeMember = httpChecksum.getRequestValidationModeMember(); + if (responseValidationModeMember != null) { + configureResponseChecksumValidation(operationModel, responseValidationModeMember, codeBuilder, httpChecksum); + } + + return codeBuilder.add(CodeBlock.of(".build())")).build(); + } + + private static void configureResponseChecksumValidation(OperationModel operationModel, + String responseValidationModeMember, + CodeBlock.Builder codeBuilder, + software.amazon.awssdk.codegen.checksum.HttpChecksum httpChecksum) { + MemberModel checksumMember = + operationModel.getInputShape().tryFindMemberModelByC2jName( + responseValidationModeMember, true); + + if (checksumMember == null) { + throw new IllegalStateException(responseValidationModeMember + + " is not a member in " + + operationModel.getInputShape().getShapeName()); + } + codeBuilder.add(".requestValidationMode($N.$N())", + operationModel.getInput().getVariableName(), + checksumMember.getFluentGetterMethodName()); + + List responseAlgorithms = httpChecksum.getResponseAlgorithms(); + if (!CollectionUtils.isNullOrEmpty(responseAlgorithms)) { + addResponseAlgorithmsCodeBlock(responseAlgorithms, codeBuilder); + } + } + + private static void configureRequestChecksumCalculation(OperationModel operationModel, + String requestAlgorithmMember, + CodeBlock.Builder codeBuilder) { + MemberModel requestAlgorithm = + operationModel.getInputShape().tryFindMemberModelByC2jName( + requestAlgorithmMember, true); + + if (requestAlgorithm == null) { + throw new IllegalStateException(requestAlgorithmMember + + " is not a member in " + + operationModel.getInputShape().getShapeName()); + } + codeBuilder.add(".requestAlgorithm($N.$N())", + operationModel.getInput().getVariableName(), + requestAlgorithm.getFluentGetterMethodName()); + + if (requestAlgorithm.getHttp().getMarshallLocation() != MarshallLocation.HEADER) { + throw new IllegalStateException("Unsupported request algorithm location for " + requestAlgorithm); + } + + String headerName = requestAlgorithm.getHttp().getMarshallLocationName(); + + if (headerName == null) { + throw new IllegalStateException("Request algorithm header name is null for " + requestAlgorithm); + } + + codeBuilder.add(".requestAlgorithmHeader($S)", headerName); } - private static void addFluentGetterToBuilder(OperationModel operationModel, CodeBlock.Builder codeBuilder, - String requestValidationModeMemberInModel, String memberBuilderName) { + /** + * Sort the responseAlgorithms provided by the service by the time it takes to calculate a checksum for a given algorithm + * with the fastest-to-calculate algorithms first. + */ + private static void addResponseAlgorithmsCodeBlock(List responseAlgorithms, CodeBlock.Builder codeBuilder) { + responseAlgorithms.sort(Comparator.comparingInt(o -> CHECKSUM_ALGORITHM_PRIORITY.getOrDefault( + o.toUpperCase(Locale.US), Integer.MAX_VALUE))); - if (requestValidationModeMemberInModel != null) { - MemberModel requestValidationModeMember = - operationModel.getInputShape().tryFindMemberModelByC2jName( - requestValidationModeMemberInModel, true); + codeBuilder.add(CodeBlock.of(".responseAlgorithmsV2(")); + List responseAlgorithmsCodeBlocks = responseAlgorithmsCodeBlocks(responseAlgorithms); + for (int i = 0; i < responseAlgorithmsCodeBlocks.size(); i++) { + CodeBlock code = responseAlgorithmsCodeBlocks.get(i); + codeBuilder.add(code); + if (i != responseAlgorithmsCodeBlocks.size() - 1) { + codeBuilder.add(","); + } + } + codeBuilder.add(CodeBlock.of(")")); + } - if (requestValidationModeMember == null) { - throw new IllegalStateException(requestValidationModeMemberInModel - + " is not a member in " - + operationModel.getInputShape().getShapeName()); + private static List responseAlgorithmsCodeBlocks(List responseAlgorithms) { + List list = new ArrayList<>(); + for (String algo : responseAlgorithms) { + String algorithmName = algo.toUpperCase(Locale.US); + if (!CHECKSUM_ALGORITHM_PRIORITY.containsKey(algorithmName)) { + throw new UnsupportedOperationException("Unsupported algorithm: " + algorithmName); } - codeBuilder.add(".$L($N.$N())", - memberBuilderName, - operationModel.getInput().getVariableName(), - requestValidationModeMember.getFluentGetterMethodName()); + CodeBlock codeBlock = CodeBlock.of("$T.$L", DefaultChecksumAlgorithm.class, + algorithmName); + list.add(codeBlock); } + return list; + } + + public static boolean hasRequestAlgorithmMember(IntermediateModel model) { + Predicate requestCalculation = + httpChecksum -> httpChecksum.getRequestAlgorithmMember() != null || httpChecksum.isRequestChecksumRequired(); + return model.getOperations().values().stream() + .filter(operationModel -> operationModel.getHttpChecksum() != null) + .anyMatch(opModel -> requestCalculation.test(opModel.getHttpChecksum())); + } + + public static boolean hasResponseAlgorithms(IntermediateModel model) { + return model.getOperations().values().stream() + .anyMatch(opModel -> opModel.getHttpChecksum() != null + && opModel.getHttpChecksum().getResponseAlgorithms() != null); } } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/emitters/content-after-unused-import-removal.txt b/codegen/src/test/resources/software/amazon/awssdk/codegen/emitters/content-after-unused-import-removal.txt index 7a18b19a3148..202a88a1cf46 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/emitters/content-after-unused-import-removal.txt +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/emitters/content-after-unused-import-removal.txt @@ -25,6 +25,9 @@ import java.util.Set; import java.time.*; import java.time.format.*; +/* + * import something in the doc; + */ public class FileWithUnusedImports implements Predicate { private final List dates; public FileWithUnusedImports() { diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/emitters/content-before-unused-import-removal.txt b/codegen/src/test/resources/software/amazon/awssdk/codegen/emitters/content-before-unused-import-removal.txt index 5b1619f521be..5dd4a72f1375 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/emitters/content-before-unused-import-removal.txt +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/emitters/content-before-unused-import-removal.txt @@ -33,6 +33,9 @@ import java.util.ArrayList ; +/* + * import something in the doc; + */ public class FileWithUnusedImports implements Predicate { private final List dates; public FileWithUnusedImports() { diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-client-builder-class.java index 550968449ff0..4539aed74c0b 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-client-builder-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-client-builder-class.java @@ -19,6 +19,10 @@ import software.amazon.awssdk.codegen.poet.plugins.InternalTestPlugin1; import software.amazon.awssdk.codegen.poet.plugins.InternalTestPlugin2; import software.amazon.awssdk.core.SdkPlugin; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculationResolver; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidation; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidationResolver; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.core.client.config.SdkClientConfiguration; import software.amazon.awssdk.core.client.config.SdkClientOption; @@ -138,6 +142,24 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon } else { serviceConfigBuilder.accelerateModeEnabled(clientContextParams.get(JsonClientContextParams.ACCELERATE)); } + Boolean checksumValidationEnabled = serviceConfigBuilder.checksumValidationEnabled(); + if (checksumValidationEnabled != null) { + Validate.validState( + config.option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION) == null, + "Checksum behavior has been configured on both ServiceConfiguration and the client/global level. Please limit checksum behavior configuration to one location."); + Validate.validState( + config.option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION) == null, + "Checksum behavior has been configured on both ServiceConfiguration and the client/global level. Please limit checksum behavior configuration to one location."); + if (checksumValidationEnabled) { + config = config.toBuilder() + .option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION, RequestChecksumCalculation.WHEN_SUPPORTED) + .option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION, ResponseChecksumValidation.WHEN_SUPPORTED).build(); + } else { + config = config.toBuilder() + .option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION, RequestChecksumCalculation.WHEN_REQUIRED) + .option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION, ResponseChecksumValidation.WHEN_REQUIRED).build(); + } + } ServiceConfiguration finalServiceConfig = serviceConfigBuilder.build(); clientContextParams.put(JsonClientContextParams.USE_ARN_REGION, finalServiceConfig.useArnRegionEnabled()); clientContextParams.put(JsonClientContextParams.DISABLE_MULTI_REGION_ACCESS_POINTS, @@ -181,6 +203,9 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT)) .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED)) .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build()); + SdkClientConfiguration clientConfig = config; + builder.lazyOption(SdkClientOption.REQUEST_CHECKSUM_CALCULATION, c -> resolveRequestChecksumCalculation(clientConfig)); + builder.lazyOption(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION, c -> resolveResponseChecksumValidation(clientConfig)); return builder.build(); } @@ -220,6 +245,16 @@ private Map> authSchemes() { return schemes; } + public B requestChecksumCalculation(RequestChecksumCalculation requestChecksumCalculation) { + clientConfiguration.option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION, requestChecksumCalculation); + return thisBuilder(); + } + + public B responseChecksumValidation(ResponseChecksumValidation responseChecksumValidation) { + clientConfiguration.option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION, responseChecksumValidation); + return thisBuilder(); + } + public B serviceConfiguration(ServiceConfiguration serviceConfiguration) { clientConfiguration.option(SdkClientOption.SERVICE_CONFIGURATION, serviceConfiguration); return thisBuilder(); @@ -286,6 +321,28 @@ private List internalPlugins(SdkClientConfiguration config) { return internalPlugins; } + private RequestChecksumCalculation resolveRequestChecksumCalculation(SdkClientConfiguration config) { + RequestChecksumCalculation configuredChecksumCalculation = config.option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION); + if (configuredChecksumCalculation == null) { + configuredChecksumCalculation = RequestChecksumCalculationResolver.create() + .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER)) + .profileName(config.option(SdkClientOption.PROFILE_NAME)) + .defaultChecksumCalculation(RequestChecksumCalculation.WHEN_SUPPORTED).resolve(); + } + return configuredChecksumCalculation; + } + + private ResponseChecksumValidation resolveResponseChecksumValidation(SdkClientConfiguration config) { + ResponseChecksumValidation configuredChecksumValidation = config.option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION); + if (configuredChecksumValidation == null) { + configuredChecksumValidation = ResponseChecksumValidationResolver.create() + .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER)) + .profileName(config.option(SdkClientOption.PROFILE_NAME)) + .defaultChecksumValidation(ResponseChecksumValidation.WHEN_SUPPORTED).resolve(); + } + return configuredChecksumValidation; + } + protected static void validateClientOptions(SdkClientConfiguration c) { Validate.notNull(c.option(AwsClientOption.TOKEN_IDENTITY_PROVIDER), "The 'tokenProvider' must be configured in the client builder."); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-client-builder-endpoints-auth-params.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-client-builder-endpoints-auth-params.java index abf3132c7518..e48d848c4276 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-client-builder-endpoints-auth-params.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-client-builder-endpoints-auth-params.java @@ -17,6 +17,10 @@ import software.amazon.awssdk.awscore.endpoints.AccountIdEndpointModeResolver; import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; import software.amazon.awssdk.core.SdkPlugin; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculationResolver; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidation; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidationResolver; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.core.client.config.SdkClientConfiguration; import software.amazon.awssdk.core.client.config.SdkClientOption; @@ -118,6 +122,9 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT)) .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED)) .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build()); + SdkClientConfiguration clientConfig = config; + builder.lazyOption(SdkClientOption.REQUEST_CHECKSUM_CALCULATION, c -> resolveRequestChecksumCalculation(clientConfig)); + builder.lazyOption(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION, c -> resolveResponseChecksumValidation(clientConfig)); return builder.build(); } @@ -159,6 +166,16 @@ private Map> authSchemes() { return schemes; } + public B requestChecksumCalculation(RequestChecksumCalculation requestChecksumCalculation) { + clientConfiguration.option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION, requestChecksumCalculation); + return thisBuilder(); + } + + public B responseChecksumValidation(ResponseChecksumValidation responseChecksumValidation) { + clientConfiguration.option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION, responseChecksumValidation); + return thisBuilder(); + } + public B booleanContextParam(Boolean booleanContextParam) { clientContextParams.put(QueryClientContextParams.BOOLEAN_CONTEXT_PARAM, booleanContextParam); return thisBuilder(); @@ -233,6 +250,28 @@ private AccountIdEndpointMode resolveAccountIdEndpointMode(SdkClientConfiguratio return configuredMode; } + private RequestChecksumCalculation resolveRequestChecksumCalculation(SdkClientConfiguration config) { + RequestChecksumCalculation configuredChecksumCalculation = config.option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION); + if (configuredChecksumCalculation == null) { + configuredChecksumCalculation = RequestChecksumCalculationResolver.create() + .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER)) + .profileName(config.option(SdkClientOption.PROFILE_NAME)) + .defaultChecksumCalculation(RequestChecksumCalculation.WHEN_SUPPORTED).resolve(); + } + return configuredChecksumCalculation; + } + + private ResponseChecksumValidation resolveResponseChecksumValidation(SdkClientConfiguration config) { + ResponseChecksumValidation configuredChecksumValidation = config.option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION); + if (configuredChecksumValidation == null) { + configuredChecksumValidation = ResponseChecksumValidationResolver.create() + .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER)) + .profileName(config.option(SdkClientOption.PROFILE_NAME)) + .defaultChecksumValidation(ResponseChecksumValidation.WHEN_SUPPORTED).resolve(); + } + return configuredChecksumValidation; + } + protected static void validateClientOptions(SdkClientConfiguration c) { Validate.notNull(c.option(AwsClientOption.TOKEN_IDENTITY_PROVIDER), "The 'tokenProvider' must be configured in the client builder."); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-composed-sync-default-client-builder.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-composed-sync-default-client-builder.java index f001f47d6824..c441fcd575e4 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-composed-sync-default-client-builder.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-composed-sync-default-client-builder.java @@ -15,6 +15,10 @@ import software.amazon.awssdk.awscore.endpoint.AwsClientEndpointProvider; import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; import software.amazon.awssdk.core.SdkPlugin; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculationResolver; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidation; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidationResolver; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.core.client.config.SdkClientConfiguration; import software.amazon.awssdk.core.client.config.SdkClientOption; @@ -122,6 +126,9 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT)) .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED)) .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build()); + SdkClientConfiguration clientConfig = config; + builder.lazyOption(SdkClientOption.REQUEST_CHECKSUM_CALCULATION, c -> resolveRequestChecksumCalculation(clientConfig)); + builder.lazyOption(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION, c -> resolveResponseChecksumValidation(clientConfig)); return builder.build(); } @@ -161,6 +168,16 @@ private Map> authSchemes() { return schemes; } + public B requestChecksumCalculation(RequestChecksumCalculation requestChecksumCalculation) { + clientConfiguration.option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION, requestChecksumCalculation); + return thisBuilder(); + } + + public B responseChecksumValidation(ResponseChecksumValidation responseChecksumValidation) { + clientConfiguration.option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION, responseChecksumValidation); + return thisBuilder(); + } + public B customParameter(Boolean customParameter) { clientContextParams.put(JsonClientContextParams.CUSTOM_PARAMETER, customParameter); return thisBuilder(); @@ -223,6 +240,28 @@ private List internalPlugins(SdkClientConfiguration config) { return Collections.emptyList(); } + private RequestChecksumCalculation resolveRequestChecksumCalculation(SdkClientConfiguration config) { + RequestChecksumCalculation configuredChecksumCalculation = config.option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION); + if (configuredChecksumCalculation == null) { + configuredChecksumCalculation = RequestChecksumCalculationResolver.create() + .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER)) + .profileName(config.option(SdkClientOption.PROFILE_NAME)) + .defaultChecksumCalculation(RequestChecksumCalculation.WHEN_SUPPORTED).resolve(); + } + return configuredChecksumCalculation; + } + + private ResponseChecksumValidation resolveResponseChecksumValidation(SdkClientConfiguration config) { + ResponseChecksumValidation configuredChecksumValidation = config.option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION); + if (configuredChecksumValidation == null) { + configuredChecksumValidation = ResponseChecksumValidationResolver.create() + .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER)) + .profileName(config.option(SdkClientOption.PROFILE_NAME)) + .defaultChecksumValidation(ResponseChecksumValidation.WHEN_SUPPORTED).resolve(); + } + return configuredChecksumValidation; + } + protected static void validateClientOptions(SdkClientConfiguration c) { Validate.notNull(c.option(AwsClientOption.TOKEN_IDENTITY_PROVIDER), "The 'tokenProvider' must be configured in the client builder."); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-query-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-query-client-builder-class.java index 6f11b3364aba..724eb838439d 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-query-client-builder-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/sra/test-query-client-builder-class.java @@ -17,6 +17,10 @@ import software.amazon.awssdk.awscore.endpoints.AccountIdEndpointModeResolver; import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; import software.amazon.awssdk.core.SdkPlugin; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculationResolver; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidation; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidationResolver; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.core.client.config.SdkClientConfiguration; import software.amazon.awssdk.core.client.config.SdkClientOption; @@ -117,6 +121,9 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT)) .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED)) .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build()); + SdkClientConfiguration clientConfig = config; + builder.lazyOption(SdkClientOption.REQUEST_CHECKSUM_CALCULATION, c -> resolveRequestChecksumCalculation(clientConfig)); + builder.lazyOption(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION, c -> resolveResponseChecksumValidation(clientConfig)); return builder.build(); } @@ -156,6 +163,16 @@ private Map> authSchemes() { return schemes; } + public B requestChecksumCalculation(RequestChecksumCalculation requestChecksumCalculation) { + clientConfiguration.option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION, requestChecksumCalculation); + return thisBuilder(); + } + + public B responseChecksumValidation(ResponseChecksumValidation responseChecksumValidation) { + clientConfiguration.option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION, responseChecksumValidation); + return thisBuilder(); + } + public B booleanContextParam(Boolean booleanContextParam) { clientContextParams.put(QueryClientContextParams.BOOLEAN_CONTEXT_PARAM, booleanContextParam); return thisBuilder(); @@ -230,6 +247,28 @@ private AccountIdEndpointMode resolveAccountIdEndpointMode(SdkClientConfiguratio return configuredMode; } + private RequestChecksumCalculation resolveRequestChecksumCalculation(SdkClientConfiguration config) { + RequestChecksumCalculation configuredChecksumCalculation = config.option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION); + if (configuredChecksumCalculation == null) { + configuredChecksumCalculation = RequestChecksumCalculationResolver.create() + .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER)) + .profileName(config.option(SdkClientOption.PROFILE_NAME)) + .defaultChecksumCalculation(RequestChecksumCalculation.WHEN_SUPPORTED).resolve(); + } + return configuredChecksumCalculation; + } + + private ResponseChecksumValidation resolveResponseChecksumValidation(SdkClientConfiguration config) { + ResponseChecksumValidation configuredChecksumValidation = config.option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION); + if (configuredChecksumValidation == null) { + configuredChecksumValidation = ResponseChecksumValidationResolver.create() + .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER)) + .profileName(config.option(SdkClientOption.PROFILE_NAME)) + .defaultChecksumValidation(ResponseChecksumValidation.WHEN_SUPPORTED).resolve(); + } + return configuredChecksumValidation; + } + protected static void validateClientOptions(SdkClientConfiguration c) { Validate.notNull(c.option(AwsClientOption.TOKEN_IDENTITY_PROVIDER), "The 'tokenProvider' must be configured in the client builder."); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-client-builder-class.java index ca26f0321aec..8e6fae2e8c5a 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-client-builder-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-client-builder-class.java @@ -19,6 +19,10 @@ import software.amazon.awssdk.codegen.poet.plugins.InternalTestPlugin1; import software.amazon.awssdk.codegen.poet.plugins.InternalTestPlugin2; import software.amazon.awssdk.core.SdkPlugin; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculationResolver; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidation; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidationResolver; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption; import software.amazon.awssdk.core.client.config.SdkClientConfiguration; @@ -131,6 +135,24 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon } else { serviceConfigBuilder.accelerateModeEnabled(clientContextParams.get(JsonClientContextParams.ACCELERATE)); } + Boolean checksumValidationEnabled = serviceConfigBuilder.checksumValidationEnabled(); + if (checksumValidationEnabled != null) { + Validate.validState( + config.option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION) == null, + "Checksum behavior has been configured on both ServiceConfiguration and the client/global level. Please limit checksum behavior configuration to one location."); + Validate.validState( + config.option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION) == null, + "Checksum behavior has been configured on both ServiceConfiguration and the client/global level. Please limit checksum behavior configuration to one location."); + if (checksumValidationEnabled) { + config = config.toBuilder() + .option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION, RequestChecksumCalculation.WHEN_SUPPORTED) + .option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION, ResponseChecksumValidation.WHEN_SUPPORTED).build(); + } else { + config = config.toBuilder() + .option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION, RequestChecksumCalculation.WHEN_REQUIRED) + .option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION, ResponseChecksumValidation.WHEN_REQUIRED).build(); + } + } ServiceConfiguration finalServiceConfig = serviceConfigBuilder.build(); clientContextParams.put(JsonClientContextParams.USE_ARN_REGION, finalServiceConfig.useArnRegionEnabled()); clientContextParams.put(JsonClientContextParams.DISABLE_MULTI_REGION_ACCESS_POINTS, @@ -174,6 +196,9 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT)) .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED)) .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build()); + SdkClientConfiguration clientConfig = config; + builder.lazyOption(SdkClientOption.REQUEST_CHECKSUM_CALCULATION, c -> resolveRequestChecksumCalculation(clientConfig)); + builder.lazyOption(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION, c -> resolveResponseChecksumValidation(clientConfig)); return builder.build(); } @@ -190,6 +215,16 @@ private JsonEndpointProvider defaultEndpointProvider() { return JsonEndpointProvider.defaultProvider(); } + public B requestChecksumCalculation(RequestChecksumCalculation requestChecksumCalculation) { + clientConfiguration.option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION, requestChecksumCalculation); + return thisBuilder(); + } + + public B responseChecksumValidation(ResponseChecksumValidation responseChecksumValidation) { + clientConfiguration.option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION, responseChecksumValidation); + return thisBuilder(); + } + public B serviceConfiguration(ServiceConfiguration serviceConfiguration) { clientConfiguration.option(SdkClientOption.SERVICE_CONFIGURATION, serviceConfiguration); return thisBuilder(); @@ -260,6 +295,28 @@ private List internalPlugins(SdkClientConfiguration config) { return internalPlugins; } + private RequestChecksumCalculation resolveRequestChecksumCalculation(SdkClientConfiguration config) { + RequestChecksumCalculation configuredChecksumCalculation = config.option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION); + if (configuredChecksumCalculation == null) { + configuredChecksumCalculation = RequestChecksumCalculationResolver.create() + .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER)) + .profileName(config.option(SdkClientOption.PROFILE_NAME)) + .defaultChecksumCalculation(RequestChecksumCalculation.WHEN_SUPPORTED).resolve(); + } + return configuredChecksumCalculation; + } + + private ResponseChecksumValidation resolveResponseChecksumValidation(SdkClientConfiguration config) { + ResponseChecksumValidation configuredChecksumValidation = config.option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION); + if (configuredChecksumValidation == null) { + configuredChecksumValidation = ResponseChecksumValidationResolver.create() + .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER)) + .profileName(config.option(SdkClientOption.PROFILE_NAME)) + .defaultChecksumValidation(ResponseChecksumValidation.WHEN_SUPPORTED).resolve(); + } + return configuredChecksumValidation; + } + protected static void validateClientOptions(SdkClientConfiguration c) { Validate.notNull(c.option(SdkAdvancedClientOption.SIGNER), "The 'overrideConfiguration.advancedOption[SIGNER]' must be configured in the client builder."); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-client-builder-endpoints-auth-params.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-client-builder-endpoints-auth-params.java index ef0dce52a8ce..df04abcb8bef 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-client-builder-endpoints-auth-params.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-client-builder-endpoints-auth-params.java @@ -17,6 +17,10 @@ import software.amazon.awssdk.awscore.endpoints.AccountIdEndpointModeResolver; import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; import software.amazon.awssdk.core.SdkPlugin; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculationResolver; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidation; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidationResolver; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption; import software.amazon.awssdk.core.client.config.SdkClientConfiguration; @@ -110,6 +114,9 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT)) .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED)) .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build()); + SdkClientConfiguration clientConfig = config; + builder.lazyOption(SdkClientOption.REQUEST_CHECKSUM_CALCULATION, c -> resolveRequestChecksumCalculation(clientConfig)); + builder.lazyOption(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION, c -> resolveResponseChecksumValidation(clientConfig)); return builder.build(); } @@ -126,6 +133,16 @@ private QueryEndpointProvider defaultEndpointProvider() { return QueryEndpointProvider.defaultProvider(); } + public B requestChecksumCalculation(RequestChecksumCalculation requestChecksumCalculation) { + clientConfiguration.option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION, requestChecksumCalculation); + return thisBuilder(); + } + + public B responseChecksumValidation(ResponseChecksumValidation responseChecksumValidation) { + clientConfiguration.option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION, responseChecksumValidation); + return thisBuilder(); + } + public B booleanContextParam(Boolean booleanContextParam) { clientContextParams.put(QueryClientContextParams.BOOLEAN_CONTEXT_PARAM, booleanContextParam); return thisBuilder(); @@ -204,6 +221,28 @@ private AccountIdEndpointMode resolveAccountIdEndpointMode(SdkClientConfiguratio return configuredMode; } + private RequestChecksumCalculation resolveRequestChecksumCalculation(SdkClientConfiguration config) { + RequestChecksumCalculation configuredChecksumCalculation = config.option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION); + if (configuredChecksumCalculation == null) { + configuredChecksumCalculation = RequestChecksumCalculationResolver.create() + .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER)) + .profileName(config.option(SdkClientOption.PROFILE_NAME)) + .defaultChecksumCalculation(RequestChecksumCalculation.WHEN_SUPPORTED).resolve(); + } + return configuredChecksumCalculation; + } + + private ResponseChecksumValidation resolveResponseChecksumValidation(SdkClientConfiguration config) { + ResponseChecksumValidation configuredChecksumValidation = config.option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION); + if (configuredChecksumValidation == null) { + configuredChecksumValidation = ResponseChecksumValidationResolver.create() + .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER)) + .profileName(config.option(SdkClientOption.PROFILE_NAME)) + .defaultChecksumValidation(ResponseChecksumValidation.WHEN_SUPPORTED).resolve(); + } + return configuredChecksumValidation; + } + protected static void validateClientOptions(SdkClientConfiguration c) { Validate.notNull(c.option(SdkAdvancedClientOption.SIGNER), "The 'overrideConfiguration.advancedOption[SIGNER]' must be configured in the client builder."); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-client-builder-interface.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-client-builder-interface.java index 0e02ce46c2e4..006eeea2a2e5 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-client-builder-interface.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-client-builder-interface.java @@ -5,6 +5,8 @@ import software.amazon.awssdk.annotations.SdkPublicApi; import software.amazon.awssdk.auth.token.credentials.SdkTokenProvider; import software.amazon.awssdk.awscore.client.builder.AwsClientBuilder; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidation; import software.amazon.awssdk.identity.spi.IdentityProvider; import software.amazon.awssdk.identity.spi.TokenIdentity; import software.amazon.awssdk.services.json.auth.scheme.JsonAuthSchemeProvider; @@ -32,8 +34,8 @@ default B endpointProvider(JsonEndpointProvider endpointProvider) { } /** - * Set the {@link JsonAuthSchemeProvider} implementation that will be used by the client to resolve the auth scheme for - * each request. This is optional; if none is provided a default implementation will be used the SDK. + * Set the {@link JsonAuthSchemeProvider} implementation that will be used by the client to resolve the auth scheme + * for each request. This is optional; if none is provided a default implementation will be used the SDK. */ default B authSchemeProvider(JsonAuthSchemeProvider authSchemeProvider) { throw new UnsupportedOperationException(); @@ -68,4 +70,18 @@ default B tokenProvider(SdkTokenProvider tokenProvider) { default B tokenProvider(IdentityProvider tokenProvider) { throw new UnsupportedOperationException(); } + + /** + * Configures the client behavior for request checksum calculation. + */ + default B requestChecksumCalculation(RequestChecksumCalculation requestChecksumCalculation) { + throw new UnsupportedOperationException(); + } + + /** + * Configures the client behavior for response checksum validation. + */ + default B responseChecksumValidation(ResponseChecksumValidation responseChecksumValidation) { + throw new UnsupportedOperationException(); + } } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-composed-sync-default-client-builder.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-composed-sync-default-client-builder.java index 848dc95f7a0a..912e516f6a0e 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-composed-sync-default-client-builder.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-composed-sync-default-client-builder.java @@ -15,6 +15,10 @@ import software.amazon.awssdk.awscore.endpoint.AwsClientEndpointProvider; import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; import software.amazon.awssdk.core.SdkPlugin; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculationResolver; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidation; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidationResolver; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption; import software.amazon.awssdk.core.client.config.SdkClientConfiguration; @@ -115,6 +119,9 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT)) .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED)) .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build()); + SdkClientConfiguration clientConfig = config; + builder.lazyOption(SdkClientOption.REQUEST_CHECKSUM_CALCULATION, c -> resolveRequestChecksumCalculation(clientConfig)); + builder.lazyOption(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION, c -> resolveResponseChecksumValidation(clientConfig)); return builder.build(); } @@ -131,6 +138,16 @@ private JsonEndpointProvider defaultEndpointProvider() { return JsonEndpointProvider.defaultProvider(); } + public B requestChecksumCalculation(RequestChecksumCalculation requestChecksumCalculation) { + clientConfiguration.option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION, requestChecksumCalculation); + return thisBuilder(); + } + + public B responseChecksumValidation(ResponseChecksumValidation responseChecksumValidation) { + clientConfiguration.option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION, responseChecksumValidation); + return thisBuilder(); + } + public B customParameter(Boolean customParameter) { clientContextParams.put(JsonClientContextParams.CUSTOM_PARAMETER, customParameter); return thisBuilder(); @@ -197,6 +214,28 @@ private List internalPlugins(SdkClientConfiguration config) { return Collections.emptyList(); } + private RequestChecksumCalculation resolveRequestChecksumCalculation(SdkClientConfiguration config) { + RequestChecksumCalculation configuredChecksumCalculation = config.option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION); + if (configuredChecksumCalculation == null) { + configuredChecksumCalculation = RequestChecksumCalculationResolver.create() + .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER)) + .profileName(config.option(SdkClientOption.PROFILE_NAME)) + .defaultChecksumCalculation(RequestChecksumCalculation.WHEN_SUPPORTED).resolve(); + } + return configuredChecksumCalculation; + } + + private ResponseChecksumValidation resolveResponseChecksumValidation(SdkClientConfiguration config) { + ResponseChecksumValidation configuredChecksumValidation = config.option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION); + if (configuredChecksumValidation == null) { + configuredChecksumValidation = ResponseChecksumValidationResolver.create() + .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER)) + .profileName(config.option(SdkClientOption.PROFILE_NAME)) + .defaultChecksumValidation(ResponseChecksumValidation.WHEN_SUPPORTED).resolve(); + } + return configuredChecksumValidation; + } + protected static void validateClientOptions(SdkClientConfiguration c) { Validate.notNull(c.option(SdkAdvancedClientOption.SIGNER), "The 'overrideConfiguration.advancedOption[SIGNER]' must be configured in the client builder."); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-customcontextparams-sync-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-customcontextparams-sync-client-builder-class.java index da8484341d0e..4f6feac826ac 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-customcontextparams-sync-client-builder-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-customcontextparams-sync-client-builder-class.java @@ -5,6 +5,8 @@ import software.amazon.awssdk.annotations.SdkPublicApi; import software.amazon.awssdk.auth.token.credentials.SdkTokenProvider; import software.amazon.awssdk.awscore.client.builder.AwsClientBuilder; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidation; import software.amazon.awssdk.identity.spi.IdentityProvider; import software.amazon.awssdk.identity.spi.TokenIdentity; import software.amazon.awssdk.services.json.auth.scheme.JsonAuthSchemeProvider; @@ -73,4 +75,18 @@ default B tokenProvider(SdkTokenProvider tokenProvider) { default B tokenProvider(IdentityProvider tokenProvider) { throw new UnsupportedOperationException(); } + + /** + * Configures the client behavior for request checksum calculation. + */ + default B requestChecksumCalculation(RequestChecksumCalculation requestChecksumCalculation) { + throw new UnsupportedOperationException(); + } + + /** + * Configures the client behavior for response checksum validation. + */ + default B responseChecksumValidation(ResponseChecksumValidation responseChecksumValidation) { + throw new UnsupportedOperationException(); + } } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-endpointparams-client-builder-interface.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-endpointparams-client-builder-interface.java index 2b8c8460e2c3..6ca2099d6b9b 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-endpointparams-client-builder-interface.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-endpointparams-client-builder-interface.java @@ -5,6 +5,8 @@ import software.amazon.awssdk.auth.token.credentials.SdkTokenProvider; import software.amazon.awssdk.awscore.client.builder.AwsClientBuilder; import software.amazon.awssdk.awscore.endpoints.AccountIdEndpointMode; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidation; import software.amazon.awssdk.identity.spi.IdentityProvider; import software.amazon.awssdk.identity.spi.TokenIdentity; import software.amazon.awssdk.services.query.auth.scheme.QueryAuthSchemeProvider; @@ -77,4 +79,18 @@ default B tokenProvider(SdkTokenProvider tokenProvider) { default B tokenProvider(IdentityProvider tokenProvider) { throw new UnsupportedOperationException(); } + + /** + * Configures the client behavior for request checksum calculation. + */ + default B requestChecksumCalculation(RequestChecksumCalculation requestChecksumCalculation) { + throw new UnsupportedOperationException(); + } + + /** + * Configures the client behavior for response checksum validation. + */ + default B responseChecksumValidation(ResponseChecksumValidation responseChecksumValidation) { + throw new UnsupportedOperationException(); + } } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-query-client-builder-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-query-client-builder-class.java index ef0dce52a8ce..df04abcb8bef 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-query-client-builder-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/builder/test-query-client-builder-class.java @@ -17,6 +17,10 @@ import software.amazon.awssdk.awscore.endpoints.AccountIdEndpointModeResolver; import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; import software.amazon.awssdk.core.SdkPlugin; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculationResolver; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidation; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidationResolver; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption; import software.amazon.awssdk.core.client.config.SdkClientConfiguration; @@ -110,6 +114,9 @@ protected final SdkClientConfiguration finalizeServiceConfiguration(SdkClientCon c.get(ServiceMetadataAdvancedOption.DEFAULT_S3_US_EAST_1_REGIONAL_ENDPOINT)) .dualstackEnabled(c.get(AwsClientOption.DUALSTACK_ENDPOINT_ENABLED)) .fipsEnabled(c.get(AwsClientOption.FIPS_ENDPOINT_ENABLED)).build()); + SdkClientConfiguration clientConfig = config; + builder.lazyOption(SdkClientOption.REQUEST_CHECKSUM_CALCULATION, c -> resolveRequestChecksumCalculation(clientConfig)); + builder.lazyOption(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION, c -> resolveResponseChecksumValidation(clientConfig)); return builder.build(); } @@ -126,6 +133,16 @@ private QueryEndpointProvider defaultEndpointProvider() { return QueryEndpointProvider.defaultProvider(); } + public B requestChecksumCalculation(RequestChecksumCalculation requestChecksumCalculation) { + clientConfiguration.option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION, requestChecksumCalculation); + return thisBuilder(); + } + + public B responseChecksumValidation(ResponseChecksumValidation responseChecksumValidation) { + clientConfiguration.option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION, responseChecksumValidation); + return thisBuilder(); + } + public B booleanContextParam(Boolean booleanContextParam) { clientContextParams.put(QueryClientContextParams.BOOLEAN_CONTEXT_PARAM, booleanContextParam); return thisBuilder(); @@ -204,6 +221,28 @@ private AccountIdEndpointMode resolveAccountIdEndpointMode(SdkClientConfiguratio return configuredMode; } + private RequestChecksumCalculation resolveRequestChecksumCalculation(SdkClientConfiguration config) { + RequestChecksumCalculation configuredChecksumCalculation = config.option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION); + if (configuredChecksumCalculation == null) { + configuredChecksumCalculation = RequestChecksumCalculationResolver.create() + .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER)) + .profileName(config.option(SdkClientOption.PROFILE_NAME)) + .defaultChecksumCalculation(RequestChecksumCalculation.WHEN_SUPPORTED).resolve(); + } + return configuredChecksumCalculation; + } + + private ResponseChecksumValidation resolveResponseChecksumValidation(SdkClientConfiguration config) { + ResponseChecksumValidation configuredChecksumValidation = config.option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION); + if (configuredChecksumValidation == null) { + configuredChecksumValidation = ResponseChecksumValidationResolver.create() + .profileFile(config.option(SdkClientOption.PROFILE_FILE_SUPPLIER)) + .profileName(config.option(SdkClientOption.PROFILE_NAME)) + .defaultChecksumValidation(ResponseChecksumValidation.WHEN_SUPPORTED).resolve(); + } + return configuredChecksumValidation; + } + protected static void validateClientOptions(SdkClientConfiguration c) { Validate.notNull(c.option(SdkAdvancedClientOption.SIGNER), "The 'overrideConfiguration.advancedOption[SIGNER]' must be configured in the client builder."); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query/service-2.json b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query/service-2.json index 10e881516df1..b67576928eea 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query/service-2.json +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/query/service-2.json @@ -423,7 +423,7 @@ "ChecksumAlgorithm":{ "shape":"ChecksumAlgorithm", "location":"header", - "locationName":"x-amz-checksum-algorithm" + "locationName":"x-amz-sdk-checksum-algorithm" } }, "payload":"Body" @@ -441,7 +441,7 @@ "ChecksumAlgorithm":{ "shape":"ChecksumAlgorithm", "location":"header", - "locationName":"x-amz-checksum-algorithm" + "locationName":"x-amz-sdk-checksum-algorithm" } }, "payload":"Body" diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/rest-json/customization.config b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/rest-json/customization.config index 683ddcaa682e..250560d3535f 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/rest-json/customization.config +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/rest-json/customization.config @@ -11,7 +11,8 @@ "hasUseArnRegionProperty": true, "hasMultiRegionEnabledProperty": true, "hasPathStyleAccessEnabledProperty":true, - "hasAccelerateModeEnabledProperty":true + "hasAccelerateModeEnabledProperty":true, + "hasChecksumValidationEnabledProperty":true }, "customRetryPolicy": "software.amazon.MyServiceRetryPolicy", "customRetryStrategy": "software.amazon.MyServiceRetryStrategy", diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/rest-json/service-2.json b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/rest-json/service-2.json index 82620e0da9bf..8d229d802943 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/rest-json/service-2.json +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/rest-json/service-2.json @@ -577,7 +577,7 @@ "ChecksumAlgorithm":{ "shape":"ChecksumAlgorithm", "location":"header", - "locationName":"x-amz-checksum-algorithm" + "locationName":"x-amz-sdk-checksum-algorithm" } }, "payload":"Body" @@ -595,7 +595,7 @@ "ChecksumAlgorithm":{ "shape":"ChecksumAlgorithm", "location":"header", - "locationName":"x-amz-checksum-algorithm" + "locationName":"x-amz-sdk-checksum-algorithm" } }, "payload":"stringMember" diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/xml/service-2.json b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/xml/service-2.json index bcc3b9796f47..cee9d180107a 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/xml/service-2.json +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/c2j/xml/service-2.json @@ -288,7 +288,7 @@ "ChecksumAlgorithm":{ "shape":"ChecksumAlgorithm", "location":"header", - "locationName":"x-amz-checksum-algorithm" + "locationName":"x-amz-sdk-checksum-algorithm" } }, "payload":"Body" @@ -306,7 +306,7 @@ "ChecksumAlgorithm":{ "shape":"ChecksumAlgorithm", "location":"header", - "locationName":"x-amz-checksum-algorithm" + "locationName":"x-amz-sdk-checksum-algorithm" } }, "payload":"stringMember" diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/sra/test-json-async-client-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/sra/test-json-async-client-class.java index 5958db5e6167..4a99f346bc6c 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/sra/test-json-async-client-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/sra/test-json-async-client-class.java @@ -26,6 +26,7 @@ import software.amazon.awssdk.awscore.internal.AwsProtocolMetadata; import software.amazon.awssdk.awscore.internal.AwsServiceProtocol; import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; +import software.amazon.awssdk.checksums.DefaultChecksumAlgorithm; import software.amazon.awssdk.core.CredentialType; import software.amazon.awssdk.core.RequestOverrideConfiguration; import software.amazon.awssdk.core.SdkPlugin; @@ -689,9 +690,10 @@ public CompletableFuture getOperationWithCheck .withMetricCollector(apiCallMetricCollector) .putExecutionAttribute( SdkInternalExecutionAttribute.HTTP_CHECKSUM, - HttpChecksum.builder().requestChecksumRequired(true) + HttpChecksum.builder().requestChecksumRequired(true).isRequestStreaming(false) .requestAlgorithm(getOperationWithChecksumRequest.checksumAlgorithmAsString()) - .isRequestStreaming(false).build()).withInput(getOperationWithChecksumRequest)); + .requestAlgorithmHeader("x-amz-sdk-checksum-algorithm").build()) + .withInput(getOperationWithChecksumRequest)); CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); }); @@ -1094,10 +1096,15 @@ public CompletableFuture putOperationWithChecksum( .withAsyncRequestBody(requestBody) .putExecutionAttribute( SdkInternalExecutionAttribute.HTTP_CHECKSUM, - HttpChecksum.builder().requestChecksumRequired(false) - .requestValidationMode(putOperationWithChecksumRequest.checksumModeAsString()) - .responseAlgorithms("CRC32C", "CRC32", "SHA1", "SHA256").isRequestStreaming(true) - .build()).withInput(putOperationWithChecksumRequest), asyncResponseTransformer); + HttpChecksum + .builder() + .requestChecksumRequired(false) + .isRequestStreaming(true) + .requestValidationMode(putOperationWithChecksumRequest.checksumModeAsString()) + .responseAlgorithmsV2(DefaultChecksumAlgorithm.CRC32C, + DefaultChecksumAlgorithm.CRC32, DefaultChecksumAlgorithm.SHA1, + DefaultChecksumAlgorithm.SHA256).build()) + .withInput(putOperationWithChecksumRequest), asyncResponseTransformer); AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { if (e != null) { diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/sra/test-json-client-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/sra/test-json-client-class.java index 2fd06ccb9d6d..2ac6c6ae6d23 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/sra/test-json-client-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/sra/test-json-client-class.java @@ -10,6 +10,7 @@ import software.amazon.awssdk.awscore.internal.AwsProtocolMetadata; import software.amazon.awssdk.awscore.internal.AwsServiceProtocol; import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; +import software.amazon.awssdk.checksums.DefaultChecksumAlgorithm; import software.amazon.awssdk.core.CredentialType; import software.amazon.awssdk.core.RequestOverrideConfiguration; import software.amazon.awssdk.core.SdkPlugin; @@ -315,9 +316,9 @@ public GetOperationWithChecksumResponse getOperationWithChecksum( .withMetricCollector(apiCallMetricCollector) .putExecutionAttribute( SdkInternalExecutionAttribute.HTTP_CHECKSUM, - HttpChecksum.builder().requestChecksumRequired(true) + HttpChecksum.builder().requestChecksumRequired(true).isRequestStreaming(false) .requestAlgorithm(getOperationWithChecksumRequest.checksumAlgorithmAsString()) - .isRequestStreaming(false).build()) + .requestAlgorithmHeader("x-amz-sdk-checksum-algorithm").build()) .withMarshaller(new GetOperationWithChecksumRequestMarshaller(protocolFactory))); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -596,11 +597,11 @@ public PaginatedOperationWithoutResultKeyResponse paginatedOperationWithoutResul * The content to send to the service. A {@link RequestBody} can be created using one of several factory * methods for various sources of data. For example, to create a request body from a file you can do the * following. - * + * *
      * {@code RequestBody.fromFile(new File("myfile.txt"))}
      * 
- * + * * See documentation in {@link RequestBody} for additional details and which sources of data are supported. * The service documentation for the request content is as follows ' *

@@ -663,10 +664,14 @@ public ReturnT putOperationWithChecksum(PutOperationWithChecksumReques .withMetricCollector(apiCallMetricCollector) .putExecutionAttribute( SdkInternalExecutionAttribute.HTTP_CHECKSUM, - HttpChecksum.builder().requestChecksumRequired(false) + HttpChecksum + .builder() + .requestChecksumRequired(false) + .isRequestStreaming(true) .requestValidationMode(putOperationWithChecksumRequest.checksumModeAsString()) - .responseAlgorithms("CRC32C", "CRC32", "SHA1", "SHA256").isRequestStreaming(true) - .build()) + .responseAlgorithmsV2(DefaultChecksumAlgorithm.CRC32C, + DefaultChecksumAlgorithm.CRC32, DefaultChecksumAlgorithm.SHA1, + DefaultChecksumAlgorithm.SHA256).build()) .withRequestBody(requestBody) .withMarshaller( StreamingRequestMarshaller.builder() diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/sra/test-query-async-client-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/sra/test-query-async-client-class.java index 1e5fd3a8ff1e..5c97f4ae619c 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/sra/test-query-async-client-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/sra/test-query-async-client-class.java @@ -16,6 +16,7 @@ import software.amazon.awssdk.awscore.internal.AwsProtocolMetadata; import software.amazon.awssdk.awscore.internal.AwsServiceProtocol; import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; +import software.amazon.awssdk.checksums.DefaultChecksumAlgorithm; import software.amazon.awssdk.codegen.internal.UtilsTest; import software.amazon.awssdk.core.CredentialType; import software.amazon.awssdk.core.RequestOverrideConfiguration; @@ -109,7 +110,7 @@ final class DefaultQueryAsyncClient implements QueryAsyncClient { private static final Logger log = LoggerFactory.getLogger(DefaultQueryAsyncClient.class); private static final AwsProtocolMetadata protocolMetadata = AwsProtocolMetadata.builder() - .serviceProtocol(AwsServiceProtocol.QUERY).build(); + .serviceProtocol(AwsServiceProtocol.QUERY).build(); private final AsyncClientHandler clientHandler; @@ -154,27 +155,27 @@ protected DefaultQueryAsyncClient(SdkClientConfiguration clientConfiguration) { public CompletableFuture aPostOperation(APostOperationRequest aPostOperationRequest) { SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(aPostOperationRequest, this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, aPostOperationRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "APostOperation"); HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(APostOperationResponse::builder); + .createResponseHandler(APostOperationResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); String hostPrefix = "foo-"; String resolvedHostExpression = "foo-"; CompletableFuture executeFuture = clientHandler - .execute(new ClientExecutionParams() - .withOperationName("APostOperation").withProtocolMetadata(protocolMetadata) - .withMarshaller(new APostOperationRequestMarshaller(protocolFactory)) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .hostPrefixExpression(resolvedHostExpression).withInput(aPostOperationRequest)); + .execute(new ClientExecutionParams() + .withOperationName("APostOperation").withProtocolMetadata(protocolMetadata) + .withMarshaller(new APostOperationRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .hostPrefixExpression(resolvedHostExpression).withInput(aPostOperationRequest)); CompletableFuture whenCompleteFuture = null; whenCompleteFuture = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -212,29 +213,29 @@ public CompletableFuture aPostOperation(APostOperationRe */ @Override public CompletableFuture aPostOperationWithOutput( - APostOperationWithOutputRequest aPostOperationWithOutputRequest) { + APostOperationWithOutputRequest aPostOperationWithOutputRequest) { SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(aPostOperationWithOutputRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, aPostOperationWithOutputRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "APostOperationWithOutput"); HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(APostOperationWithOutputResponse::builder); + .createResponseHandler(APostOperationWithOutputResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); CompletableFuture executeFuture = clientHandler - .execute(new ClientExecutionParams() - .withOperationName("APostOperationWithOutput").withProtocolMetadata(protocolMetadata) - .withMarshaller(new APostOperationWithOutputRequestMarshaller(protocolFactory)) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(aPostOperationWithOutputRequest)); + .execute(new ClientExecutionParams() + .withOperationName("APostOperationWithOutput").withProtocolMetadata(protocolMetadata) + .withMarshaller(new APostOperationWithOutputRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withInput(aPostOperationWithOutputRequest)); CompletableFuture whenCompleteFuture = null; whenCompleteFuture = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -268,29 +269,29 @@ public CompletableFuture aPostOperationWithOut */ @Override public CompletableFuture bearerAuthOperation( - BearerAuthOperationRequest bearerAuthOperationRequest) { + BearerAuthOperationRequest bearerAuthOperationRequest) { SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(bearerAuthOperationRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, bearerAuthOperationRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "BearerAuthOperation"); HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(BearerAuthOperationResponse::builder); + .createResponseHandler(BearerAuthOperationResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); CompletableFuture executeFuture = clientHandler - .execute(new ClientExecutionParams() - .withOperationName("BearerAuthOperation").withProtocolMetadata(protocolMetadata) - .withMarshaller(new BearerAuthOperationRequestMarshaller(protocolFactory)) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .credentialType(CredentialType.TOKEN).withRequestConfiguration(clientConfiguration) - .withMetricCollector(apiCallMetricCollector).withInput(bearerAuthOperationRequest)); + .execute(new ClientExecutionParams() + .withOperationName("BearerAuthOperation").withProtocolMetadata(protocolMetadata) + .withMarshaller(new BearerAuthOperationRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .credentialType(CredentialType.TOKEN).withRequestConfiguration(clientConfiguration) + .withMetricCollector(apiCallMetricCollector).withInput(bearerAuthOperationRequest)); CompletableFuture whenCompleteFuture = null; whenCompleteFuture = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -324,36 +325,37 @@ public CompletableFuture bearerAuthOperation( */ @Override public CompletableFuture getOperationWithChecksum( - GetOperationWithChecksumRequest getOperationWithChecksumRequest) { + GetOperationWithChecksumRequest getOperationWithChecksumRequest) { SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(getOperationWithChecksumRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, getOperationWithChecksumRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "GetOperationWithChecksum"); HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(GetOperationWithChecksumResponse::builder); + .createResponseHandler(GetOperationWithChecksumResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); CompletableFuture executeFuture = clientHandler - .execute(new ClientExecutionParams() - .withOperationName("GetOperationWithChecksum") - .withProtocolMetadata(protocolMetadata) - .withMarshaller(new GetOperationWithChecksumRequestMarshaller(protocolFactory)) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withMetricCollector(apiCallMetricCollector) - .putExecutionAttribute( - SdkInternalExecutionAttribute.HTTP_CHECKSUM, - HttpChecksum.builder().requestChecksumRequired(true) - .requestAlgorithm(getOperationWithChecksumRequest.checksumAlgorithmAsString()) - .isRequestStreaming(false).build()).withInput(getOperationWithChecksumRequest)); + .execute(new ClientExecutionParams() + .withOperationName("GetOperationWithChecksum") + .withProtocolMetadata(protocolMetadata) + .withMarshaller(new GetOperationWithChecksumRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler) + .withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration) + .withMetricCollector(apiCallMetricCollector) + .putExecutionAttribute( + SdkInternalExecutionAttribute.HTTP_CHECKSUM, + HttpChecksum.builder().requestChecksumRequired(true).isRequestStreaming(false) + .requestAlgorithm(getOperationWithChecksumRequest.checksumAlgorithmAsString()) + .requestAlgorithmHeader("x-amz-sdk-checksum-algorithm").build()) + .withInput(getOperationWithChecksumRequest)); CompletableFuture whenCompleteFuture = null; whenCompleteFuture = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -388,33 +390,33 @@ public CompletableFuture getOperationWithCheck */ @Override public CompletableFuture operationWithChecksumRequired( - OperationWithChecksumRequiredRequest operationWithChecksumRequiredRequest) { + OperationWithChecksumRequiredRequest operationWithChecksumRequiredRequest) { SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithChecksumRequiredRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, - operationWithChecksumRequiredRequest.overrideConfiguration().orElse(null)); + operationWithChecksumRequiredRequest.overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithChecksumRequired"); HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(OperationWithChecksumRequiredResponse::builder); + .createResponseHandler(OperationWithChecksumRequiredResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); CompletableFuture executeFuture = clientHandler - .execute(new ClientExecutionParams() - .withOperationName("OperationWithChecksumRequired") - .withProtocolMetadata(protocolMetadata) - .withMarshaller(new OperationWithChecksumRequiredRequestMarshaller(protocolFactory)) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withMetricCollector(apiCallMetricCollector) - .putExecutionAttribute(SdkInternalExecutionAttribute.HTTP_CHECKSUM_REQUIRED, - HttpChecksumRequired.create()).withInput(operationWithChecksumRequiredRequest)); + .execute(new ClientExecutionParams() + .withOperationName("OperationWithChecksumRequired") + .withProtocolMetadata(protocolMetadata) + .withMarshaller(new OperationWithChecksumRequiredRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler) + .withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration) + .withMetricCollector(apiCallMetricCollector) + .putExecutionAttribute(SdkInternalExecutionAttribute.HTTP_CHECKSUM_REQUIRED, + HttpChecksumRequired.create()).withInput(operationWithChecksumRequiredRequest)); CompletableFuture whenCompleteFuture = null; whenCompleteFuture = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -448,29 +450,29 @@ public CompletableFuture operationWithChe */ @Override public CompletableFuture operationWithContextParam( - OperationWithContextParamRequest operationWithContextParamRequest) { + OperationWithContextParamRequest operationWithContextParamRequest) { SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithContextParamRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, operationWithContextParamRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithContextParam"); HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(OperationWithContextParamResponse::builder); + .createResponseHandler(OperationWithContextParamResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); CompletableFuture executeFuture = clientHandler - .execute(new ClientExecutionParams() - .withOperationName("OperationWithContextParam").withProtocolMetadata(protocolMetadata) - .withMarshaller(new OperationWithContextParamRequestMarshaller(protocolFactory)) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(operationWithContextParamRequest)); + .execute(new ClientExecutionParams() + .withOperationName("OperationWithContextParam").withProtocolMetadata(protocolMetadata) + .withMarshaller(new OperationWithContextParamRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withInput(operationWithContextParamRequest)); CompletableFuture whenCompleteFuture = null; whenCompleteFuture = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -504,30 +506,30 @@ public CompletableFuture operationWithContext */ @Override public CompletableFuture operationWithCustomMember( - OperationWithCustomMemberRequest operationWithCustomMemberRequest) { + OperationWithCustomMemberRequest operationWithCustomMemberRequest) { operationWithCustomMemberRequest = UtilsTest.dummyRequestModifier(operationWithCustomMemberRequest); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithCustomMemberRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, operationWithCustomMemberRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithCustomMember"); HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(OperationWithCustomMemberResponse::builder); + .createResponseHandler(OperationWithCustomMemberResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); CompletableFuture executeFuture = clientHandler - .execute(new ClientExecutionParams() - .withOperationName("OperationWithCustomMember").withProtocolMetadata(protocolMetadata) - .withMarshaller(new OperationWithCustomMemberRequestMarshaller(protocolFactory)) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(operationWithCustomMemberRequest)); + .execute(new ClientExecutionParams() + .withOperationName("OperationWithCustomMember").withProtocolMetadata(protocolMetadata) + .withMarshaller(new OperationWithCustomMemberRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withInput(operationWithCustomMemberRequest)); CompletableFuture whenCompleteFuture = null; whenCompleteFuture = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -563,30 +565,30 @@ public CompletableFuture operationWithCustomM */ @Override public CompletableFuture operationWithCustomizedOperationContextParam( - OperationWithCustomizedOperationContextParamRequest operationWithCustomizedOperationContextParamRequest) { + OperationWithCustomizedOperationContextParamRequest operationWithCustomizedOperationContextParamRequest) { SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration( - operationWithCustomizedOperationContextParamRequest, this.clientConfiguration); + operationWithCustomizedOperationContextParamRequest, this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, - operationWithCustomizedOperationContextParamRequest.overrideConfiguration().orElse(null)); + operationWithCustomizedOperationContextParamRequest.overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithCustomizedOperationContextParam"); HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(OperationWithCustomizedOperationContextParamResponse::builder); + .createResponseHandler(OperationWithCustomizedOperationContextParamResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); CompletableFuture executeFuture = clientHandler - .execute(new ClientExecutionParams() - .withOperationName("OperationWithCustomizedOperationContextParam") - .withProtocolMetadata(protocolMetadata) - .withMarshaller(new OperationWithCustomizedOperationContextParamRequestMarshaller(protocolFactory)) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(operationWithCustomizedOperationContextParamRequest)); + .execute(new ClientExecutionParams() + .withOperationName("OperationWithCustomizedOperationContextParam") + .withProtocolMetadata(protocolMetadata) + .withMarshaller(new OperationWithCustomizedOperationContextParamRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withInput(operationWithCustomizedOperationContextParamRequest)); CompletableFuture whenCompleteFuture = null; whenCompleteFuture = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -622,29 +624,29 @@ public CompletableFuture o */ @Override public CompletableFuture operationWithMapOperationContextParam( - OperationWithMapOperationContextParamRequest operationWithMapOperationContextParamRequest) { + OperationWithMapOperationContextParamRequest operationWithMapOperationContextParamRequest) { SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithMapOperationContextParamRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, - operationWithMapOperationContextParamRequest.overrideConfiguration().orElse(null)); + operationWithMapOperationContextParamRequest.overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithMapOperationContextParam"); HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(OperationWithMapOperationContextParamResponse::builder); + .createResponseHandler(OperationWithMapOperationContextParamResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); CompletableFuture executeFuture = clientHandler - .execute(new ClientExecutionParams() - .withOperationName("OperationWithMapOperationContextParam").withProtocolMetadata(protocolMetadata) - .withMarshaller(new OperationWithMapOperationContextParamRequestMarshaller(protocolFactory)) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(operationWithMapOperationContextParamRequest)); + .execute(new ClientExecutionParams() + .withOperationName("OperationWithMapOperationContextParam").withProtocolMetadata(protocolMetadata) + .withMarshaller(new OperationWithMapOperationContextParamRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withInput(operationWithMapOperationContextParamRequest)); CompletableFuture whenCompleteFuture = null; whenCompleteFuture = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -678,29 +680,29 @@ public CompletableFuture operatio */ @Override public CompletableFuture operationWithNoneAuthType( - OperationWithNoneAuthTypeRequest operationWithNoneAuthTypeRequest) { + OperationWithNoneAuthTypeRequest operationWithNoneAuthTypeRequest) { SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithNoneAuthTypeRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, operationWithNoneAuthTypeRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithNoneAuthType"); HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(OperationWithNoneAuthTypeResponse::builder); + .createResponseHandler(OperationWithNoneAuthTypeResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); CompletableFuture executeFuture = clientHandler - .execute(new ClientExecutionParams() - .withOperationName("OperationWithNoneAuthType").withProtocolMetadata(protocolMetadata) - .withMarshaller(new OperationWithNoneAuthTypeRequestMarshaller(protocolFactory)) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(operationWithNoneAuthTypeRequest)); + .execute(new ClientExecutionParams() + .withOperationName("OperationWithNoneAuthType").withProtocolMetadata(protocolMetadata) + .withMarshaller(new OperationWithNoneAuthTypeRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withInput(operationWithNoneAuthTypeRequest)); CompletableFuture whenCompleteFuture = null; whenCompleteFuture = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -736,29 +738,29 @@ public CompletableFuture operationWithNoneAut */ @Override public CompletableFuture operationWithOperationContextParam( - OperationWithOperationContextParamRequest operationWithOperationContextParamRequest) { + OperationWithOperationContextParamRequest operationWithOperationContextParamRequest) { SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithOperationContextParamRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, - operationWithOperationContextParamRequest.overrideConfiguration().orElse(null)); + operationWithOperationContextParamRequest.overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithOperationContextParam"); HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(OperationWithOperationContextParamResponse::builder); + .createResponseHandler(OperationWithOperationContextParamResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); CompletableFuture executeFuture = clientHandler - .execute(new ClientExecutionParams() - .withOperationName("OperationWithOperationContextParam").withProtocolMetadata(protocolMetadata) - .withMarshaller(new OperationWithOperationContextParamRequestMarshaller(protocolFactory)) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(operationWithOperationContextParamRequest)); + .execute(new ClientExecutionParams() + .withOperationName("OperationWithOperationContextParam").withProtocolMetadata(protocolMetadata) + .withMarshaller(new OperationWithOperationContextParamRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withInput(operationWithOperationContextParamRequest)); CompletableFuture whenCompleteFuture = null; whenCompleteFuture = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -793,34 +795,34 @@ public CompletableFuture operationWi */ @Override public CompletableFuture operationWithRequestCompression( - OperationWithRequestCompressionRequest operationWithRequestCompressionRequest) { + OperationWithRequestCompressionRequest operationWithRequestCompressionRequest) { SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithRequestCompressionRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, - operationWithRequestCompressionRequest.overrideConfiguration().orElse(null)); + operationWithRequestCompressionRequest.overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithRequestCompression"); HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(OperationWithRequestCompressionResponse::builder); + .createResponseHandler(OperationWithRequestCompressionResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); CompletableFuture executeFuture = clientHandler - .execute(new ClientExecutionParams() - .withOperationName("OperationWithRequestCompression") - .withProtocolMetadata(protocolMetadata) - .withMarshaller(new OperationWithRequestCompressionRequestMarshaller(protocolFactory)) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withMetricCollector(apiCallMetricCollector) - .putExecutionAttribute(SdkInternalExecutionAttribute.REQUEST_COMPRESSION, - RequestCompression.builder().encodings("gzip").isStreaming(false).build()) - .withInput(operationWithRequestCompressionRequest)); + .execute(new ClientExecutionParams() + .withOperationName("OperationWithRequestCompression") + .withProtocolMetadata(protocolMetadata) + .withMarshaller(new OperationWithRequestCompressionRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler) + .withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration) + .withMetricCollector(apiCallMetricCollector) + .putExecutionAttribute(SdkInternalExecutionAttribute.REQUEST_COMPRESSION, + RequestCompression.builder().encodings("gzip").isStreaming(false).build()) + .withInput(operationWithRequestCompressionRequest)); CompletableFuture whenCompleteFuture = null; whenCompleteFuture = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -855,29 +857,29 @@ public CompletableFuture operationWithR */ @Override public CompletableFuture operationWithStaticContextParams( - OperationWithStaticContextParamsRequest operationWithStaticContextParamsRequest) { + OperationWithStaticContextParamsRequest operationWithStaticContextParamsRequest) { SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithStaticContextParamsRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, - operationWithStaticContextParamsRequest.overrideConfiguration().orElse(null)); + operationWithStaticContextParamsRequest.overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithStaticContextParams"); HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(OperationWithStaticContextParamsResponse::builder); + .createResponseHandler(OperationWithStaticContextParamsResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); CompletableFuture executeFuture = clientHandler - .execute(new ClientExecutionParams() - .withOperationName("OperationWithStaticContextParams").withProtocolMetadata(protocolMetadata) - .withMarshaller(new OperationWithStaticContextParamsRequestMarshaller(protocolFactory)) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(operationWithStaticContextParamsRequest)); + .execute(new ClientExecutionParams() + .withOperationName("OperationWithStaticContextParams").withProtocolMetadata(protocolMetadata) + .withMarshaller(new OperationWithStaticContextParamsRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withInput(operationWithStaticContextParamsRequest)); CompletableFuture whenCompleteFuture = null; whenCompleteFuture = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -929,52 +931,56 @@ public CompletableFuture operationWith */ @Override public CompletableFuture putOperationWithChecksum( - PutOperationWithChecksumRequest putOperationWithChecksumRequest, AsyncRequestBody requestBody, - AsyncResponseTransformer asyncResponseTransformer) { + PutOperationWithChecksumRequest putOperationWithChecksumRequest, AsyncRequestBody requestBody, + AsyncResponseTransformer asyncResponseTransformer) { SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(putOperationWithChecksumRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, putOperationWithChecksumRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "PutOperationWithChecksum"); Pair, CompletableFuture> pair = AsyncResponseTransformerUtils - .wrapWithEndOfStreamFuture(asyncResponseTransformer); + .wrapWithEndOfStreamFuture(asyncResponseTransformer); asyncResponseTransformer = pair.left(); CompletableFuture endOfStreamFuture = pair.right(); HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(PutOperationWithChecksumResponse::builder); + .createResponseHandler(PutOperationWithChecksumResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); CompletableFuture executeFuture = clientHandler.execute( - new ClientExecutionParams() - .withOperationName("PutOperationWithChecksum") - .withProtocolMetadata(protocolMetadata) - .withMarshaller( - AsyncStreamingRequestMarshaller.builder() - .delegateMarshaller(new PutOperationWithChecksumRequestMarshaller(protocolFactory)) - .asyncRequestBody(requestBody).build()) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withMetricCollector(apiCallMetricCollector) - .putExecutionAttribute( - SdkInternalExecutionAttribute.HTTP_CHECKSUM, - HttpChecksum.builder().requestChecksumRequired(false) - .requestValidationMode(putOperationWithChecksumRequest.checksumModeAsString()) - .responseAlgorithms("CRC32C", "CRC32", "SHA1", "SHA256").isRequestStreaming(true) - .build()).withAsyncRequestBody(requestBody) - .withInput(putOperationWithChecksumRequest), asyncResponseTransformer); + new ClientExecutionParams() + .withOperationName("PutOperationWithChecksum") + .withProtocolMetadata(protocolMetadata) + .withMarshaller( + AsyncStreamingRequestMarshaller.builder() + .delegateMarshaller(new PutOperationWithChecksumRequestMarshaller(protocolFactory)) + .asyncRequestBody(requestBody).build()) + .withResponseHandler(responseHandler) + .withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration) + .withMetricCollector(apiCallMetricCollector) + .putExecutionAttribute( + SdkInternalExecutionAttribute.HTTP_CHECKSUM, + HttpChecksum + .builder() + .requestChecksumRequired(false) + .isRequestStreaming(true) + .requestValidationMode(putOperationWithChecksumRequest.checksumModeAsString()) + .responseAlgorithmsV2(DefaultChecksumAlgorithm.CRC32C, + DefaultChecksumAlgorithm.CRC32, DefaultChecksumAlgorithm.SHA1, + DefaultChecksumAlgorithm.SHA256).build()).withAsyncRequestBody(requestBody) + .withInput(putOperationWithChecksumRequest), asyncResponseTransformer); CompletableFuture whenCompleteFuture = null; AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; whenCompleteFuture = executeFuture.whenComplete((r, e) -> { if (e != null) { runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", - () -> finalAsyncResponseTransformer.exceptionOccurred(e)); + () -> finalAsyncResponseTransformer.exceptionOccurred(e)); } endOfStreamFuture.whenComplete((r2, e2) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -984,7 +990,7 @@ public CompletableFuture putOperationWithChecksum( } catch (Throwable t) { AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", - () -> finalAsyncResponseTransformer.exceptionOccurred(t)); + () -> finalAsyncResponseTransformer.exceptionOccurred(t)); metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); return CompletableFutureUtils.failedFuture(t); } @@ -1017,33 +1023,33 @@ public CompletableFuture putOperationWithChecksum( */ @Override public CompletableFuture streamingInputOperation( - StreamingInputOperationRequest streamingInputOperationRequest, AsyncRequestBody requestBody) { + StreamingInputOperationRequest streamingInputOperationRequest, AsyncRequestBody requestBody) { SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(streamingInputOperationRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, streamingInputOperationRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "StreamingInputOperation"); HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(StreamingInputOperationResponse::builder); + .createResponseHandler(StreamingInputOperationResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); CompletableFuture executeFuture = clientHandler - .execute(new ClientExecutionParams() - .withOperationName("StreamingInputOperation") - .withProtocolMetadata(protocolMetadata) - .withMarshaller( - AsyncStreamingRequestMarshaller.builder() - .delegateMarshaller(new StreamingInputOperationRequestMarshaller(protocolFactory)) - .asyncRequestBody(requestBody).build()).withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler).withRequestConfiguration(clientConfiguration) - .withMetricCollector(apiCallMetricCollector).withAsyncRequestBody(requestBody) - .withInput(streamingInputOperationRequest)); + .execute(new ClientExecutionParams() + .withOperationName("StreamingInputOperation") + .withProtocolMetadata(protocolMetadata) + .withMarshaller( + AsyncStreamingRequestMarshaller.builder() + .delegateMarshaller(new StreamingInputOperationRequestMarshaller(protocolFactory)) + .asyncRequestBody(requestBody).build()).withResponseHandler(responseHandler) + .withErrorResponseHandler(errorResponseHandler).withRequestConfiguration(clientConfiguration) + .withMetricCollector(apiCallMetricCollector).withAsyncRequestBody(requestBody) + .withInput(streamingInputOperationRequest)); CompletableFuture whenCompleteFuture = null; whenCompleteFuture = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -1082,40 +1088,40 @@ public CompletableFuture streamingInputOperatio */ @Override public CompletableFuture streamingOutputOperation( - StreamingOutputOperationRequest streamingOutputOperationRequest, - AsyncResponseTransformer asyncResponseTransformer) { + StreamingOutputOperationRequest streamingOutputOperationRequest, + AsyncResponseTransformer asyncResponseTransformer) { SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(streamingOutputOperationRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, streamingOutputOperationRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "StreamingOutputOperation"); Pair, CompletableFuture> pair = AsyncResponseTransformerUtils - .wrapWithEndOfStreamFuture(asyncResponseTransformer); + .wrapWithEndOfStreamFuture(asyncResponseTransformer); asyncResponseTransformer = pair.left(); CompletableFuture endOfStreamFuture = pair.right(); HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(StreamingOutputOperationResponse::builder); + .createResponseHandler(StreamingOutputOperationResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); CompletableFuture executeFuture = clientHandler.execute( - new ClientExecutionParams() - .withOperationName("StreamingOutputOperation").withProtocolMetadata(protocolMetadata) - .withMarshaller(new StreamingOutputOperationRequestMarshaller(protocolFactory)) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(streamingOutputOperationRequest), asyncResponseTransformer); + new ClientExecutionParams() + .withOperationName("StreamingOutputOperation").withProtocolMetadata(protocolMetadata) + .withMarshaller(new StreamingOutputOperationRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withInput(streamingOutputOperationRequest), asyncResponseTransformer); CompletableFuture whenCompleteFuture = null; AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; whenCompleteFuture = executeFuture.whenComplete((r, e) -> { if (e != null) { runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", - () -> finalAsyncResponseTransformer.exceptionOccurred(e)); + () -> finalAsyncResponseTransformer.exceptionOccurred(e)); } endOfStreamFuture.whenComplete((r2, e2) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -1125,7 +1131,7 @@ public CompletableFuture streamingOutputOperation( } catch (Throwable t) { AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", - () -> finalAsyncResponseTransformer.exceptionOccurred(t)); + () -> finalAsyncResponseTransformer.exceptionOccurred(t)); metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); return CompletableFutureUtils.failedFuture(t); } @@ -1148,15 +1154,15 @@ public final String serviceName() { private AwsQueryProtocolFactory init() { return AwsQueryProtocolFactory - .builder() - .registerModeledException( - ExceptionMetadata.builder().errorCode("InvalidInput") - .exceptionBuilderSupplier(InvalidInputException::builder).httpStatusCode(400).build()) - .clientConfiguration(clientConfiguration).defaultServiceExceptionSupplier(QueryException::builder).build(); + .builder() + .registerModeledException( + ExceptionMetadata.builder().errorCode("InvalidInput") + .exceptionBuilderSupplier(InvalidInputException::builder).httpStatusCode(400).build()) + .clientConfiguration(clientConfiguration).defaultServiceExceptionSupplier(QueryException::builder).build(); } private static List resolveMetricPublishers(SdkClientConfiguration clientConfiguration, - RequestOverrideConfiguration requestOverrideConfiguration) { + RequestOverrideConfiguration requestOverrideConfiguration) { List publishers = null; if (requestOverrideConfiguration != null) { publishers = requestOverrideConfiguration.metricPublishers(); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/sra/test-query-client-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/sra/test-query-client-class.java index 922e2559ce82..5961432e145d 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/sra/test-query-client-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/sra/test-query-client-class.java @@ -10,6 +10,7 @@ import software.amazon.awssdk.awscore.internal.AwsProtocolMetadata; import software.amazon.awssdk.awscore.internal.AwsServiceProtocol; import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; +import software.amazon.awssdk.checksums.DefaultChecksumAlgorithm; import software.amazon.awssdk.codegen.internal.UtilsTest; import software.amazon.awssdk.core.CredentialType; import software.amazon.awssdk.core.RequestOverrideConfiguration; @@ -102,7 +103,7 @@ final class DefaultQueryClient implements QueryClient { private static final Logger log = Logger.loggerFor(DefaultQueryClient.class); private static final AwsProtocolMetadata protocolMetadata = AwsProtocolMetadata.builder() - .serviceProtocol(AwsServiceProtocol.QUERY).build(); + .serviceProtocol(AwsServiceProtocol.QUERY).build(); private final SyncClientHandler clientHandler; @@ -138,17 +139,17 @@ protected DefaultQueryClient(SdkClientConfiguration clientConfiguration) { */ @Override public APostOperationResponse aPostOperation(APostOperationRequest aPostOperationRequest) throws InvalidInputException, - AwsServiceException, SdkClientException, QueryException { + AwsServiceException, SdkClientException, QueryException { HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(APostOperationResponse::builder); + .createResponseHandler(APostOperationResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(aPostOperationRequest, this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, aPostOperationRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "APostOperation"); @@ -156,11 +157,11 @@ public APostOperationResponse aPostOperation(APostOperationRequest aPostOperatio String resolvedHostExpression = "foo-"; return clientHandler.execute(new ClientExecutionParams() - .withOperationName("APostOperation").withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .hostPrefixExpression(resolvedHostExpression).withRequestConfiguration(clientConfiguration) - .withInput(aPostOperationRequest).withMetricCollector(apiCallMetricCollector) - .withMarshaller(new APostOperationRequestMarshaller(protocolFactory))); + .withOperationName("APostOperation").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .hostPrefixExpression(resolvedHostExpression).withRequestConfiguration(clientConfiguration) + .withInput(aPostOperationRequest).withMetricCollector(apiCallMetricCollector) + .withMarshaller(new APostOperationRequestMarshaller(protocolFactory))); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); } @@ -188,30 +189,30 @@ public APostOperationResponse aPostOperation(APostOperationRequest aPostOperatio */ @Override public APostOperationWithOutputResponse aPostOperationWithOutput( - APostOperationWithOutputRequest aPostOperationWithOutputRequest) throws InvalidInputException, AwsServiceException, - SdkClientException, QueryException { + APostOperationWithOutputRequest aPostOperationWithOutputRequest) throws InvalidInputException, AwsServiceException, + SdkClientException, QueryException { HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(APostOperationWithOutputResponse::builder); + .createResponseHandler(APostOperationWithOutputResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(aPostOperationWithOutputRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, aPostOperationWithOutputRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "APostOperationWithOutput"); return clientHandler - .execute(new ClientExecutionParams() - .withOperationName("APostOperationWithOutput").withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withInput(aPostOperationWithOutputRequest) - .withMetricCollector(apiCallMetricCollector) - .withMarshaller(new APostOperationWithOutputRequestMarshaller(protocolFactory))); + .execute(new ClientExecutionParams() + .withOperationName("APostOperationWithOutput").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withInput(aPostOperationWithOutputRequest) + .withMetricCollector(apiCallMetricCollector) + .withMarshaller(new APostOperationWithOutputRequestMarshaller(protocolFactory))); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); } @@ -235,28 +236,28 @@ public APostOperationWithOutputResponse aPostOperationWithOutput( */ @Override public BearerAuthOperationResponse bearerAuthOperation(BearerAuthOperationRequest bearerAuthOperationRequest) - throws AwsServiceException, SdkClientException, QueryException { + throws AwsServiceException, SdkClientException, QueryException { HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(BearerAuthOperationResponse::builder); + .createResponseHandler(BearerAuthOperationResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(bearerAuthOperationRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, bearerAuthOperationRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "BearerAuthOperation"); return clientHandler.execute(new ClientExecutionParams() - .withOperationName("BearerAuthOperation").withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .credentialType(CredentialType.TOKEN).withRequestConfiguration(clientConfiguration) - .withInput(bearerAuthOperationRequest).withMetricCollector(apiCallMetricCollector) - .withMarshaller(new BearerAuthOperationRequestMarshaller(protocolFactory))); + .withOperationName("BearerAuthOperation").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .credentialType(CredentialType.TOKEN).withRequestConfiguration(clientConfiguration) + .withInput(bearerAuthOperationRequest).withMetricCollector(apiCallMetricCollector) + .withMarshaller(new BearerAuthOperationRequestMarshaller(protocolFactory))); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); } @@ -280,38 +281,38 @@ public BearerAuthOperationResponse bearerAuthOperation(BearerAuthOperationReques */ @Override public GetOperationWithChecksumResponse getOperationWithChecksum( - GetOperationWithChecksumRequest getOperationWithChecksumRequest) throws AwsServiceException, SdkClientException, - QueryException { + GetOperationWithChecksumRequest getOperationWithChecksumRequest) throws AwsServiceException, SdkClientException, + QueryException { HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(GetOperationWithChecksumResponse::builder); + .createResponseHandler(GetOperationWithChecksumResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(getOperationWithChecksumRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, getOperationWithChecksumRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "GetOperationWithChecksum"); return clientHandler - .execute(new ClientExecutionParams() - .withOperationName("GetOperationWithChecksum") - .withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withInput(getOperationWithChecksumRequest) - .withMetricCollector(apiCallMetricCollector) - .putExecutionAttribute( - SdkInternalExecutionAttribute.HTTP_CHECKSUM, - HttpChecksum.builder().requestChecksumRequired(true) - .requestAlgorithm(getOperationWithChecksumRequest.checksumAlgorithmAsString()) - .isRequestStreaming(false).build()) - .withMarshaller(new GetOperationWithChecksumRequestMarshaller(protocolFactory))); + .execute(new ClientExecutionParams() + .withOperationName("GetOperationWithChecksum") + .withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler) + .withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration) + .withInput(getOperationWithChecksumRequest) + .withMetricCollector(apiCallMetricCollector) + .putExecutionAttribute( + SdkInternalExecutionAttribute.HTTP_CHECKSUM, + HttpChecksum.builder().requestChecksumRequired(true).isRequestStreaming(false) + .requestAlgorithm(getOperationWithChecksumRequest.checksumAlgorithmAsString()) + .requestAlgorithmHeader("x-amz-sdk-checksum-algorithm").build()) + .withMarshaller(new GetOperationWithChecksumRequestMarshaller(protocolFactory))); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); } @@ -335,35 +336,35 @@ public GetOperationWithChecksumResponse getOperationWithChecksum( */ @Override public OperationWithChecksumRequiredResponse operationWithChecksumRequired( - OperationWithChecksumRequiredRequest operationWithChecksumRequiredRequest) throws AwsServiceException, - SdkClientException, QueryException { + OperationWithChecksumRequiredRequest operationWithChecksumRequiredRequest) throws AwsServiceException, + SdkClientException, QueryException { HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(OperationWithChecksumRequiredResponse::builder); + .createResponseHandler(OperationWithChecksumRequiredResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithChecksumRequiredRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, - operationWithChecksumRequiredRequest.overrideConfiguration().orElse(null)); + operationWithChecksumRequiredRequest.overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithChecksumRequired"); return clientHandler - .execute(new ClientExecutionParams() - .withOperationName("OperationWithChecksumRequired") - .withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withInput(operationWithChecksumRequiredRequest) - .withMetricCollector(apiCallMetricCollector) - .putExecutionAttribute(SdkInternalExecutionAttribute.HTTP_CHECKSUM_REQUIRED, - HttpChecksumRequired.create()) - .withMarshaller(new OperationWithChecksumRequiredRequestMarshaller(protocolFactory))); + .execute(new ClientExecutionParams() + .withOperationName("OperationWithChecksumRequired") + .withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler) + .withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration) + .withInput(operationWithChecksumRequiredRequest) + .withMetricCollector(apiCallMetricCollector) + .putExecutionAttribute(SdkInternalExecutionAttribute.HTTP_CHECKSUM_REQUIRED, + HttpChecksumRequired.create()) + .withMarshaller(new OperationWithChecksumRequiredRequestMarshaller(protocolFactory))); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); } @@ -387,30 +388,30 @@ public OperationWithChecksumRequiredResponse operationWithChecksumRequired( */ @Override public OperationWithContextParamResponse operationWithContextParam( - OperationWithContextParamRequest operationWithContextParamRequest) throws AwsServiceException, SdkClientException, - QueryException { + OperationWithContextParamRequest operationWithContextParamRequest) throws AwsServiceException, SdkClientException, + QueryException { HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(OperationWithContextParamResponse::builder); + .createResponseHandler(OperationWithContextParamResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithContextParamRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, operationWithContextParamRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithContextParam"); return clientHandler - .execute(new ClientExecutionParams() - .withOperationName("OperationWithContextParam").withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withInput(operationWithContextParamRequest) - .withMetricCollector(apiCallMetricCollector) - .withMarshaller(new OperationWithContextParamRequestMarshaller(protocolFactory))); + .execute(new ClientExecutionParams() + .withOperationName("OperationWithContextParam").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withInput(operationWithContextParamRequest) + .withMetricCollector(apiCallMetricCollector) + .withMarshaller(new OperationWithContextParamRequestMarshaller(protocolFactory))); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); } @@ -434,31 +435,31 @@ public OperationWithContextParamResponse operationWithContextParam( */ @Override public OperationWithCustomMemberResponse operationWithCustomMember( - OperationWithCustomMemberRequest operationWithCustomMemberRequest) throws AwsServiceException, SdkClientException, - QueryException { + OperationWithCustomMemberRequest operationWithCustomMemberRequest) throws AwsServiceException, SdkClientException, + QueryException { operationWithCustomMemberRequest = UtilsTest.dummyRequestModifier(operationWithCustomMemberRequest); HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(OperationWithCustomMemberResponse::builder); + .createResponseHandler(OperationWithCustomMemberResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithCustomMemberRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, operationWithCustomMemberRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithCustomMember"); return clientHandler - .execute(new ClientExecutionParams() - .withOperationName("OperationWithCustomMember").withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withInput(operationWithCustomMemberRequest) - .withMetricCollector(apiCallMetricCollector) - .withMarshaller(new OperationWithCustomMemberRequestMarshaller(protocolFactory))); + .execute(new ClientExecutionParams() + .withOperationName("OperationWithCustomMember").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withInput(operationWithCustomMemberRequest) + .withMetricCollector(apiCallMetricCollector) + .withMarshaller(new OperationWithCustomMemberRequestMarshaller(protocolFactory))); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); } @@ -483,31 +484,31 @@ public OperationWithCustomMemberResponse operationWithCustomMember( */ @Override public OperationWithCustomizedOperationContextParamResponse operationWithCustomizedOperationContextParam( - OperationWithCustomizedOperationContextParamRequest operationWithCustomizedOperationContextParamRequest) - throws AwsServiceException, SdkClientException, QueryException { + OperationWithCustomizedOperationContextParamRequest operationWithCustomizedOperationContextParamRequest) + throws AwsServiceException, SdkClientException, QueryException { HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(OperationWithCustomizedOperationContextParamResponse::builder); + .createResponseHandler(OperationWithCustomizedOperationContextParamResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration( - operationWithCustomizedOperationContextParamRequest, this.clientConfiguration); + operationWithCustomizedOperationContextParamRequest, this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, - operationWithCustomizedOperationContextParamRequest.overrideConfiguration().orElse(null)); + operationWithCustomizedOperationContextParamRequest.overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithCustomizedOperationContextParam"); return clientHandler - .execute(new ClientExecutionParams() - .withOperationName("OperationWithCustomizedOperationContextParam") - .withProtocolMetadata(protocolMetadata).withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler).withRequestConfiguration(clientConfiguration) - .withInput(operationWithCustomizedOperationContextParamRequest) - .withMetricCollector(apiCallMetricCollector) - .withMarshaller(new OperationWithCustomizedOperationContextParamRequestMarshaller(protocolFactory))); + .execute(new ClientExecutionParams() + .withOperationName("OperationWithCustomizedOperationContextParam") + .withProtocolMetadata(protocolMetadata).withResponseHandler(responseHandler) + .withErrorResponseHandler(errorResponseHandler).withRequestConfiguration(clientConfiguration) + .withInput(operationWithCustomizedOperationContextParamRequest) + .withMetricCollector(apiCallMetricCollector) + .withMarshaller(new OperationWithCustomizedOperationContextParamRequestMarshaller(protocolFactory))); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); } @@ -532,30 +533,30 @@ public OperationWithCustomizedOperationContextParamResponse operationWithCustomi */ @Override public OperationWithMapOperationContextParamResponse operationWithMapOperationContextParam( - OperationWithMapOperationContextParamRequest operationWithMapOperationContextParamRequest) - throws AwsServiceException, SdkClientException, QueryException { + OperationWithMapOperationContextParamRequest operationWithMapOperationContextParamRequest) + throws AwsServiceException, SdkClientException, QueryException { HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(OperationWithMapOperationContextParamResponse::builder); + .createResponseHandler(OperationWithMapOperationContextParamResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithMapOperationContextParamRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, - operationWithMapOperationContextParamRequest.overrideConfiguration().orElse(null)); + operationWithMapOperationContextParamRequest.overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithMapOperationContextParam"); return clientHandler - .execute(new ClientExecutionParams() - .withOperationName("OperationWithMapOperationContextParam").withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withInput(operationWithMapOperationContextParamRequest).withMetricCollector(apiCallMetricCollector) - .withMarshaller(new OperationWithMapOperationContextParamRequestMarshaller(protocolFactory))); + .execute(new ClientExecutionParams() + .withOperationName("OperationWithMapOperationContextParam").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration) + .withInput(operationWithMapOperationContextParamRequest).withMetricCollector(apiCallMetricCollector) + .withMarshaller(new OperationWithMapOperationContextParamRequestMarshaller(protocolFactory))); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); } @@ -579,30 +580,30 @@ public OperationWithMapOperationContextParamResponse operationWithMapOperationCo */ @Override public OperationWithNoneAuthTypeResponse operationWithNoneAuthType( - OperationWithNoneAuthTypeRequest operationWithNoneAuthTypeRequest) throws AwsServiceException, SdkClientException, - QueryException { + OperationWithNoneAuthTypeRequest operationWithNoneAuthTypeRequest) throws AwsServiceException, SdkClientException, + QueryException { HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(OperationWithNoneAuthTypeResponse::builder); + .createResponseHandler(OperationWithNoneAuthTypeResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithNoneAuthTypeRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, operationWithNoneAuthTypeRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithNoneAuthType"); return clientHandler - .execute(new ClientExecutionParams() - .withOperationName("OperationWithNoneAuthType").withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withInput(operationWithNoneAuthTypeRequest) - .withMetricCollector(apiCallMetricCollector) - .withMarshaller(new OperationWithNoneAuthTypeRequestMarshaller(protocolFactory))); + .execute(new ClientExecutionParams() + .withOperationName("OperationWithNoneAuthType").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withInput(operationWithNoneAuthTypeRequest) + .withMetricCollector(apiCallMetricCollector) + .withMarshaller(new OperationWithNoneAuthTypeRequestMarshaller(protocolFactory))); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); } @@ -627,30 +628,30 @@ public OperationWithNoneAuthTypeResponse operationWithNoneAuthType( */ @Override public OperationWithOperationContextParamResponse operationWithOperationContextParam( - OperationWithOperationContextParamRequest operationWithOperationContextParamRequest) throws AwsServiceException, - SdkClientException, QueryException { + OperationWithOperationContextParamRequest operationWithOperationContextParamRequest) throws AwsServiceException, + SdkClientException, QueryException { HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(OperationWithOperationContextParamResponse::builder); + .createResponseHandler(OperationWithOperationContextParamResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithOperationContextParamRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, - operationWithOperationContextParamRequest.overrideConfiguration().orElse(null)); + operationWithOperationContextParamRequest.overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithOperationContextParam"); return clientHandler - .execute(new ClientExecutionParams() - .withOperationName("OperationWithOperationContextParam").withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withInput(operationWithOperationContextParamRequest) - .withMetricCollector(apiCallMetricCollector) - .withMarshaller(new OperationWithOperationContextParamRequestMarshaller(protocolFactory))); + .execute(new ClientExecutionParams() + .withOperationName("OperationWithOperationContextParam").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withInput(operationWithOperationContextParamRequest) + .withMetricCollector(apiCallMetricCollector) + .withMarshaller(new OperationWithOperationContextParamRequestMarshaller(protocolFactory))); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); } @@ -674,35 +675,35 @@ public OperationWithOperationContextParamResponse operationWithOperationContextP */ @Override public OperationWithRequestCompressionResponse operationWithRequestCompression( - OperationWithRequestCompressionRequest operationWithRequestCompressionRequest) throws AwsServiceException, - SdkClientException, QueryException { + OperationWithRequestCompressionRequest operationWithRequestCompressionRequest) throws AwsServiceException, + SdkClientException, QueryException { HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(OperationWithRequestCompressionResponse::builder); + .createResponseHandler(OperationWithRequestCompressionResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithRequestCompressionRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, - operationWithRequestCompressionRequest.overrideConfiguration().orElse(null)); + operationWithRequestCompressionRequest.overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithRequestCompression"); return clientHandler - .execute(new ClientExecutionParams() - .withOperationName("OperationWithRequestCompression") - .withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withInput(operationWithRequestCompressionRequest) - .withMetricCollector(apiCallMetricCollector) - .putExecutionAttribute(SdkInternalExecutionAttribute.REQUEST_COMPRESSION, - RequestCompression.builder().encodings("gzip").isStreaming(false).build()) - .withMarshaller(new OperationWithRequestCompressionRequestMarshaller(protocolFactory))); + .execute(new ClientExecutionParams() + .withOperationName("OperationWithRequestCompression") + .withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler) + .withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration) + .withInput(operationWithRequestCompressionRequest) + .withMetricCollector(apiCallMetricCollector) + .putExecutionAttribute(SdkInternalExecutionAttribute.REQUEST_COMPRESSION, + RequestCompression.builder().encodings("gzip").isStreaming(false).build()) + .withMarshaller(new OperationWithRequestCompressionRequestMarshaller(protocolFactory))); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); } @@ -726,30 +727,30 @@ public OperationWithRequestCompressionResponse operationWithRequestCompression( */ @Override public OperationWithStaticContextParamsResponse operationWithStaticContextParams( - OperationWithStaticContextParamsRequest operationWithStaticContextParamsRequest) throws AwsServiceException, - SdkClientException, QueryException { + OperationWithStaticContextParamsRequest operationWithStaticContextParamsRequest) throws AwsServiceException, + SdkClientException, QueryException { HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(OperationWithStaticContextParamsResponse::builder); + .createResponseHandler(OperationWithStaticContextParamsResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithStaticContextParamsRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, - operationWithStaticContextParamsRequest.overrideConfiguration().orElse(null)); + operationWithStaticContextParamsRequest.overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithStaticContextParams"); return clientHandler - .execute(new ClientExecutionParams() - .withOperationName("OperationWithStaticContextParams").withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withInput(operationWithStaticContextParamsRequest) - .withMetricCollector(apiCallMetricCollector) - .withMarshaller(new OperationWithStaticContextParamsRequestMarshaller(protocolFactory))); + .execute(new ClientExecutionParams() + .withOperationName("OperationWithStaticContextParams").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withInput(operationWithStaticContextParamsRequest) + .withMetricCollector(apiCallMetricCollector) + .withMarshaller(new OperationWithStaticContextParamsRequestMarshaller(protocolFactory))); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); } @@ -799,43 +800,47 @@ public OperationWithStaticContextParamsResponse operationWithStaticContextParams */ @Override public ReturnT putOperationWithChecksum(PutOperationWithChecksumRequest putOperationWithChecksumRequest, - RequestBody requestBody, ResponseTransformer responseTransformer) - throws AwsServiceException, SdkClientException, QueryException { + RequestBody requestBody, ResponseTransformer responseTransformer) + throws AwsServiceException, SdkClientException, QueryException { HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(PutOperationWithChecksumResponse::builder); + .createResponseHandler(PutOperationWithChecksumResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(putOperationWithChecksumRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, putOperationWithChecksumRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "PutOperationWithChecksum"); return clientHandler - .execute(new ClientExecutionParams() - .withOperationName("PutOperationWithChecksum") - .withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withInput(putOperationWithChecksumRequest) - .withMetricCollector(apiCallMetricCollector) - .putExecutionAttribute( - SdkInternalExecutionAttribute.HTTP_CHECKSUM, - HttpChecksum.builder().requestChecksumRequired(false) - .requestValidationMode(putOperationWithChecksumRequest.checksumModeAsString()) - .responseAlgorithms("CRC32C", "CRC32", "SHA1", "SHA256").isRequestStreaming(true) - .build()) - .withRequestBody(requestBody) - .withMarshaller( - StreamingRequestMarshaller.builder() - .delegateMarshaller(new PutOperationWithChecksumRequestMarshaller(protocolFactory)) - .requestBody(requestBody).build())); + .execute(new ClientExecutionParams() + .withOperationName("PutOperationWithChecksum") + .withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler) + .withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration) + .withInput(putOperationWithChecksumRequest) + .withMetricCollector(apiCallMetricCollector) + .putExecutionAttribute( + SdkInternalExecutionAttribute.HTTP_CHECKSUM, + HttpChecksum + .builder() + .requestChecksumRequired(false) + .isRequestStreaming(true) + .requestValidationMode(putOperationWithChecksumRequest.checksumModeAsString()) + .responseAlgorithmsV2(DefaultChecksumAlgorithm.CRC32C, + DefaultChecksumAlgorithm.CRC32, DefaultChecksumAlgorithm.SHA1, + DefaultChecksumAlgorithm.SHA256).build()) + .withRequestBody(requestBody) + .withMarshaller( + StreamingRequestMarshaller.builder() + .delegateMarshaller(new PutOperationWithChecksumRequestMarshaller(protocolFactory)) + .requestBody(requestBody).build())); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); } @@ -870,36 +875,36 @@ public ReturnT putOperationWithChecksum(PutOperationWithChecksumReques */ @Override public StreamingInputOperationResponse streamingInputOperation(StreamingInputOperationRequest streamingInputOperationRequest, - RequestBody requestBody) throws AwsServiceException, SdkClientException, QueryException { + RequestBody requestBody) throws AwsServiceException, SdkClientException, QueryException { HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(StreamingInputOperationResponse::builder); + .createResponseHandler(StreamingInputOperationResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(streamingInputOperationRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, streamingInputOperationRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "StreamingInputOperation"); return clientHandler - .execute(new ClientExecutionParams() - .withOperationName("StreamingInputOperation") - .withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withInput(streamingInputOperationRequest) - .withMetricCollector(apiCallMetricCollector) - .withRequestBody(requestBody) - .withMarshaller( - StreamingRequestMarshaller.builder() - .delegateMarshaller(new StreamingInputOperationRequestMarshaller(protocolFactory)) - .requestBody(requestBody).build())); + .execute(new ClientExecutionParams() + .withOperationName("StreamingInputOperation") + .withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler) + .withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration) + .withInput(streamingInputOperationRequest) + .withMetricCollector(apiCallMetricCollector) + .withRequestBody(requestBody) + .withMarshaller( + StreamingRequestMarshaller.builder() + .delegateMarshaller(new StreamingInputOperationRequestMarshaller(protocolFactory)) + .requestBody(requestBody).build())); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); } @@ -930,30 +935,30 @@ public StreamingInputOperationResponse streamingInputOperation(StreamingInputOpe */ @Override public ReturnT streamingOutputOperation(StreamingOutputOperationRequest streamingOutputOperationRequest, - ResponseTransformer responseTransformer) throws AwsServiceException, - SdkClientException, QueryException { + ResponseTransformer responseTransformer) throws AwsServiceException, + SdkClientException, QueryException { HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(StreamingOutputOperationResponse::builder); + .createResponseHandler(StreamingOutputOperationResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(streamingOutputOperationRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, streamingOutputOperationRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "StreamingOutputOperation"); return clientHandler.execute( - new ClientExecutionParams() - .withOperationName("StreamingOutputOperation").withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withInput(streamingOutputOperationRequest) - .withMetricCollector(apiCallMetricCollector) - .withMarshaller(new StreamingOutputOperationRequestMarshaller(protocolFactory)), responseTransformer); + new ClientExecutionParams() + .withOperationName("StreamingOutputOperation").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withInput(streamingOutputOperationRequest) + .withMetricCollector(apiCallMetricCollector) + .withMarshaller(new StreamingOutputOperationRequestMarshaller(protocolFactory)), responseTransformer); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); } @@ -978,7 +983,7 @@ public final String serviceName() { } private static List resolveMetricPublishers(SdkClientConfiguration clientConfiguration, - RequestOverrideConfiguration requestOverrideConfiguration) { + RequestOverrideConfiguration requestOverrideConfiguration) { List publishers = null; if (requestOverrideConfiguration != null) { publishers = requestOverrideConfiguration.metricPublishers(); @@ -1031,11 +1036,11 @@ private SdkClientConfiguration updateSdkClientConfiguration(SdkRequest request, private AwsQueryProtocolFactory init() { return AwsQueryProtocolFactory - .builder() - .registerModeledException( - ExceptionMetadata.builder().errorCode("InvalidInput") - .exceptionBuilderSupplier(InvalidInputException::builder).httpStatusCode(400).build()) - .clientConfiguration(clientConfiguration).defaultServiceExceptionSupplier(QueryException::builder).build(); + .builder() + .registerModeledException( + ExceptionMetadata.builder().errorCode("InvalidInput") + .exceptionBuilderSupplier(InvalidInputException::builder).httpStatusCode(400).build()) + .clientConfiguration(clientConfiguration).defaultServiceExceptionSupplier(QueryException::builder).build(); } @Override diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/sra/test-xml-async-client-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/sra/test-xml-async-client-class.java index 980d91a00f76..c082dd8f8ab0 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/sra/test-xml-async-client-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/sra/test-xml-async-client-class.java @@ -19,6 +19,7 @@ import software.amazon.awssdk.awscore.internal.AwsProtocolMetadata; import software.amazon.awssdk.awscore.internal.AwsServiceProtocol; import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; +import software.amazon.awssdk.checksums.DefaultChecksumAlgorithm; import software.amazon.awssdk.core.CredentialType; import software.amazon.awssdk.core.RequestOverrideConfiguration; import software.amazon.awssdk.core.Response; @@ -422,9 +423,10 @@ public CompletableFuture getOperationWithCheck .withMetricCollector(apiCallMetricCollector) .putExecutionAttribute( SdkInternalExecutionAttribute.HTTP_CHECKSUM, - HttpChecksum.builder().requestChecksumRequired(true) + HttpChecksum.builder().requestChecksumRequired(true).isRequestStreaming(false) .requestAlgorithm(getOperationWithChecksumRequest.checksumAlgorithmAsString()) - .isRequestStreaming(false).build()).withInput(getOperationWithChecksumRequest)); + .requestAlgorithmHeader("x-amz-sdk-checksum-algorithm").build()) + .withInput(getOperationWithChecksumRequest)); CompletableFuture whenCompleteFuture = null; whenCompleteFuture = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -689,10 +691,14 @@ public CompletableFuture putOperationWithChecksum( .withMetricCollector(apiCallMetricCollector) .putExecutionAttribute( SdkInternalExecutionAttribute.HTTP_CHECKSUM, - HttpChecksum.builder().requestChecksumRequired(false) + HttpChecksum + .builder() + .requestChecksumRequired(false) + .isRequestStreaming(true) .requestValidationMode(putOperationWithChecksumRequest.checksumModeAsString()) - .responseAlgorithms("CRC32C", "CRC32", "SHA1", "SHA256").isRequestStreaming(true) - .build()).withAsyncRequestBody(requestBody) + .responseAlgorithmsV2(DefaultChecksumAlgorithm.CRC32C, + DefaultChecksumAlgorithm.CRC32, DefaultChecksumAlgorithm.SHA1, + DefaultChecksumAlgorithm.SHA256).build()).withAsyncRequestBody(requestBody) .withInput(putOperationWithChecksumRequest), asyncResponseTransformer); CompletableFuture whenCompleteFuture = null; AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/sra/test-xml-client-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/sra/test-xml-client-class.java index 396ffee0814c..457d5a36c2c3 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/sra/test-xml-client-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/sra/test-xml-client-class.java @@ -10,6 +10,7 @@ import software.amazon.awssdk.awscore.internal.AwsProtocolMetadata; import software.amazon.awssdk.awscore.internal.AwsServiceProtocol; import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; +import software.amazon.awssdk.checksums.DefaultChecksumAlgorithm; import software.amazon.awssdk.core.CredentialType; import software.amazon.awssdk.core.RequestOverrideConfiguration; import software.amazon.awssdk.core.Response; @@ -282,9 +283,9 @@ public GetOperationWithChecksumResponse getOperationWithChecksum( .withInput(getOperationWithChecksumRequest) .putExecutionAttribute( SdkInternalExecutionAttribute.HTTP_CHECKSUM, - HttpChecksum.builder().requestChecksumRequired(true) + HttpChecksum.builder().requestChecksumRequired(true).isRequestStreaming(false) .requestAlgorithm(getOperationWithChecksumRequest.checksumAlgorithmAsString()) - .isRequestStreaming(false).build()) + .requestAlgorithmHeader("x-amz-sdk-checksum-algorithm").build()) .withMarshaller(new GetOperationWithChecksumRequestMarshaller(protocolFactory))); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -444,11 +445,11 @@ public OperationWithRequestCompressionResponse operationWithRequestCompression( * The content to send to the service. A {@link RequestBody} can be created using one of several factory * methods for various sources of data. For example, to create a request body from a file you can do the * following. - * + * *

      * {@code RequestBody.fromFile(new File("myfile.txt"))}
      * 
- * + * * See documentation in {@link RequestBody} for additional details and which sources of data are supported. * The service documentation for the request content is as follows ' *

@@ -508,10 +509,14 @@ public ReturnT putOperationWithChecksum(PutOperationWithChecksumReques .withMetricCollector(apiCallMetricCollector) .putExecutionAttribute( SdkInternalExecutionAttribute.HTTP_CHECKSUM, - HttpChecksum.builder().requestChecksumRequired(false) + HttpChecksum + .builder() + .requestChecksumRequired(false) + .isRequestStreaming(true) .requestValidationMode(putOperationWithChecksumRequest.checksumModeAsString()) - .responseAlgorithms("CRC32C", "CRC32", "SHA1", "SHA256").isRequestStreaming(true) - .build()) + .responseAlgorithmsV2(DefaultChecksumAlgorithm.CRC32C, + DefaultChecksumAlgorithm.CRC32, DefaultChecksumAlgorithm.SHA1, + DefaultChecksumAlgorithm.SHA256).build()) .withRequestBody(requestBody) .withMarshaller( StreamingRequestMarshaller.builder() @@ -530,11 +535,11 @@ public ReturnT putOperationWithChecksum(PutOperationWithChecksumReques * The content to send to the service. A {@link RequestBody} can be created using one of several factory * methods for various sources of data. For example, to create a request body from a file you can do the * following. - * + * *

      * {@code RequestBody.fromFile(new File("myfile.txt"))}
      * 
- * + * * See documentation in {@link RequestBody} for additional details and which sources of data are supported. * The service documentation for the request content is as follows 'This be a stream' * @return Result of the StreamingInputOperation operation returned by the service. diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-json-async-client-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-json-async-client-class.java index bdb16c6bf6a3..1dfb81af4d68 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-json-async-client-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-json-async-client-class.java @@ -31,6 +31,7 @@ import software.amazon.awssdk.awscore.internal.AwsProtocolMetadata; import software.amazon.awssdk.awscore.internal.AwsServiceProtocol; import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; +import software.amazon.awssdk.checksums.DefaultChecksumAlgorithm; import software.amazon.awssdk.core.CredentialType; import software.amazon.awssdk.core.RequestOverrideConfiguration; import software.amazon.awssdk.core.SdkPlugin; @@ -700,9 +701,10 @@ public CompletableFuture getOperationWithCheck .withMetricCollector(apiCallMetricCollector) .putExecutionAttribute( SdkInternalExecutionAttribute.HTTP_CHECKSUM, - HttpChecksum.builder().requestChecksumRequired(true) + HttpChecksum.builder().requestChecksumRequired(true).isRequestStreaming(false) .requestAlgorithm(getOperationWithChecksumRequest.checksumAlgorithmAsString()) - .isRequestStreaming(false).build()).withInput(getOperationWithChecksumRequest)); + .requestAlgorithmHeader("x-amz-sdk-checksum-algorithm").build()) + .withInput(getOperationWithChecksumRequest)); CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); }); @@ -1108,10 +1110,15 @@ public CompletableFuture putOperationWithChecksum( .withAsyncRequestBody(requestBody) .putExecutionAttribute( SdkInternalExecutionAttribute.HTTP_CHECKSUM, - HttpChecksum.builder().requestChecksumRequired(false) - .requestValidationMode(putOperationWithChecksumRequest.checksumModeAsString()) - .responseAlgorithms("CRC32C", "CRC32", "SHA1", "SHA256").isRequestStreaming(true) - .build()).withInput(putOperationWithChecksumRequest), asyncResponseTransformer); + HttpChecksum + .builder() + .requestChecksumRequired(false) + .isRequestStreaming(true) + .requestValidationMode(putOperationWithChecksumRequest.checksumModeAsString()) + .responseAlgorithmsV2(DefaultChecksumAlgorithm.CRC32C, + DefaultChecksumAlgorithm.CRC32, DefaultChecksumAlgorithm.SHA1, + DefaultChecksumAlgorithm.SHA256).build()) + .withInput(putOperationWithChecksumRequest), asyncResponseTransformer); AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { if (e != null) { diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-json-client-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-json-client-class.java index 38e7ee8bd9b9..8b32410d4bb9 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-json-client-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-json-client-class.java @@ -13,6 +13,7 @@ import software.amazon.awssdk.awscore.internal.AwsProtocolMetadata; import software.amazon.awssdk.awscore.internal.AwsServiceProtocol; import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; +import software.amazon.awssdk.checksums.DefaultChecksumAlgorithm; import software.amazon.awssdk.core.CredentialType; import software.amazon.awssdk.core.RequestOverrideConfiguration; import software.amazon.awssdk.core.SdkPlugin; @@ -321,9 +322,9 @@ public GetOperationWithChecksumResponse getOperationWithChecksum( .withMetricCollector(apiCallMetricCollector) .putExecutionAttribute( SdkInternalExecutionAttribute.HTTP_CHECKSUM, - HttpChecksum.builder().requestChecksumRequired(true) + HttpChecksum.builder().requestChecksumRequired(true).isRequestStreaming(false) .requestAlgorithm(getOperationWithChecksumRequest.checksumAlgorithmAsString()) - .isRequestStreaming(false).build()) + .requestAlgorithmHeader("x-amz-sdk-checksum-algorithm").build()) .withMarshaller(new GetOperationWithChecksumRequestMarshaller(protocolFactory))); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -602,11 +603,11 @@ public PaginatedOperationWithoutResultKeyResponse paginatedOperationWithoutResul * The content to send to the service. A {@link RequestBody} can be created using one of several factory * methods for various sources of data. For example, to create a request body from a file you can do the * following. - * + * *
      * {@code RequestBody.fromFile(new File("myfile.txt"))}
      * 
- * + * * See documentation in {@link RequestBody} for additional details and which sources of data are supported. * The service documentation for the request content is as follows ' *

@@ -669,10 +670,14 @@ public ReturnT putOperationWithChecksum(PutOperationWithChecksumReques .withMetricCollector(apiCallMetricCollector) .putExecutionAttribute( SdkInternalExecutionAttribute.HTTP_CHECKSUM, - HttpChecksum.builder().requestChecksumRequired(false) + HttpChecksum + .builder() + .requestChecksumRequired(false) + .isRequestStreaming(true) .requestValidationMode(putOperationWithChecksumRequest.checksumModeAsString()) - .responseAlgorithms("CRC32C", "CRC32", "SHA1", "SHA256").isRequestStreaming(true) - .build()) + .responseAlgorithmsV2(DefaultChecksumAlgorithm.CRC32C, + DefaultChecksumAlgorithm.CRC32, DefaultChecksumAlgorithm.SHA1, + DefaultChecksumAlgorithm.SHA256).build()) .withRequestBody(requestBody) .withMarshaller( StreamingRequestMarshaller.builder() diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-query-async-client-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-query-async-client-class.java index 825b4fda6477..3878372becba 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-query-async-client-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-query-async-client-class.java @@ -19,6 +19,7 @@ import software.amazon.awssdk.awscore.internal.AwsProtocolMetadata; import software.amazon.awssdk.awscore.internal.AwsServiceProtocol; import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; +import software.amazon.awssdk.checksums.DefaultChecksumAlgorithm; import software.amazon.awssdk.codegen.internal.UtilsTest; import software.amazon.awssdk.core.CredentialType; import software.amazon.awssdk.core.RequestOverrideConfiguration; @@ -114,7 +115,7 @@ final class DefaultQueryAsyncClient implements QueryAsyncClient { private static final Logger log = LoggerFactory.getLogger(DefaultQueryAsyncClient.class); private static final AwsProtocolMetadata protocolMetadata = AwsProtocolMetadata.builder() - .serviceProtocol(AwsServiceProtocol.QUERY).build(); + .serviceProtocol(AwsServiceProtocol.QUERY).build(); private final AsyncClientHandler clientHandler; @@ -159,27 +160,27 @@ protected DefaultQueryAsyncClient(SdkClientConfiguration clientConfiguration) { public CompletableFuture aPostOperation(APostOperationRequest aPostOperationRequest) { SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(aPostOperationRequest, this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, aPostOperationRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "APostOperation"); HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(APostOperationResponse::builder); + .createResponseHandler(APostOperationResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); String hostPrefix = "foo-"; String resolvedHostExpression = "foo-"; CompletableFuture executeFuture = clientHandler - .execute(new ClientExecutionParams() - .withOperationName("APostOperation").withProtocolMetadata(protocolMetadata) - .withMarshaller(new APostOperationRequestMarshaller(protocolFactory)) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .hostPrefixExpression(resolvedHostExpression).withInput(aPostOperationRequest)); + .execute(new ClientExecutionParams() + .withOperationName("APostOperation").withProtocolMetadata(protocolMetadata) + .withMarshaller(new APostOperationRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .hostPrefixExpression(resolvedHostExpression).withInput(aPostOperationRequest)); CompletableFuture whenCompleteFuture = null; whenCompleteFuture = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -217,29 +218,29 @@ public CompletableFuture aPostOperation(APostOperationRe */ @Override public CompletableFuture aPostOperationWithOutput( - APostOperationWithOutputRequest aPostOperationWithOutputRequest) { + APostOperationWithOutputRequest aPostOperationWithOutputRequest) { SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(aPostOperationWithOutputRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, aPostOperationWithOutputRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "APostOperationWithOutput"); HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(APostOperationWithOutputResponse::builder); + .createResponseHandler(APostOperationWithOutputResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); CompletableFuture executeFuture = clientHandler - .execute(new ClientExecutionParams() - .withOperationName("APostOperationWithOutput").withProtocolMetadata(protocolMetadata) - .withMarshaller(new APostOperationWithOutputRequestMarshaller(protocolFactory)) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(aPostOperationWithOutputRequest)); + .execute(new ClientExecutionParams() + .withOperationName("APostOperationWithOutput").withProtocolMetadata(protocolMetadata) + .withMarshaller(new APostOperationWithOutputRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withInput(aPostOperationWithOutputRequest)); CompletableFuture whenCompleteFuture = null; whenCompleteFuture = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -273,30 +274,30 @@ public CompletableFuture aPostOperationWithOut */ @Override public CompletableFuture bearerAuthOperation( - BearerAuthOperationRequest bearerAuthOperationRequest) { + BearerAuthOperationRequest bearerAuthOperationRequest) { SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(bearerAuthOperationRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, bearerAuthOperationRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "BearerAuthOperation"); bearerAuthOperationRequest = applySignerOverride(bearerAuthOperationRequest, BearerTokenSigner.create()); HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(BearerAuthOperationResponse::builder); + .createResponseHandler(BearerAuthOperationResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); CompletableFuture executeFuture = clientHandler - .execute(new ClientExecutionParams() - .withOperationName("BearerAuthOperation").withProtocolMetadata(protocolMetadata) - .withMarshaller(new BearerAuthOperationRequestMarshaller(protocolFactory)) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .credentialType(CredentialType.TOKEN).withRequestConfiguration(clientConfiguration) - .withMetricCollector(apiCallMetricCollector).withInput(bearerAuthOperationRequest)); + .execute(new ClientExecutionParams() + .withOperationName("BearerAuthOperation").withProtocolMetadata(protocolMetadata) + .withMarshaller(new BearerAuthOperationRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .credentialType(CredentialType.TOKEN).withRequestConfiguration(clientConfiguration) + .withMetricCollector(apiCallMetricCollector).withInput(bearerAuthOperationRequest)); CompletableFuture whenCompleteFuture = null; whenCompleteFuture = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -330,36 +331,37 @@ public CompletableFuture bearerAuthOperation( */ @Override public CompletableFuture getOperationWithChecksum( - GetOperationWithChecksumRequest getOperationWithChecksumRequest) { + GetOperationWithChecksumRequest getOperationWithChecksumRequest) { SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(getOperationWithChecksumRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, getOperationWithChecksumRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "GetOperationWithChecksum"); HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(GetOperationWithChecksumResponse::builder); + .createResponseHandler(GetOperationWithChecksumResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); CompletableFuture executeFuture = clientHandler - .execute(new ClientExecutionParams() - .withOperationName("GetOperationWithChecksum") - .withProtocolMetadata(protocolMetadata) - .withMarshaller(new GetOperationWithChecksumRequestMarshaller(protocolFactory)) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withMetricCollector(apiCallMetricCollector) - .putExecutionAttribute( - SdkInternalExecutionAttribute.HTTP_CHECKSUM, - HttpChecksum.builder().requestChecksumRequired(true) - .requestAlgorithm(getOperationWithChecksumRequest.checksumAlgorithmAsString()) - .isRequestStreaming(false).build()).withInput(getOperationWithChecksumRequest)); + .execute(new ClientExecutionParams() + .withOperationName("GetOperationWithChecksum") + .withProtocolMetadata(protocolMetadata) + .withMarshaller(new GetOperationWithChecksumRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler) + .withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration) + .withMetricCollector(apiCallMetricCollector) + .putExecutionAttribute( + SdkInternalExecutionAttribute.HTTP_CHECKSUM, + HttpChecksum.builder().requestChecksumRequired(true).isRequestStreaming(false) + .requestAlgorithm(getOperationWithChecksumRequest.checksumAlgorithmAsString()) + .requestAlgorithmHeader("x-amz-sdk-checksum-algorithm").build()) + .withInput(getOperationWithChecksumRequest)); CompletableFuture whenCompleteFuture = null; whenCompleteFuture = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -394,33 +396,33 @@ public CompletableFuture getOperationWithCheck */ @Override public CompletableFuture operationWithChecksumRequired( - OperationWithChecksumRequiredRequest operationWithChecksumRequiredRequest) { + OperationWithChecksumRequiredRequest operationWithChecksumRequiredRequest) { SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithChecksumRequiredRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, - operationWithChecksumRequiredRequest.overrideConfiguration().orElse(null)); + operationWithChecksumRequiredRequest.overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithChecksumRequired"); HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(OperationWithChecksumRequiredResponse::builder); + .createResponseHandler(OperationWithChecksumRequiredResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); CompletableFuture executeFuture = clientHandler - .execute(new ClientExecutionParams() - .withOperationName("OperationWithChecksumRequired") - .withProtocolMetadata(protocolMetadata) - .withMarshaller(new OperationWithChecksumRequiredRequestMarshaller(protocolFactory)) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withMetricCollector(apiCallMetricCollector) - .putExecutionAttribute(SdkInternalExecutionAttribute.HTTP_CHECKSUM_REQUIRED, - HttpChecksumRequired.create()).withInput(operationWithChecksumRequiredRequest)); + .execute(new ClientExecutionParams() + .withOperationName("OperationWithChecksumRequired") + .withProtocolMetadata(protocolMetadata) + .withMarshaller(new OperationWithChecksumRequiredRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler) + .withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration) + .withMetricCollector(apiCallMetricCollector) + .putExecutionAttribute(SdkInternalExecutionAttribute.HTTP_CHECKSUM_REQUIRED, + HttpChecksumRequired.create()).withInput(operationWithChecksumRequiredRequest)); CompletableFuture whenCompleteFuture = null; whenCompleteFuture = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -454,29 +456,29 @@ public CompletableFuture operationWithChe */ @Override public CompletableFuture operationWithContextParam( - OperationWithContextParamRequest operationWithContextParamRequest) { + OperationWithContextParamRequest operationWithContextParamRequest) { SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithContextParamRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, operationWithContextParamRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithContextParam"); HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(OperationWithContextParamResponse::builder); + .createResponseHandler(OperationWithContextParamResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); CompletableFuture executeFuture = clientHandler - .execute(new ClientExecutionParams() - .withOperationName("OperationWithContextParam").withProtocolMetadata(protocolMetadata) - .withMarshaller(new OperationWithContextParamRequestMarshaller(protocolFactory)) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(operationWithContextParamRequest)); + .execute(new ClientExecutionParams() + .withOperationName("OperationWithContextParam").withProtocolMetadata(protocolMetadata) + .withMarshaller(new OperationWithContextParamRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withInput(operationWithContextParamRequest)); CompletableFuture whenCompleteFuture = null; whenCompleteFuture = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -510,30 +512,30 @@ public CompletableFuture operationWithContext */ @Override public CompletableFuture operationWithCustomMember( - OperationWithCustomMemberRequest operationWithCustomMemberRequest) { + OperationWithCustomMemberRequest operationWithCustomMemberRequest) { operationWithCustomMemberRequest = UtilsTest.dummyRequestModifier(operationWithCustomMemberRequest); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithCustomMemberRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, operationWithCustomMemberRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithCustomMember"); HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(OperationWithCustomMemberResponse::builder); + .createResponseHandler(OperationWithCustomMemberResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); CompletableFuture executeFuture = clientHandler - .execute(new ClientExecutionParams() - .withOperationName("OperationWithCustomMember").withProtocolMetadata(protocolMetadata) - .withMarshaller(new OperationWithCustomMemberRequestMarshaller(protocolFactory)) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(operationWithCustomMemberRequest)); + .execute(new ClientExecutionParams() + .withOperationName("OperationWithCustomMember").withProtocolMetadata(protocolMetadata) + .withMarshaller(new OperationWithCustomMemberRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withInput(operationWithCustomMemberRequest)); CompletableFuture whenCompleteFuture = null; whenCompleteFuture = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -569,30 +571,30 @@ public CompletableFuture operationWithCustomM */ @Override public CompletableFuture operationWithCustomizedOperationContextParam( - OperationWithCustomizedOperationContextParamRequest operationWithCustomizedOperationContextParamRequest) { + OperationWithCustomizedOperationContextParamRequest operationWithCustomizedOperationContextParamRequest) { SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration( - operationWithCustomizedOperationContextParamRequest, this.clientConfiguration); + operationWithCustomizedOperationContextParamRequest, this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, - operationWithCustomizedOperationContextParamRequest.overrideConfiguration().orElse(null)); + operationWithCustomizedOperationContextParamRequest.overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithCustomizedOperationContextParam"); HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(OperationWithCustomizedOperationContextParamResponse::builder); + .createResponseHandler(OperationWithCustomizedOperationContextParamResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); CompletableFuture executeFuture = clientHandler - .execute(new ClientExecutionParams() - .withOperationName("OperationWithCustomizedOperationContextParam") - .withProtocolMetadata(protocolMetadata) - .withMarshaller(new OperationWithCustomizedOperationContextParamRequestMarshaller(protocolFactory)) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(operationWithCustomizedOperationContextParamRequest)); + .execute(new ClientExecutionParams() + .withOperationName("OperationWithCustomizedOperationContextParam") + .withProtocolMetadata(protocolMetadata) + .withMarshaller(new OperationWithCustomizedOperationContextParamRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withInput(operationWithCustomizedOperationContextParamRequest)); CompletableFuture whenCompleteFuture = null; whenCompleteFuture = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -628,29 +630,29 @@ public CompletableFuture o */ @Override public CompletableFuture operationWithMapOperationContextParam( - OperationWithMapOperationContextParamRequest operationWithMapOperationContextParamRequest) { + OperationWithMapOperationContextParamRequest operationWithMapOperationContextParamRequest) { SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithMapOperationContextParamRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, - operationWithMapOperationContextParamRequest.overrideConfiguration().orElse(null)); + operationWithMapOperationContextParamRequest.overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithMapOperationContextParam"); HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(OperationWithMapOperationContextParamResponse::builder); + .createResponseHandler(OperationWithMapOperationContextParamResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); CompletableFuture executeFuture = clientHandler - .execute(new ClientExecutionParams() - .withOperationName("OperationWithMapOperationContextParam").withProtocolMetadata(protocolMetadata) - .withMarshaller(new OperationWithMapOperationContextParamRequestMarshaller(protocolFactory)) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(operationWithMapOperationContextParamRequest)); + .execute(new ClientExecutionParams() + .withOperationName("OperationWithMapOperationContextParam").withProtocolMetadata(protocolMetadata) + .withMarshaller(new OperationWithMapOperationContextParamRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withInput(operationWithMapOperationContextParamRequest)); CompletableFuture whenCompleteFuture = null; whenCompleteFuture = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -684,30 +686,30 @@ public CompletableFuture operatio */ @Override public CompletableFuture operationWithNoneAuthType( - OperationWithNoneAuthTypeRequest operationWithNoneAuthTypeRequest) { + OperationWithNoneAuthTypeRequest operationWithNoneAuthTypeRequest) { SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithNoneAuthTypeRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, operationWithNoneAuthTypeRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithNoneAuthType"); HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(OperationWithNoneAuthTypeResponse::builder); + .createResponseHandler(OperationWithNoneAuthTypeResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); CompletableFuture executeFuture = clientHandler - .execute(new ClientExecutionParams() - .withOperationName("OperationWithNoneAuthType").withProtocolMetadata(protocolMetadata) - .withMarshaller(new OperationWithNoneAuthTypeRequestMarshaller(protocolFactory)) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .putExecutionAttribute(SdkInternalExecutionAttribute.IS_NONE_AUTH_TYPE_REQUEST, false) - .withInput(operationWithNoneAuthTypeRequest)); + .execute(new ClientExecutionParams() + .withOperationName("OperationWithNoneAuthType").withProtocolMetadata(protocolMetadata) + .withMarshaller(new OperationWithNoneAuthTypeRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .putExecutionAttribute(SdkInternalExecutionAttribute.IS_NONE_AUTH_TYPE_REQUEST, false) + .withInput(operationWithNoneAuthTypeRequest)); CompletableFuture whenCompleteFuture = null; whenCompleteFuture = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -743,29 +745,29 @@ public CompletableFuture operationWithNoneAut */ @Override public CompletableFuture operationWithOperationContextParam( - OperationWithOperationContextParamRequest operationWithOperationContextParamRequest) { + OperationWithOperationContextParamRequest operationWithOperationContextParamRequest) { SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithOperationContextParamRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, - operationWithOperationContextParamRequest.overrideConfiguration().orElse(null)); + operationWithOperationContextParamRequest.overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithOperationContextParam"); HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(OperationWithOperationContextParamResponse::builder); + .createResponseHandler(OperationWithOperationContextParamResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); CompletableFuture executeFuture = clientHandler - .execute(new ClientExecutionParams() - .withOperationName("OperationWithOperationContextParam").withProtocolMetadata(protocolMetadata) - .withMarshaller(new OperationWithOperationContextParamRequestMarshaller(protocolFactory)) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(operationWithOperationContextParamRequest)); + .execute(new ClientExecutionParams() + .withOperationName("OperationWithOperationContextParam").withProtocolMetadata(protocolMetadata) + .withMarshaller(new OperationWithOperationContextParamRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withInput(operationWithOperationContextParamRequest)); CompletableFuture whenCompleteFuture = null; whenCompleteFuture = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -800,34 +802,34 @@ public CompletableFuture operationWi */ @Override public CompletableFuture operationWithRequestCompression( - OperationWithRequestCompressionRequest operationWithRequestCompressionRequest) { + OperationWithRequestCompressionRequest operationWithRequestCompressionRequest) { SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithRequestCompressionRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, - operationWithRequestCompressionRequest.overrideConfiguration().orElse(null)); + operationWithRequestCompressionRequest.overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithRequestCompression"); HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(OperationWithRequestCompressionResponse::builder); + .createResponseHandler(OperationWithRequestCompressionResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); CompletableFuture executeFuture = clientHandler - .execute(new ClientExecutionParams() - .withOperationName("OperationWithRequestCompression") - .withProtocolMetadata(protocolMetadata) - .withMarshaller(new OperationWithRequestCompressionRequestMarshaller(protocolFactory)) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withMetricCollector(apiCallMetricCollector) - .putExecutionAttribute(SdkInternalExecutionAttribute.REQUEST_COMPRESSION, - RequestCompression.builder().encodings("gzip").isStreaming(false).build()) - .withInput(operationWithRequestCompressionRequest)); + .execute(new ClientExecutionParams() + .withOperationName("OperationWithRequestCompression") + .withProtocolMetadata(protocolMetadata) + .withMarshaller(new OperationWithRequestCompressionRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler) + .withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration) + .withMetricCollector(apiCallMetricCollector) + .putExecutionAttribute(SdkInternalExecutionAttribute.REQUEST_COMPRESSION, + RequestCompression.builder().encodings("gzip").isStreaming(false).build()) + .withInput(operationWithRequestCompressionRequest)); CompletableFuture whenCompleteFuture = null; whenCompleteFuture = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -862,29 +864,29 @@ public CompletableFuture operationWithR */ @Override public CompletableFuture operationWithStaticContextParams( - OperationWithStaticContextParamsRequest operationWithStaticContextParamsRequest) { + OperationWithStaticContextParamsRequest operationWithStaticContextParamsRequest) { SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithStaticContextParamsRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, - operationWithStaticContextParamsRequest.overrideConfiguration().orElse(null)); + operationWithStaticContextParamsRequest.overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithStaticContextParams"); HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(OperationWithStaticContextParamsResponse::builder); + .createResponseHandler(OperationWithStaticContextParamsResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); CompletableFuture executeFuture = clientHandler - .execute(new ClientExecutionParams() - .withOperationName("OperationWithStaticContextParams").withProtocolMetadata(protocolMetadata) - .withMarshaller(new OperationWithStaticContextParamsRequestMarshaller(protocolFactory)) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(operationWithStaticContextParamsRequest)); + .execute(new ClientExecutionParams() + .withOperationName("OperationWithStaticContextParams").withProtocolMetadata(protocolMetadata) + .withMarshaller(new OperationWithStaticContextParamsRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withInput(operationWithStaticContextParamsRequest)); CompletableFuture whenCompleteFuture = null; whenCompleteFuture = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -936,19 +938,19 @@ public CompletableFuture operationWith */ @Override public CompletableFuture putOperationWithChecksum( - PutOperationWithChecksumRequest putOperationWithChecksumRequest, AsyncRequestBody requestBody, - AsyncResponseTransformer asyncResponseTransformer) { + PutOperationWithChecksumRequest putOperationWithChecksumRequest, AsyncRequestBody requestBody, + AsyncResponseTransformer asyncResponseTransformer) { SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(putOperationWithChecksumRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, putOperationWithChecksumRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "PutOperationWithChecksum"); Pair, CompletableFuture> pair = AsyncResponseTransformerUtils - .wrapWithEndOfStreamFuture(asyncResponseTransformer); + .wrapWithEndOfStreamFuture(asyncResponseTransformer); asyncResponseTransformer = pair.left(); CompletableFuture endOfStreamFuture = pair.right(); if (!isSignerOverridden(clientConfiguration)) { @@ -956,35 +958,39 @@ public CompletableFuture putOperationWithChecksum( } HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(PutOperationWithChecksumResponse::builder); + .createResponseHandler(PutOperationWithChecksumResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); CompletableFuture executeFuture = clientHandler.execute( - new ClientExecutionParams() - .withOperationName("PutOperationWithChecksum") - .withProtocolMetadata(protocolMetadata) - .withMarshaller( - AsyncStreamingRequestMarshaller.builder() - .delegateMarshaller(new PutOperationWithChecksumRequestMarshaller(protocolFactory)) - .asyncRequestBody(requestBody).build()) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withMetricCollector(apiCallMetricCollector) - .putExecutionAttribute( - SdkInternalExecutionAttribute.HTTP_CHECKSUM, - HttpChecksum.builder().requestChecksumRequired(false) - .requestValidationMode(putOperationWithChecksumRequest.checksumModeAsString()) - .responseAlgorithms("CRC32C", "CRC32", "SHA1", "SHA256").isRequestStreaming(true) - .build()).withAsyncRequestBody(requestBody) - .withInput(putOperationWithChecksumRequest), asyncResponseTransformer); + new ClientExecutionParams() + .withOperationName("PutOperationWithChecksum") + .withProtocolMetadata(protocolMetadata) + .withMarshaller( + AsyncStreamingRequestMarshaller.builder() + .delegateMarshaller(new PutOperationWithChecksumRequestMarshaller(protocolFactory)) + .asyncRequestBody(requestBody).build()) + .withResponseHandler(responseHandler) + .withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration) + .withMetricCollector(apiCallMetricCollector) + .putExecutionAttribute( + SdkInternalExecutionAttribute.HTTP_CHECKSUM, + HttpChecksum + .builder() + .requestChecksumRequired(false) + .isRequestStreaming(true) + .requestValidationMode(putOperationWithChecksumRequest.checksumModeAsString()) + .responseAlgorithmsV2(DefaultChecksumAlgorithm.CRC32C, + DefaultChecksumAlgorithm.CRC32, DefaultChecksumAlgorithm.SHA1, + DefaultChecksumAlgorithm.SHA256).build()).withAsyncRequestBody(requestBody) + .withInput(putOperationWithChecksumRequest), asyncResponseTransformer); CompletableFuture whenCompleteFuture = null; AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; whenCompleteFuture = executeFuture.whenComplete((r, e) -> { if (e != null) { runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", - () -> finalAsyncResponseTransformer.exceptionOccurred(e)); + () -> finalAsyncResponseTransformer.exceptionOccurred(e)); } endOfStreamFuture.whenComplete((r2, e2) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -994,7 +1000,7 @@ public CompletableFuture putOperationWithChecksum( } catch (Throwable t) { AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", - () -> finalAsyncResponseTransformer.exceptionOccurred(t)); + () -> finalAsyncResponseTransformer.exceptionOccurred(t)); metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); return CompletableFutureUtils.failedFuture(t); } @@ -1027,13 +1033,13 @@ public CompletableFuture putOperationWithChecksum( */ @Override public CompletableFuture streamingInputOperation( - StreamingInputOperationRequest streamingInputOperationRequest, AsyncRequestBody requestBody) { + StreamingInputOperationRequest streamingInputOperationRequest, AsyncRequestBody requestBody) { SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(streamingInputOperationRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, streamingInputOperationRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "StreamingInputOperation"); @@ -1042,21 +1048,21 @@ public CompletableFuture streamingInputOperatio } HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(StreamingInputOperationResponse::builder); + .createResponseHandler(StreamingInputOperationResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); CompletableFuture executeFuture = clientHandler - .execute(new ClientExecutionParams() - .withOperationName("StreamingInputOperation") - .withProtocolMetadata(protocolMetadata) - .withMarshaller( - AsyncStreamingRequestMarshaller.builder() - .delegateMarshaller(new StreamingInputOperationRequestMarshaller(protocolFactory)) - .asyncRequestBody(requestBody).build()).withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler).withRequestConfiguration(clientConfiguration) - .withMetricCollector(apiCallMetricCollector).withAsyncRequestBody(requestBody) - .withInput(streamingInputOperationRequest)); + .execute(new ClientExecutionParams() + .withOperationName("StreamingInputOperation") + .withProtocolMetadata(protocolMetadata) + .withMarshaller( + AsyncStreamingRequestMarshaller.builder() + .delegateMarshaller(new StreamingInputOperationRequestMarshaller(protocolFactory)) + .asyncRequestBody(requestBody).build()).withResponseHandler(responseHandler) + .withErrorResponseHandler(errorResponseHandler).withRequestConfiguration(clientConfiguration) + .withMetricCollector(apiCallMetricCollector).withAsyncRequestBody(requestBody) + .withInput(streamingInputOperationRequest)); CompletableFuture whenCompleteFuture = null; whenCompleteFuture = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -1095,40 +1101,40 @@ public CompletableFuture streamingInputOperatio */ @Override public CompletableFuture streamingOutputOperation( - StreamingOutputOperationRequest streamingOutputOperationRequest, - AsyncResponseTransformer asyncResponseTransformer) { + StreamingOutputOperationRequest streamingOutputOperationRequest, + AsyncResponseTransformer asyncResponseTransformer) { SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(streamingOutputOperationRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, streamingOutputOperationRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "StreamingOutputOperation"); Pair, CompletableFuture> pair = AsyncResponseTransformerUtils - .wrapWithEndOfStreamFuture(asyncResponseTransformer); + .wrapWithEndOfStreamFuture(asyncResponseTransformer); asyncResponseTransformer = pair.left(); CompletableFuture endOfStreamFuture = pair.right(); HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(StreamingOutputOperationResponse::builder); + .createResponseHandler(StreamingOutputOperationResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); CompletableFuture executeFuture = clientHandler.execute( - new ClientExecutionParams() - .withOperationName("StreamingOutputOperation").withProtocolMetadata(protocolMetadata) - .withMarshaller(new StreamingOutputOperationRequestMarshaller(protocolFactory)) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(streamingOutputOperationRequest), asyncResponseTransformer); + new ClientExecutionParams() + .withOperationName("StreamingOutputOperation").withProtocolMetadata(protocolMetadata) + .withMarshaller(new StreamingOutputOperationRequestMarshaller(protocolFactory)) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) + .withInput(streamingOutputOperationRequest), asyncResponseTransformer); CompletableFuture whenCompleteFuture = null; AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; whenCompleteFuture = executeFuture.whenComplete((r, e) -> { if (e != null) { runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", - () -> finalAsyncResponseTransformer.exceptionOccurred(e)); + () -> finalAsyncResponseTransformer.exceptionOccurred(e)); } endOfStreamFuture.whenComplete((r2, e2) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -1138,7 +1144,7 @@ public CompletableFuture streamingOutputOperation( } catch (Throwable t) { AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", - () -> finalAsyncResponseTransformer.exceptionOccurred(t)); + () -> finalAsyncResponseTransformer.exceptionOccurred(t)); metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); return CompletableFutureUtils.failedFuture(t); } @@ -1161,15 +1167,15 @@ public final String serviceName() { private AwsQueryProtocolFactory init() { return AwsQueryProtocolFactory - .builder() - .registerModeledException( - ExceptionMetadata.builder().errorCode("InvalidInput") - .exceptionBuilderSupplier(InvalidInputException::builder).httpStatusCode(400).build()) - .clientConfiguration(clientConfiguration).defaultServiceExceptionSupplier(QueryException::builder).build(); + .builder() + .registerModeledException( + ExceptionMetadata.builder().errorCode("InvalidInput") + .exceptionBuilderSupplier(InvalidInputException::builder).httpStatusCode(400).build()) + .clientConfiguration(clientConfiguration).defaultServiceExceptionSupplier(QueryException::builder).build(); } private static List resolveMetricPublishers(SdkClientConfiguration clientConfiguration, - RequestOverrideConfiguration requestOverrideConfiguration) { + RequestOverrideConfiguration requestOverrideConfiguration) { List publishers = null; if (requestOverrideConfiguration != null) { publishers = requestOverrideConfiguration.metricPublishers(); @@ -1189,8 +1195,8 @@ private T applySignerOverride(T request, Signer signer) } Consumer signerOverride = b -> b.signer(signer).build(); AwsRequestOverrideConfiguration overrideConfiguration = request.overrideConfiguration() - .map(c -> c.toBuilder().applyMutation(signerOverride).build()) - .orElse((AwsRequestOverrideConfiguration.builder().applyMutation(signerOverride).build())); + .map(c -> c.toBuilder().applyMutation(signerOverride).build()) + .orElse((AwsRequestOverrideConfiguration.builder().applyMutation(signerOverride).build())); return (T) request.toBuilder().overrideConfiguration(overrideConfiguration).build(); } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-query-client-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-query-client-class.java index d8d222793385..5f013b28da68 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-query-client-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-query-client-class.java @@ -12,6 +12,7 @@ import software.amazon.awssdk.awscore.internal.AwsProtocolMetadata; import software.amazon.awssdk.awscore.internal.AwsServiceProtocol; import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; +import software.amazon.awssdk.checksums.DefaultChecksumAlgorithm; import software.amazon.awssdk.codegen.internal.UtilsTest; import software.amazon.awssdk.core.CredentialType; import software.amazon.awssdk.core.RequestOverrideConfiguration; @@ -106,7 +107,7 @@ final class DefaultQueryClient implements QueryClient { private static final Logger log = Logger.loggerFor(DefaultQueryClient.class); private static final AwsProtocolMetadata protocolMetadata = AwsProtocolMetadata.builder() - .serviceProtocol(AwsServiceProtocol.QUERY).build(); + .serviceProtocol(AwsServiceProtocol.QUERY).build(); private final SyncClientHandler clientHandler; @@ -142,17 +143,17 @@ protected DefaultQueryClient(SdkClientConfiguration clientConfiguration) { */ @Override public APostOperationResponse aPostOperation(APostOperationRequest aPostOperationRequest) throws InvalidInputException, - AwsServiceException, SdkClientException, QueryException { + AwsServiceException, SdkClientException, QueryException { HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(APostOperationResponse::builder); + .createResponseHandler(APostOperationResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(aPostOperationRequest, this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, aPostOperationRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "APostOperation"); @@ -160,11 +161,11 @@ public APostOperationResponse aPostOperation(APostOperationRequest aPostOperatio String resolvedHostExpression = "foo-"; return clientHandler.execute(new ClientExecutionParams() - .withOperationName("APostOperation").withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .hostPrefixExpression(resolvedHostExpression).withRequestConfiguration(clientConfiguration) - .withInput(aPostOperationRequest).withMetricCollector(apiCallMetricCollector) - .withMarshaller(new APostOperationRequestMarshaller(protocolFactory))); + .withOperationName("APostOperation").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .hostPrefixExpression(resolvedHostExpression).withRequestConfiguration(clientConfiguration) + .withInput(aPostOperationRequest).withMetricCollector(apiCallMetricCollector) + .withMarshaller(new APostOperationRequestMarshaller(protocolFactory))); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); } @@ -192,30 +193,30 @@ public APostOperationResponse aPostOperation(APostOperationRequest aPostOperatio */ @Override public APostOperationWithOutputResponse aPostOperationWithOutput( - APostOperationWithOutputRequest aPostOperationWithOutputRequest) throws InvalidInputException, AwsServiceException, - SdkClientException, QueryException { + APostOperationWithOutputRequest aPostOperationWithOutputRequest) throws InvalidInputException, AwsServiceException, + SdkClientException, QueryException { HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(APostOperationWithOutputResponse::builder); + .createResponseHandler(APostOperationWithOutputResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(aPostOperationWithOutputRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, aPostOperationWithOutputRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "APostOperationWithOutput"); return clientHandler - .execute(new ClientExecutionParams() - .withOperationName("APostOperationWithOutput").withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withInput(aPostOperationWithOutputRequest) - .withMetricCollector(apiCallMetricCollector) - .withMarshaller(new APostOperationWithOutputRequestMarshaller(protocolFactory))); + .execute(new ClientExecutionParams() + .withOperationName("APostOperationWithOutput").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withInput(aPostOperationWithOutputRequest) + .withMetricCollector(apiCallMetricCollector) + .withMarshaller(new APostOperationWithOutputRequestMarshaller(protocolFactory))); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); } @@ -239,29 +240,29 @@ public APostOperationWithOutputResponse aPostOperationWithOutput( */ @Override public BearerAuthOperationResponse bearerAuthOperation(BearerAuthOperationRequest bearerAuthOperationRequest) - throws AwsServiceException, SdkClientException, QueryException { + throws AwsServiceException, SdkClientException, QueryException { bearerAuthOperationRequest = applySignerOverride(bearerAuthOperationRequest, BearerTokenSigner.create()); HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(BearerAuthOperationResponse::builder); + .createResponseHandler(BearerAuthOperationResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(bearerAuthOperationRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, bearerAuthOperationRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "BearerAuthOperation"); return clientHandler.execute(new ClientExecutionParams() - .withOperationName("BearerAuthOperation").withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .credentialType(CredentialType.TOKEN).withRequestConfiguration(clientConfiguration) - .withInput(bearerAuthOperationRequest).withMetricCollector(apiCallMetricCollector) - .withMarshaller(new BearerAuthOperationRequestMarshaller(protocolFactory))); + .withOperationName("BearerAuthOperation").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .credentialType(CredentialType.TOKEN).withRequestConfiguration(clientConfiguration) + .withInput(bearerAuthOperationRequest).withMetricCollector(apiCallMetricCollector) + .withMarshaller(new BearerAuthOperationRequestMarshaller(protocolFactory))); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); } @@ -285,38 +286,38 @@ public BearerAuthOperationResponse bearerAuthOperation(BearerAuthOperationReques */ @Override public GetOperationWithChecksumResponse getOperationWithChecksum( - GetOperationWithChecksumRequest getOperationWithChecksumRequest) throws AwsServiceException, SdkClientException, - QueryException { + GetOperationWithChecksumRequest getOperationWithChecksumRequest) throws AwsServiceException, SdkClientException, + QueryException { HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(GetOperationWithChecksumResponse::builder); + .createResponseHandler(GetOperationWithChecksumResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(getOperationWithChecksumRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, getOperationWithChecksumRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "GetOperationWithChecksum"); return clientHandler - .execute(new ClientExecutionParams() - .withOperationName("GetOperationWithChecksum") - .withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withInput(getOperationWithChecksumRequest) - .withMetricCollector(apiCallMetricCollector) - .putExecutionAttribute( - SdkInternalExecutionAttribute.HTTP_CHECKSUM, - HttpChecksum.builder().requestChecksumRequired(true) - .requestAlgorithm(getOperationWithChecksumRequest.checksumAlgorithmAsString()) - .isRequestStreaming(false).build()) - .withMarshaller(new GetOperationWithChecksumRequestMarshaller(protocolFactory))); + .execute(new ClientExecutionParams() + .withOperationName("GetOperationWithChecksum") + .withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler) + .withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration) + .withInput(getOperationWithChecksumRequest) + .withMetricCollector(apiCallMetricCollector) + .putExecutionAttribute( + SdkInternalExecutionAttribute.HTTP_CHECKSUM, + HttpChecksum.builder().requestChecksumRequired(true).isRequestStreaming(false) + .requestAlgorithm(getOperationWithChecksumRequest.checksumAlgorithmAsString()) + .requestAlgorithmHeader("x-amz-sdk-checksum-algorithm").build()) + .withMarshaller(new GetOperationWithChecksumRequestMarshaller(protocolFactory))); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); } @@ -340,35 +341,35 @@ public GetOperationWithChecksumResponse getOperationWithChecksum( */ @Override public OperationWithChecksumRequiredResponse operationWithChecksumRequired( - OperationWithChecksumRequiredRequest operationWithChecksumRequiredRequest) throws AwsServiceException, - SdkClientException, QueryException { + OperationWithChecksumRequiredRequest operationWithChecksumRequiredRequest) throws AwsServiceException, + SdkClientException, QueryException { HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(OperationWithChecksumRequiredResponse::builder); + .createResponseHandler(OperationWithChecksumRequiredResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithChecksumRequiredRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, - operationWithChecksumRequiredRequest.overrideConfiguration().orElse(null)); + operationWithChecksumRequiredRequest.overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithChecksumRequired"); return clientHandler - .execute(new ClientExecutionParams() - .withOperationName("OperationWithChecksumRequired") - .withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withInput(operationWithChecksumRequiredRequest) - .withMetricCollector(apiCallMetricCollector) - .putExecutionAttribute(SdkInternalExecutionAttribute.HTTP_CHECKSUM_REQUIRED, - HttpChecksumRequired.create()) - .withMarshaller(new OperationWithChecksumRequiredRequestMarshaller(protocolFactory))); + .execute(new ClientExecutionParams() + .withOperationName("OperationWithChecksumRequired") + .withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler) + .withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration) + .withInput(operationWithChecksumRequiredRequest) + .withMetricCollector(apiCallMetricCollector) + .putExecutionAttribute(SdkInternalExecutionAttribute.HTTP_CHECKSUM_REQUIRED, + HttpChecksumRequired.create()) + .withMarshaller(new OperationWithChecksumRequiredRequestMarshaller(protocolFactory))); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); } @@ -392,30 +393,30 @@ public OperationWithChecksumRequiredResponse operationWithChecksumRequired( */ @Override public OperationWithContextParamResponse operationWithContextParam( - OperationWithContextParamRequest operationWithContextParamRequest) throws AwsServiceException, SdkClientException, - QueryException { + OperationWithContextParamRequest operationWithContextParamRequest) throws AwsServiceException, SdkClientException, + QueryException { HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(OperationWithContextParamResponse::builder); + .createResponseHandler(OperationWithContextParamResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithContextParamRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, operationWithContextParamRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithContextParam"); return clientHandler - .execute(new ClientExecutionParams() - .withOperationName("OperationWithContextParam").withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withInput(operationWithContextParamRequest) - .withMetricCollector(apiCallMetricCollector) - .withMarshaller(new OperationWithContextParamRequestMarshaller(protocolFactory))); + .execute(new ClientExecutionParams() + .withOperationName("OperationWithContextParam").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withInput(operationWithContextParamRequest) + .withMetricCollector(apiCallMetricCollector) + .withMarshaller(new OperationWithContextParamRequestMarshaller(protocolFactory))); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); } @@ -439,31 +440,31 @@ public OperationWithContextParamResponse operationWithContextParam( */ @Override public OperationWithCustomMemberResponse operationWithCustomMember( - OperationWithCustomMemberRequest operationWithCustomMemberRequest) throws AwsServiceException, SdkClientException, - QueryException { + OperationWithCustomMemberRequest operationWithCustomMemberRequest) throws AwsServiceException, SdkClientException, + QueryException { operationWithCustomMemberRequest = UtilsTest.dummyRequestModifier(operationWithCustomMemberRequest); HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(OperationWithCustomMemberResponse::builder); + .createResponseHandler(OperationWithCustomMemberResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithCustomMemberRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, operationWithCustomMemberRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithCustomMember"); return clientHandler - .execute(new ClientExecutionParams() - .withOperationName("OperationWithCustomMember").withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withInput(operationWithCustomMemberRequest) - .withMetricCollector(apiCallMetricCollector) - .withMarshaller(new OperationWithCustomMemberRequestMarshaller(protocolFactory))); + .execute(new ClientExecutionParams() + .withOperationName("OperationWithCustomMember").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withInput(operationWithCustomMemberRequest) + .withMetricCollector(apiCallMetricCollector) + .withMarshaller(new OperationWithCustomMemberRequestMarshaller(protocolFactory))); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); } @@ -488,31 +489,31 @@ public OperationWithCustomMemberResponse operationWithCustomMember( */ @Override public OperationWithCustomizedOperationContextParamResponse operationWithCustomizedOperationContextParam( - OperationWithCustomizedOperationContextParamRequest operationWithCustomizedOperationContextParamRequest) - throws AwsServiceException, SdkClientException, QueryException { + OperationWithCustomizedOperationContextParamRequest operationWithCustomizedOperationContextParamRequest) + throws AwsServiceException, SdkClientException, QueryException { HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(OperationWithCustomizedOperationContextParamResponse::builder); + .createResponseHandler(OperationWithCustomizedOperationContextParamResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration( - operationWithCustomizedOperationContextParamRequest, this.clientConfiguration); + operationWithCustomizedOperationContextParamRequest, this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, - operationWithCustomizedOperationContextParamRequest.overrideConfiguration().orElse(null)); + operationWithCustomizedOperationContextParamRequest.overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithCustomizedOperationContextParam"); return clientHandler - .execute(new ClientExecutionParams() - .withOperationName("OperationWithCustomizedOperationContextParam") - .withProtocolMetadata(protocolMetadata).withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler).withRequestConfiguration(clientConfiguration) - .withInput(operationWithCustomizedOperationContextParamRequest) - .withMetricCollector(apiCallMetricCollector) - .withMarshaller(new OperationWithCustomizedOperationContextParamRequestMarshaller(protocolFactory))); + .execute(new ClientExecutionParams() + .withOperationName("OperationWithCustomizedOperationContextParam") + .withProtocolMetadata(protocolMetadata).withResponseHandler(responseHandler) + .withErrorResponseHandler(errorResponseHandler).withRequestConfiguration(clientConfiguration) + .withInput(operationWithCustomizedOperationContextParamRequest) + .withMetricCollector(apiCallMetricCollector) + .withMarshaller(new OperationWithCustomizedOperationContextParamRequestMarshaller(protocolFactory))); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); } @@ -537,30 +538,30 @@ public OperationWithCustomizedOperationContextParamResponse operationWithCustomi */ @Override public OperationWithMapOperationContextParamResponse operationWithMapOperationContextParam( - OperationWithMapOperationContextParamRequest operationWithMapOperationContextParamRequest) - throws AwsServiceException, SdkClientException, QueryException { + OperationWithMapOperationContextParamRequest operationWithMapOperationContextParamRequest) + throws AwsServiceException, SdkClientException, QueryException { HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(OperationWithMapOperationContextParamResponse::builder); + .createResponseHandler(OperationWithMapOperationContextParamResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithMapOperationContextParamRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, - operationWithMapOperationContextParamRequest.overrideConfiguration().orElse(null)); + operationWithMapOperationContextParamRequest.overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithMapOperationContextParam"); return clientHandler - .execute(new ClientExecutionParams() - .withOperationName("OperationWithMapOperationContextParam").withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withInput(operationWithMapOperationContextParamRequest).withMetricCollector(apiCallMetricCollector) - .withMarshaller(new OperationWithMapOperationContextParamRequestMarshaller(protocolFactory))); + .execute(new ClientExecutionParams() + .withOperationName("OperationWithMapOperationContextParam").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration) + .withInput(operationWithMapOperationContextParamRequest).withMetricCollector(apiCallMetricCollector) + .withMarshaller(new OperationWithMapOperationContextParamRequestMarshaller(protocolFactory))); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); } @@ -584,31 +585,31 @@ public OperationWithMapOperationContextParamResponse operationWithMapOperationCo */ @Override public OperationWithNoneAuthTypeResponse operationWithNoneAuthType( - OperationWithNoneAuthTypeRequest operationWithNoneAuthTypeRequest) throws AwsServiceException, SdkClientException, - QueryException { + OperationWithNoneAuthTypeRequest operationWithNoneAuthTypeRequest) throws AwsServiceException, SdkClientException, + QueryException { HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(OperationWithNoneAuthTypeResponse::builder); + .createResponseHandler(OperationWithNoneAuthTypeResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithNoneAuthTypeRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, operationWithNoneAuthTypeRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithNoneAuthType"); return clientHandler - .execute(new ClientExecutionParams() - .withOperationName("OperationWithNoneAuthType").withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withInput(operationWithNoneAuthTypeRequest) - .withMetricCollector(apiCallMetricCollector) - .putExecutionAttribute(SdkInternalExecutionAttribute.IS_NONE_AUTH_TYPE_REQUEST, false) - .withMarshaller(new OperationWithNoneAuthTypeRequestMarshaller(protocolFactory))); + .execute(new ClientExecutionParams() + .withOperationName("OperationWithNoneAuthType").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withInput(operationWithNoneAuthTypeRequest) + .withMetricCollector(apiCallMetricCollector) + .putExecutionAttribute(SdkInternalExecutionAttribute.IS_NONE_AUTH_TYPE_REQUEST, false) + .withMarshaller(new OperationWithNoneAuthTypeRequestMarshaller(protocolFactory))); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); } @@ -633,30 +634,30 @@ public OperationWithNoneAuthTypeResponse operationWithNoneAuthType( */ @Override public OperationWithOperationContextParamResponse operationWithOperationContextParam( - OperationWithOperationContextParamRequest operationWithOperationContextParamRequest) throws AwsServiceException, - SdkClientException, QueryException { + OperationWithOperationContextParamRequest operationWithOperationContextParamRequest) throws AwsServiceException, + SdkClientException, QueryException { HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(OperationWithOperationContextParamResponse::builder); + .createResponseHandler(OperationWithOperationContextParamResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithOperationContextParamRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, - operationWithOperationContextParamRequest.overrideConfiguration().orElse(null)); + operationWithOperationContextParamRequest.overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithOperationContextParam"); return clientHandler - .execute(new ClientExecutionParams() - .withOperationName("OperationWithOperationContextParam").withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withInput(operationWithOperationContextParamRequest) - .withMetricCollector(apiCallMetricCollector) - .withMarshaller(new OperationWithOperationContextParamRequestMarshaller(protocolFactory))); + .execute(new ClientExecutionParams() + .withOperationName("OperationWithOperationContextParam").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withInput(operationWithOperationContextParamRequest) + .withMetricCollector(apiCallMetricCollector) + .withMarshaller(new OperationWithOperationContextParamRequestMarshaller(protocolFactory))); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); } @@ -680,35 +681,35 @@ public OperationWithOperationContextParamResponse operationWithOperationContextP */ @Override public OperationWithRequestCompressionResponse operationWithRequestCompression( - OperationWithRequestCompressionRequest operationWithRequestCompressionRequest) throws AwsServiceException, - SdkClientException, QueryException { + OperationWithRequestCompressionRequest operationWithRequestCompressionRequest) throws AwsServiceException, + SdkClientException, QueryException { HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(OperationWithRequestCompressionResponse::builder); + .createResponseHandler(OperationWithRequestCompressionResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithRequestCompressionRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, - operationWithRequestCompressionRequest.overrideConfiguration().orElse(null)); + operationWithRequestCompressionRequest.overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithRequestCompression"); return clientHandler - .execute(new ClientExecutionParams() - .withOperationName("OperationWithRequestCompression") - .withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withInput(operationWithRequestCompressionRequest) - .withMetricCollector(apiCallMetricCollector) - .putExecutionAttribute(SdkInternalExecutionAttribute.REQUEST_COMPRESSION, - RequestCompression.builder().encodings("gzip").isStreaming(false).build()) - .withMarshaller(new OperationWithRequestCompressionRequestMarshaller(protocolFactory))); + .execute(new ClientExecutionParams() + .withOperationName("OperationWithRequestCompression") + .withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler) + .withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration) + .withInput(operationWithRequestCompressionRequest) + .withMetricCollector(apiCallMetricCollector) + .putExecutionAttribute(SdkInternalExecutionAttribute.REQUEST_COMPRESSION, + RequestCompression.builder().encodings("gzip").isStreaming(false).build()) + .withMarshaller(new OperationWithRequestCompressionRequestMarshaller(protocolFactory))); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); } @@ -732,30 +733,30 @@ public OperationWithRequestCompressionResponse operationWithRequestCompression( */ @Override public OperationWithStaticContextParamsResponse operationWithStaticContextParams( - OperationWithStaticContextParamsRequest operationWithStaticContextParamsRequest) throws AwsServiceException, - SdkClientException, QueryException { + OperationWithStaticContextParamsRequest operationWithStaticContextParamsRequest) throws AwsServiceException, + SdkClientException, QueryException { HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(OperationWithStaticContextParamsResponse::builder); + .createResponseHandler(OperationWithStaticContextParamsResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(operationWithStaticContextParamsRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, - operationWithStaticContextParamsRequest.overrideConfiguration().orElse(null)); + operationWithStaticContextParamsRequest.overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "OperationWithStaticContextParams"); return clientHandler - .execute(new ClientExecutionParams() - .withOperationName("OperationWithStaticContextParams").withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withInput(operationWithStaticContextParamsRequest) - .withMetricCollector(apiCallMetricCollector) - .withMarshaller(new OperationWithStaticContextParamsRequestMarshaller(protocolFactory))); + .execute(new ClientExecutionParams() + .withOperationName("OperationWithStaticContextParams").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withInput(operationWithStaticContextParamsRequest) + .withMetricCollector(apiCallMetricCollector) + .withMarshaller(new OperationWithStaticContextParamsRequestMarshaller(protocolFactory))); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); } @@ -805,43 +806,47 @@ public OperationWithStaticContextParamsResponse operationWithStaticContextParams */ @Override public ReturnT putOperationWithChecksum(PutOperationWithChecksumRequest putOperationWithChecksumRequest, - RequestBody requestBody, ResponseTransformer responseTransformer) - throws AwsServiceException, SdkClientException, QueryException { + RequestBody requestBody, ResponseTransformer responseTransformer) + throws AwsServiceException, SdkClientException, QueryException { HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(PutOperationWithChecksumResponse::builder); + .createResponseHandler(PutOperationWithChecksumResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(putOperationWithChecksumRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, putOperationWithChecksumRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "PutOperationWithChecksum"); return clientHandler - .execute(new ClientExecutionParams() - .withOperationName("PutOperationWithChecksum") - .withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withInput(putOperationWithChecksumRequest) - .withMetricCollector(apiCallMetricCollector) - .putExecutionAttribute( - SdkInternalExecutionAttribute.HTTP_CHECKSUM, - HttpChecksum.builder().requestChecksumRequired(false) - .requestValidationMode(putOperationWithChecksumRequest.checksumModeAsString()) - .responseAlgorithms("CRC32C", "CRC32", "SHA1", "SHA256").isRequestStreaming(true) - .build()) - .withRequestBody(requestBody) - .withMarshaller( - StreamingRequestMarshaller.builder() - .delegateMarshaller(new PutOperationWithChecksumRequestMarshaller(protocolFactory)) - .requestBody(requestBody).build())); + .execute(new ClientExecutionParams() + .withOperationName("PutOperationWithChecksum") + .withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler) + .withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration) + .withInput(putOperationWithChecksumRequest) + .withMetricCollector(apiCallMetricCollector) + .putExecutionAttribute( + SdkInternalExecutionAttribute.HTTP_CHECKSUM, + HttpChecksum + .builder() + .requestChecksumRequired(false) + .isRequestStreaming(true) + .requestValidationMode(putOperationWithChecksumRequest.checksumModeAsString()) + .responseAlgorithmsV2(DefaultChecksumAlgorithm.CRC32C, + DefaultChecksumAlgorithm.CRC32, DefaultChecksumAlgorithm.SHA1, + DefaultChecksumAlgorithm.SHA256).build()) + .withRequestBody(requestBody) + .withMarshaller( + StreamingRequestMarshaller.builder() + .delegateMarshaller(new PutOperationWithChecksumRequestMarshaller(protocolFactory)) + .requestBody(requestBody).build())); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); } @@ -876,36 +881,36 @@ public ReturnT putOperationWithChecksum(PutOperationWithChecksumReques */ @Override public StreamingInputOperationResponse streamingInputOperation(StreamingInputOperationRequest streamingInputOperationRequest, - RequestBody requestBody) throws AwsServiceException, SdkClientException, QueryException { + RequestBody requestBody) throws AwsServiceException, SdkClientException, QueryException { HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(StreamingInputOperationResponse::builder); + .createResponseHandler(StreamingInputOperationResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(streamingInputOperationRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, streamingInputOperationRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "StreamingInputOperation"); return clientHandler - .execute(new ClientExecutionParams() - .withOperationName("StreamingInputOperation") - .withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler) - .withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withInput(streamingInputOperationRequest) - .withMetricCollector(apiCallMetricCollector) - .withRequestBody(requestBody) - .withMarshaller( - StreamingRequestMarshaller.builder() - .delegateMarshaller(new StreamingInputOperationRequestMarshaller(protocolFactory)) - .requestBody(requestBody).build())); + .execute(new ClientExecutionParams() + .withOperationName("StreamingInputOperation") + .withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler) + .withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration) + .withInput(streamingInputOperationRequest) + .withMetricCollector(apiCallMetricCollector) + .withRequestBody(requestBody) + .withMarshaller( + StreamingRequestMarshaller.builder() + .delegateMarshaller(new StreamingInputOperationRequestMarshaller(protocolFactory)) + .requestBody(requestBody).build())); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); } @@ -936,30 +941,30 @@ public StreamingInputOperationResponse streamingInputOperation(StreamingInputOpe */ @Override public ReturnT streamingOutputOperation(StreamingOutputOperationRequest streamingOutputOperationRequest, - ResponseTransformer responseTransformer) throws AwsServiceException, - SdkClientException, QueryException { + ResponseTransformer responseTransformer) throws AwsServiceException, + SdkClientException, QueryException { HttpResponseHandler responseHandler = protocolFactory - .createResponseHandler(StreamingOutputOperationResponse::builder); + .createResponseHandler(StreamingOutputOperationResponse::builder); HttpResponseHandler errorResponseHandler = protocolFactory.createErrorResponseHandler(); SdkClientConfiguration clientConfiguration = updateSdkClientConfiguration(streamingOutputOperationRequest, - this.clientConfiguration); + this.clientConfiguration); List metricPublishers = resolveMetricPublishers(clientConfiguration, streamingOutputOperationRequest - .overrideConfiguration().orElse(null)); + .overrideConfiguration().orElse(null)); MetricCollector apiCallMetricCollector = metricPublishers.isEmpty() ? NoOpMetricCollector.create() : MetricCollector - .create("ApiCall"); + .create("ApiCall"); try { apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "StreamingOutputOperation"); return clientHandler.execute( - new ClientExecutionParams() - .withOperationName("StreamingOutputOperation").withProtocolMetadata(protocolMetadata) - .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withInput(streamingOutputOperationRequest) - .withMetricCollector(apiCallMetricCollector) - .withMarshaller(new StreamingOutputOperationRequestMarshaller(protocolFactory)), responseTransformer); + new ClientExecutionParams() + .withOperationName("StreamingOutputOperation").withProtocolMetadata(protocolMetadata) + .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) + .withRequestConfiguration(clientConfiguration).withInput(streamingOutputOperationRequest) + .withMetricCollector(apiCallMetricCollector) + .withMarshaller(new StreamingOutputOperationRequestMarshaller(protocolFactory)), responseTransformer); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); } @@ -984,8 +989,8 @@ private T applySignerOverride(T request, Signer signer) } Consumer signerOverride = b -> b.signer(signer).build(); AwsRequestOverrideConfiguration overrideConfiguration = request.overrideConfiguration() - .map(c -> c.toBuilder().applyMutation(signerOverride).build()) - .orElse((AwsRequestOverrideConfiguration.builder().applyMutation(signerOverride).build())); + .map(c -> c.toBuilder().applyMutation(signerOverride).build()) + .orElse((AwsRequestOverrideConfiguration.builder().applyMutation(signerOverride).build())); return (T) request.toBuilder().overrideConfiguration(overrideConfiguration).build(); } @@ -995,7 +1000,7 @@ public final String serviceName() { } private static List resolveMetricPublishers(SdkClientConfiguration clientConfiguration, - RequestOverrideConfiguration requestOverrideConfiguration) { + RequestOverrideConfiguration requestOverrideConfiguration) { List publishers = null; if (requestOverrideConfiguration != null) { publishers = requestOverrideConfiguration.metricPublishers(); @@ -1048,11 +1053,11 @@ private SdkClientConfiguration updateSdkClientConfiguration(SdkRequest request, private AwsQueryProtocolFactory init() { return AwsQueryProtocolFactory - .builder() - .registerModeledException( - ExceptionMetadata.builder().errorCode("InvalidInput") - .exceptionBuilderSupplier(InvalidInputException::builder).httpStatusCode(400).build()) - .clientConfiguration(clientConfiguration).defaultServiceExceptionSupplier(QueryException::builder).build(); + .builder() + .registerModeledException( + ExceptionMetadata.builder().errorCode("InvalidInput") + .exceptionBuilderSupplier(InvalidInputException::builder).httpStatusCode(400).build()) + .clientConfiguration(clientConfiguration).defaultServiceExceptionSupplier(QueryException::builder).build(); } @Override diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-xml-async-client-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-xml-async-client-class.java index 1a5580737ec7..4f777ed50154 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-xml-async-client-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-xml-async-client-class.java @@ -22,6 +22,7 @@ import software.amazon.awssdk.awscore.internal.AwsProtocolMetadata; import software.amazon.awssdk.awscore.internal.AwsServiceProtocol; import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; +import software.amazon.awssdk.checksums.DefaultChecksumAlgorithm; import software.amazon.awssdk.core.CredentialType; import software.amazon.awssdk.core.RequestOverrideConfiguration; import software.amazon.awssdk.core.Response; @@ -428,9 +429,10 @@ public CompletableFuture getOperationWithCheck .withMetricCollector(apiCallMetricCollector) .putExecutionAttribute( SdkInternalExecutionAttribute.HTTP_CHECKSUM, - HttpChecksum.builder().requestChecksumRequired(true) + HttpChecksum.builder().requestChecksumRequired(true).isRequestStreaming(false) .requestAlgorithm(getOperationWithChecksumRequest.checksumAlgorithmAsString()) - .isRequestStreaming(false).build()).withInput(getOperationWithChecksumRequest)); + .requestAlgorithmHeader("x-amz-sdk-checksum-algorithm").build()) + .withInput(getOperationWithChecksumRequest)); CompletableFuture whenCompleteFuture = null; whenCompleteFuture = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -699,10 +701,14 @@ public CompletableFuture putOperationWithChecksum( .withMetricCollector(apiCallMetricCollector) .putExecutionAttribute( SdkInternalExecutionAttribute.HTTP_CHECKSUM, - HttpChecksum.builder().requestChecksumRequired(false) + HttpChecksum + .builder() + .requestChecksumRequired(false) + .isRequestStreaming(true) .requestValidationMode(putOperationWithChecksumRequest.checksumModeAsString()) - .responseAlgorithms("CRC32C", "CRC32", "SHA1", "SHA256").isRequestStreaming(true) - .build()).withAsyncRequestBody(requestBody) + .responseAlgorithmsV2(DefaultChecksumAlgorithm.CRC32C, + DefaultChecksumAlgorithm.CRC32, DefaultChecksumAlgorithm.SHA1, + DefaultChecksumAlgorithm.SHA256).build()).withAsyncRequestBody(requestBody) .withInput(putOperationWithChecksumRequest), asyncResponseTransformer); CompletableFuture whenCompleteFuture = null; AsyncResponseTransformer finalAsyncResponseTransformer = asyncResponseTransformer; diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-xml-client-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-xml-client-class.java index 51074f54c69c..9bad15fd6e47 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-xml-client-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-xml-client-class.java @@ -12,6 +12,7 @@ import software.amazon.awssdk.awscore.internal.AwsProtocolMetadata; import software.amazon.awssdk.awscore.internal.AwsServiceProtocol; import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; +import software.amazon.awssdk.checksums.DefaultChecksumAlgorithm; import software.amazon.awssdk.core.CredentialType; import software.amazon.awssdk.core.RequestOverrideConfiguration; import software.amazon.awssdk.core.Response; @@ -287,9 +288,9 @@ public GetOperationWithChecksumResponse getOperationWithChecksum( .withInput(getOperationWithChecksumRequest) .putExecutionAttribute( SdkInternalExecutionAttribute.HTTP_CHECKSUM, - HttpChecksum.builder().requestChecksumRequired(true) + HttpChecksum.builder().requestChecksumRequired(true).isRequestStreaming(false) .requestAlgorithm(getOperationWithChecksumRequest.checksumAlgorithmAsString()) - .isRequestStreaming(false).build()) + .requestAlgorithmHeader("x-amz-sdk-checksum-algorithm").build()) .withMarshaller(new GetOperationWithChecksumRequestMarshaller(protocolFactory))); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -450,11 +451,11 @@ public OperationWithRequestCompressionResponse operationWithRequestCompression( * The content to send to the service. A {@link RequestBody} can be created using one of several factory * methods for various sources of data. For example, to create a request body from a file you can do the * following. - * + * *

      * {@code RequestBody.fromFile(new File("myfile.txt"))}
      * 
- * + * * See documentation in {@link RequestBody} for additional details and which sources of data are supported. * The service documentation for the request content is as follows ' *

@@ -514,10 +515,14 @@ public ReturnT putOperationWithChecksum(PutOperationWithChecksumReques .withMetricCollector(apiCallMetricCollector) .putExecutionAttribute( SdkInternalExecutionAttribute.HTTP_CHECKSUM, - HttpChecksum.builder().requestChecksumRequired(false) + HttpChecksum + .builder() + .requestChecksumRequired(false) + .isRequestStreaming(true) .requestValidationMode(putOperationWithChecksumRequest.checksumModeAsString()) - .responseAlgorithms("CRC32C", "CRC32", "SHA1", "SHA256").isRequestStreaming(true) - .build()) + .responseAlgorithmsV2(DefaultChecksumAlgorithm.CRC32C, + DefaultChecksumAlgorithm.CRC32, DefaultChecksumAlgorithm.SHA1, + DefaultChecksumAlgorithm.SHA256).build()) .withRequestBody(requestBody) .withMarshaller( StreamingRequestMarshaller.builder() @@ -536,11 +541,11 @@ public ReturnT putOperationWithChecksum(PutOperationWithChecksumReques * The content to send to the service. A {@link RequestBody} can be created using one of several factory * methods for various sources of data. For example, to create a request body from a file you can do the * following. - * + * *

      * {@code RequestBody.fromFile(new File("myfile.txt"))}
      * 
- * + * * See documentation in {@link RequestBody} for additional details and which sources of data are supported. * The service documentation for the request content is as follows 'This be a stream' * @return Result of the StreamingInputOperation operation returned by the service. diff --git a/core/annotations/pom.xml b/core/annotations/pom.xml index 86faa3d94780..805793193372 100644 --- a/core/annotations/pom.xml +++ b/core/annotations/pom.xml @@ -20,7 +20,7 @@ core software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 diff --git a/core/arns/pom.xml b/core/arns/pom.xml index 59be79b02ab4..99787c0284b0 100644 --- a/core/arns/pom.xml +++ b/core/arns/pom.xml @@ -20,7 +20,7 @@ core software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 diff --git a/core/auth-crt/pom.xml b/core/auth-crt/pom.xml index 96361ff95be3..fb9aa10cefbb 100644 --- a/core/auth-crt/pom.xml +++ b/core/auth-crt/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk core - 2.29.52 + 2.30.0 auth-crt diff --git a/core/auth/pom.xml b/core/auth/pom.xml index ac1bb54fe53f..152724017537 100644 --- a/core/auth/pom.xml +++ b/core/auth/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk core - 2.29.52 + 2.30.0 auth diff --git a/core/auth/src/main/java/software/amazon/awssdk/auth/signer/params/SignerChecksumParams.java b/core/auth/src/main/java/software/amazon/awssdk/auth/signer/params/SignerChecksumParams.java index 2c4199c36987..44db8e8e0b8e 100644 --- a/core/auth/src/main/java/software/amazon/awssdk/auth/signer/params/SignerChecksumParams.java +++ b/core/auth/src/main/java/software/amazon/awssdk/auth/signer/params/SignerChecksumParams.java @@ -21,7 +21,11 @@ /** * Encapsulates the Checksum information like Algorithm and header name for the checksum in header/trailer locations. + * @deprecated this class is deprecated and will not be updated. Use + * {@link software.amazon.awssdk.http.auth.spi.signer.SignerProperty} and + * {@link software.amazon.awssdk.http.auth.spi.signer.HttpSigner} in 'http-auth-spi' instead. */ +@Deprecated @SdkPublicApi public class SignerChecksumParams { diff --git a/core/aws-core/pom.xml b/core/aws-core/pom.xml index 67eacd36c4b9..d4542102417d 100644 --- a/core/aws-core/pom.xml +++ b/core/aws-core/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk core - 2.29.52 + 2.30.0 aws-core diff --git a/core/aws-core/src/main/java/software/amazon/awssdk/awscore/internal/AwsExecutionContextBuilder.java b/core/aws-core/src/main/java/software/amazon/awssdk/awscore/internal/AwsExecutionContextBuilder.java index 3982ce9aa27b..2e24e1b64101 100644 --- a/core/aws-core/src/main/java/software/amazon/awssdk/awscore/internal/AwsExecutionContextBuilder.java +++ b/core/aws-core/src/main/java/software/amazon/awssdk/awscore/internal/AwsExecutionContextBuilder.java @@ -122,6 +122,10 @@ private AwsExecutionContextBuilder() { .putAttribute(AwsExecutionAttribute.AWS_AUTH_ACCOUNT_ID_ENDPOINT_MODE, clientConfig.option(AwsClientOption.ACCOUNT_ID_ENDPOINT_MODE)) .putAttribute(RESOLVED_CHECKSUM_SPECS, HttpChecksumResolver.resolveChecksumSpecs(executionAttributes)) + .putAttribute(SdkInternalExecutionAttribute.REQUEST_CHECKSUM_CALCULATION, + clientConfig.option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION)) + .putAttribute(SdkInternalExecutionAttribute.RESPONSE_CHECKSUM_VALIDATION, + clientConfig.option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION)) .putAttribute(SdkInternalExecutionAttribute.BUSINESS_METRICS, resolveUserAgentBusinessMetrics(clientConfig)); // Auth Scheme resolution related attributes diff --git a/core/checksums-spi/pom.xml b/core/checksums-spi/pom.xml index b8caf230471d..ad17257c13cf 100644 --- a/core/checksums-spi/pom.xml +++ b/core/checksums-spi/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk core - 2.29.52 + 2.30.0 checksums-spi diff --git a/core/checksums/pom.xml b/core/checksums/pom.xml index a3ca9bf7344b..85bb343ab815 100644 --- a/core/checksums/pom.xml +++ b/core/checksums/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk core - 2.29.52 + 2.30.0 checksums diff --git a/core/checksums/src/main/java/software/amazon/awssdk/checksums/DefaultChecksumAlgorithm.java b/core/checksums/src/main/java/software/amazon/awssdk/checksums/DefaultChecksumAlgorithm.java index 10a50c2e704f..017345c822b9 100644 --- a/core/checksums/src/main/java/software/amazon/awssdk/checksums/DefaultChecksumAlgorithm.java +++ b/core/checksums/src/main/java/software/amazon/awssdk/checksums/DefaultChecksumAlgorithm.java @@ -15,6 +15,7 @@ package software.amazon.awssdk.checksums; +import java.util.Locale; import java.util.concurrent.ConcurrentHashMap; import software.amazon.awssdk.annotations.SdkProtectedApi; import software.amazon.awssdk.checksums.spi.ChecksumAlgorithm; @@ -24,6 +25,7 @@ */ @SdkProtectedApi public final class DefaultChecksumAlgorithm { + public static final ChecksumAlgorithm CRC32C = of("CRC32C"); public static final ChecksumAlgorithm CRC32 = of("CRC32"); public static final ChecksumAlgorithm MD5 = of("MD5"); @@ -38,11 +40,29 @@ private static ChecksumAlgorithm of(String name) { return ChecksumAlgorithmsCache.put(name); } + public static ChecksumAlgorithm fromValue(String algorithm) { + if (algorithm == null) { + return null; + } + + return ChecksumAlgorithmsCache.VALUES.get(algorithm.toUpperCase(Locale.US)); + } + private static final class ChecksumAlgorithmsCache { private static final ConcurrentHashMap VALUES = new ConcurrentHashMap<>(); private static ChecksumAlgorithm put(String value) { - return VALUES.computeIfAbsent(value, v -> () -> v); + return VALUES.computeIfAbsent(value, v -> new ChecksumAlgorithm() { + @Override + public String algorithmId() { + return v; + } + + @Override + public String toString() { + return algorithmId(); + } + }); } } } diff --git a/core/crt-core/pom.xml b/core/crt-core/pom.xml index bff3f681dede..bb6bad60631c 100644 --- a/core/crt-core/pom.xml +++ b/core/crt-core/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk core - 2.29.52 + 2.30.0 crt-core diff --git a/core/endpoints-spi/pom.xml b/core/endpoints-spi/pom.xml index 3bc6dc9bdb0e..d1600049b8d5 100644 --- a/core/endpoints-spi/pom.xml +++ b/core/endpoints-spi/pom.xml @@ -20,7 +20,7 @@ core software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 diff --git a/core/http-auth-aws-crt/pom.xml b/core/http-auth-aws-crt/pom.xml index e16ae9f3426d..1e44f0ae9ef0 100644 --- a/core/http-auth-aws-crt/pom.xml +++ b/core/http-auth-aws-crt/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk core - 2.29.52 + 2.30.0 http-auth-aws-crt diff --git a/core/http-auth-aws-eventstream/pom.xml b/core/http-auth-aws-eventstream/pom.xml index 2e96139c231f..0b63f96a8842 100644 --- a/core/http-auth-aws-eventstream/pom.xml +++ b/core/http-auth-aws-eventstream/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk core - 2.29.52 + 2.30.0 http-auth-aws-eventstream diff --git a/core/http-auth-aws/pom.xml b/core/http-auth-aws/pom.xml index 80c6bec388d4..bf919096ce1c 100644 --- a/core/http-auth-aws/pom.xml +++ b/core/http-auth-aws/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk core - 2.29.52 + 2.30.0 http-auth-aws diff --git a/core/http-auth-aws/src/main/java/software/amazon/awssdk/http/auth/aws/internal/signer/AwsChunkedV4PayloadSigner.java b/core/http-auth-aws/src/main/java/software/amazon/awssdk/http/auth/aws/internal/signer/AwsChunkedV4PayloadSigner.java index a0c373792eb7..082d683ce1fd 100644 --- a/core/http-auth-aws/src/main/java/software/amazon/awssdk/http/auth/aws/internal/signer/AwsChunkedV4PayloadSigner.java +++ b/core/http-auth-aws/src/main/java/software/amazon/awssdk/http/auth/aws/internal/signer/AwsChunkedV4PayloadSigner.java @@ -117,6 +117,7 @@ public ContentStreamProvider sign(ContentStreamProvider payload, V4RequestSignin @Override public Publisher signAsync(Publisher payload, V4RequestSigningResult requestSigningResult) { + // TODO(sra-identity-and-auth): implement this first and remove addFlexibleChecksumInTrailer logic in HttpChecksumStage throw new UnsupportedOperationException(); } diff --git a/core/http-auth-spi/pom.xml b/core/http-auth-spi/pom.xml index c907122420c0..d3df973fb71d 100644 --- a/core/http-auth-spi/pom.xml +++ b/core/http-auth-spi/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk core - 2.29.52 + 2.30.0 http-auth-spi diff --git a/core/http-auth/pom.xml b/core/http-auth/pom.xml index f943d0debb5f..35f355ede061 100644 --- a/core/http-auth/pom.xml +++ b/core/http-auth/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk core - 2.29.52 + 2.30.0 http-auth diff --git a/core/identity-spi/pom.xml b/core/identity-spi/pom.xml index 730674d2c81b..9bd2d7de9df0 100644 --- a/core/identity-spi/pom.xml +++ b/core/identity-spi/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk core - 2.29.52 + 2.30.0 identity-spi diff --git a/core/imds/pom.xml b/core/imds/pom.xml index 42c17d1568a4..1f5baf68f7fc 100644 --- a/core/imds/pom.xml +++ b/core/imds/pom.xml @@ -20,7 +20,7 @@ core software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 imds diff --git a/core/json-utils/pom.xml b/core/json-utils/pom.xml index 467feeaf470b..b04488e1d5b3 100644 --- a/core/json-utils/pom.xml +++ b/core/json-utils/pom.xml @@ -20,7 +20,7 @@ core software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 diff --git a/core/metrics-spi/pom.xml b/core/metrics-spi/pom.xml index 0f6945179cb3..9103d73c9cff 100644 --- a/core/metrics-spi/pom.xml +++ b/core/metrics-spi/pom.xml @@ -5,7 +5,7 @@ core software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 diff --git a/core/pom.xml b/core/pom.xml index 5d081eaff1dc..521dd8b2746e 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -21,7 +21,7 @@ aws-sdk-java-pom software.amazon.awssdk - 2.29.52 + 2.30.0 core diff --git a/core/profiles/pom.xml b/core/profiles/pom.xml index c4d512a43f7e..dffc17083858 100644 --- a/core/profiles/pom.xml +++ b/core/profiles/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk core - 2.29.52 + 2.30.0 profiles diff --git a/core/profiles/src/main/java/software/amazon/awssdk/profiles/ProfileProperty.java b/core/profiles/src/main/java/software/amazon/awssdk/profiles/ProfileProperty.java index 72417341c61e..f27c9f8949c4 100644 --- a/core/profiles/src/main/java/software/amazon/awssdk/profiles/ProfileProperty.java +++ b/core/profiles/src/main/java/software/amazon/awssdk/profiles/ProfileProperty.java @@ -180,9 +180,15 @@ public final class ProfileProperty { public static final String ENDPOINT_URL = "endpoint_url"; /** - * Configure an optional identification value to be appended to the user agent header. - * The value should be less than 50 characters in length and is null by default. + * The request checksum calculation setting. The default value is WHEN_SUPPORTED. */ + public static final String REQUEST_CHECKSUM_CALCULATION = "request_checksum_calculation"; + + /** + * The response checksum validation setting. The default value is WHEN_SUPPORTED. + */ + public static final String RESPONSE_CHECKSUM_VALIDATION = "response_checksum_validation"; + public static final String SDK_UA_APP_ID = "sdk_ua_app_id"; private ProfileProperty() { diff --git a/core/protocols/aws-cbor-protocol/pom.xml b/core/protocols/aws-cbor-protocol/pom.xml index 4e8352757e20..8c7ccea84bf8 100644 --- a/core/protocols/aws-cbor-protocol/pom.xml +++ b/core/protocols/aws-cbor-protocol/pom.xml @@ -20,7 +20,7 @@ protocols software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 diff --git a/core/protocols/aws-json-protocol/pom.xml b/core/protocols/aws-json-protocol/pom.xml index 9b190dc5acbc..6d05c0a1f9b1 100644 --- a/core/protocols/aws-json-protocol/pom.xml +++ b/core/protocols/aws-json-protocol/pom.xml @@ -20,7 +20,7 @@ protocols software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 diff --git a/core/protocols/aws-query-protocol/pom.xml b/core/protocols/aws-query-protocol/pom.xml index 9a2aec11546a..1cd47bd90fc9 100644 --- a/core/protocols/aws-query-protocol/pom.xml +++ b/core/protocols/aws-query-protocol/pom.xml @@ -20,7 +20,7 @@ protocols software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 diff --git a/core/protocols/aws-xml-protocol/pom.xml b/core/protocols/aws-xml-protocol/pom.xml index a3088d1e8b9d..7e76f7021d91 100644 --- a/core/protocols/aws-xml-protocol/pom.xml +++ b/core/protocols/aws-xml-protocol/pom.xml @@ -20,7 +20,7 @@ protocols software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 diff --git a/core/protocols/pom.xml b/core/protocols/pom.xml index 32c71ac10b5f..e4bb4f65f70c 100644 --- a/core/protocols/pom.xml +++ b/core/protocols/pom.xml @@ -20,7 +20,7 @@ core software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 diff --git a/core/protocols/protocol-core/pom.xml b/core/protocols/protocol-core/pom.xml index 4a3158b1768a..5ffecdf34be8 100644 --- a/core/protocols/protocol-core/pom.xml +++ b/core/protocols/protocol-core/pom.xml @@ -20,7 +20,7 @@ protocols software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 diff --git a/core/protocols/smithy-rpcv2-protocol/pom.xml b/core/protocols/smithy-rpcv2-protocol/pom.xml index 796ecf03c37a..aa7c4c77f5be 100644 --- a/core/protocols/smithy-rpcv2-protocol/pom.xml +++ b/core/protocols/smithy-rpcv2-protocol/pom.xml @@ -20,7 +20,7 @@ protocols software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 diff --git a/core/regions/pom.xml b/core/regions/pom.xml index 1782191e0c27..02a466f730d5 100644 --- a/core/regions/pom.xml +++ b/core/regions/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk core - 2.29.52 + 2.30.0 regions diff --git a/core/regions/src/main/resources/software/amazon/awssdk/regions/internal/region/endpoints.json b/core/regions/src/main/resources/software/amazon/awssdk/regions/internal/region/endpoints.json index 37297d3cca1d..d0a69877c0f4 100644 --- a/core/regions/src/main/resources/software/amazon/awssdk/regions/internal/region/endpoints.json +++ b/core/regions/src/main/resources/software/amazon/awssdk/regions/internal/region/endpoints.json @@ -2924,6 +2924,7 @@ "ap-southeast-3" : { }, "ap-southeast-4" : { }, "ap-southeast-5" : { }, + "ap-southeast-7" : { }, "ca-central-1" : { }, "ca-west-1" : { }, "eu-central-1" : { }, @@ -18850,6 +18851,8 @@ "ap-southeast-2" : { }, "ap-southeast-3" : { }, "ap-southeast-4" : { }, + "ap-southeast-5" : { }, + "ap-southeast-7" : { }, "ca-central-1" : { }, "ca-west-1" : { }, "eu-central-1" : { }, @@ -18891,6 +18894,7 @@ "il-central-1" : { }, "me-central-1" : { }, "me-south-1" : { }, + "mx-central-1" : { }, "sa-east-1" : { }, "us-east-1" : { "variants" : [ { diff --git a/core/retries-spi/pom.xml b/core/retries-spi/pom.xml index 771e1ad78178..1fda0f3f0bef 100644 --- a/core/retries-spi/pom.xml +++ b/core/retries-spi/pom.xml @@ -20,7 +20,7 @@ core software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 diff --git a/core/retries/pom.xml b/core/retries/pom.xml index 1fdc8958e591..b5af9c4ee60a 100644 --- a/core/retries/pom.xml +++ b/core/retries/pom.xml @@ -21,7 +21,7 @@ core software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 diff --git a/core/sdk-core/pom.xml b/core/sdk-core/pom.xml index 55069da94d84..8cf98026f737 100644 --- a/core/sdk-core/pom.xml +++ b/core/sdk-core/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk core - 2.29.52 + 2.30.0 sdk-core AWS Java SDK :: SDK Core diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/SdkSystemSetting.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/SdkSystemSetting.java index 479cf9a9e191..58a5df2fd7aa 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/SdkSystemSetting.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/SdkSystemSetting.java @@ -236,6 +236,16 @@ public enum SdkSystemSetting implements SystemSetting { */ AWS_PARTITIONS_FILE("aws.partitionsFile", null), + /** + * The request checksum calculation setting. The default value is WHEN_SUPPORTED. + */ + AWS_REQUEST_CHECKSUM_CALCULATION("aws.requestChecksumCalculation", null), + + /** + * The response checksum validation setting. The default value is WHEN_SUPPORTED. + */ + AWS_RESPONSE_CHECKSUM_VALIDATION("aws.responseChecksumValidation", null), + /** * Configure an optional identification value to be appended to the user agent header. * The value should be less than 50 characters in length and is null by default. diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/checksums/Algorithm.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/checksums/Algorithm.java index 8054257580ff..0087dc362565 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/checksums/Algorithm.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/checksums/Algorithm.java @@ -31,6 +31,7 @@ public enum Algorithm { CRC32C("crc32c", 8), CRC32("crc32", 8), + CRC64NVME("crc64nvme", 12), SHA256("sha256", 44), SHA1("sha1", 28), ; diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/checksums/ChecksumSpecs.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/checksums/ChecksumSpecs.java index 56a794ebc5dc..382be01a4aee 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/checksums/ChecksumSpecs.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/checksums/ChecksumSpecs.java @@ -18,21 +18,30 @@ import java.util.Collections; import java.util.List; import java.util.Objects; -import software.amazon.awssdk.annotations.SdkInternalApi; +import java.util.stream.Collectors; +import software.amazon.awssdk.annotations.SdkProtectedApi; +import software.amazon.awssdk.checksums.spi.ChecksumAlgorithm; +import software.amazon.awssdk.core.internal.util.HttpChecksumUtils; +import software.amazon.awssdk.utils.builder.CopyableBuilder; +import software.amazon.awssdk.utils.builder.ToCopyableBuilder; /** * Defines all the Specifications that are required while adding HttpChecksum to a request and validating HttpChecksum of a * response. + * + *

+ * Implementor notes: this class is technically not needed, but we can't remove it now for backwards compatibility reasons. */ -@SdkInternalApi -public class ChecksumSpecs { +@SdkProtectedApi +public class ChecksumSpecs implements ToCopyableBuilder { - private final Algorithm algorithm; + private final ChecksumAlgorithm algorithm; private final String headerName; - private final List responseValidationAlgorithms; + private final List responseValidationAlgorithms; private final boolean isValidationEnabled; private final boolean isRequestChecksumRequired; private final boolean isRequestStreaming; + private final String requestAlgorithmHeader; private ChecksumSpecs(Builder builder) { this.algorithm = builder.algorithm; @@ -41,13 +50,22 @@ private ChecksumSpecs(Builder builder) { this.isValidationEnabled = builder.isValidationEnabled; this.isRequestChecksumRequired = builder.isRequestChecksumRequired; this.isRequestStreaming = builder.isRequestStreaming; + this.requestAlgorithmHeader = builder.requestAlgorithmHeader; } public static Builder builder() { return new Builder(); } + /** + * @deprecated use {@link #algorithmV2()} instead + */ + @Deprecated public Algorithm algorithm() { + return HttpChecksumUtils.toLegacyChecksumAlgorithm(algorithm); + } + + public ChecksumAlgorithm algorithmV2() { return algorithm; } @@ -67,7 +85,22 @@ public boolean isRequestChecksumRequired() { return isRequestChecksumRequired; } + public String requestAlgorithmHeader() { + return requestAlgorithmHeader; + } + + /** + * @deprecated use {@link #algorithmV2()} instead + */ + @Deprecated public List responseValidationAlgorithms() { + return responseValidationAlgorithms == null ? null : + responseValidationAlgorithms.stream() + .map(algo -> HttpChecksumUtils.toLegacyChecksumAlgorithm(algo)) + .collect(Collectors.toList()); + } + + public List responseValidationAlgorithmsV2() { return responseValidationAlgorithms; } @@ -85,6 +118,7 @@ public boolean equals(Object o) { Objects.equals(headerName(), checksum.headerName()) && Objects.equals(responseValidationAlgorithms(), checksum.responseValidationAlgorithms()) && Objects.equals(isValidationEnabled(), checksum.isValidationEnabled()) && + Objects.equals(requestAlgorithmHeader(), checksum.requestAlgorithmHeader()) && Objects.equals(isRequestChecksumRequired(), checksum.isRequestChecksumRequired()); } @@ -96,6 +130,7 @@ public int hashCode() { result = 31 * result + (isValidationEnabled ? 1 : 0); result = 31 * result + (isRequestChecksumRequired ? 1 : 0); result = 31 * result + (isRequestStreaming ? 1 : 0); + result = 31 * result + (requestAlgorithmHeader != null ? requestAlgorithmHeader.hashCode() : 0); return result; } @@ -108,13 +143,20 @@ public String toString() { ", isValidationEnabled=" + isValidationEnabled + ", isRequestChecksumRequired=" + isRequestChecksumRequired + ", isStreamingData=" + isRequestStreaming + + ", requestAlgorithmHeader='" + requestAlgorithmHeader + '\'' + '}'; } - public static final class Builder { - private Algorithm algorithm; + @Override + public ChecksumSpecs.Builder toBuilder() { + return new Builder(this); + } + + public static final class Builder implements CopyableBuilder { + private String requestAlgorithmHeader; + private ChecksumAlgorithm algorithm; private String headerName; - private List responseValidationAlgorithms; + private List responseValidationAlgorithms; private boolean isValidationEnabled; private boolean isRequestChecksumRequired; private boolean isRequestStreaming; @@ -122,7 +164,26 @@ public static final class Builder { private Builder() { } + private Builder(ChecksumSpecs checksumSpecs) { + this.algorithm = checksumSpecs.algorithm; + this.headerName = checksumSpecs.headerName; + this.responseValidationAlgorithms = checksumSpecs.responseValidationAlgorithms; + this.isValidationEnabled = checksumSpecs.isValidationEnabled; + this.isRequestChecksumRequired = checksumSpecs.isRequestChecksumRequired; + this.isRequestStreaming = checksumSpecs.isRequestStreaming; + this.requestAlgorithmHeader = checksumSpecs.requestAlgorithmHeader; + } + + /** + * @deprecated use {@link #algorithmV2(ChecksumAlgorithm)} instead + */ + @Deprecated public Builder algorithm(Algorithm algorithm) { + this.algorithm = HttpChecksumUtils.toNewChecksumAlgorithm(algorithm); + return this; + } + + public Builder algorithmV2(ChecksumAlgorithm algorithm) { this.algorithm = algorithm; return this; } @@ -132,7 +193,21 @@ public Builder headerName(String headerName) { return this; } + /** + * @deprecated use {@link #responseValidationAlgorithms} instead + */ + @Deprecated public Builder responseValidationAlgorithms(List responseValidationAlgorithms) { + this.responseValidationAlgorithms = + responseValidationAlgorithms == null ? null : + Collections.unmodifiableList( + responseValidationAlgorithms.stream() + .map(algorithm -> HttpChecksumUtils.toNewChecksumAlgorithm(algorithm)) + .collect(Collectors.toList())); + return this; + } + + public Builder responseValidationAlgorithmsV2(List responseValidationAlgorithms) { this.responseValidationAlgorithms = responseValidationAlgorithms != null ? Collections.unmodifiableList(responseValidationAlgorithms) : null; return this; @@ -153,6 +228,15 @@ public Builder isRequestStreaming(boolean isRequestStreaming) { return this; } + /** + * Configure the request algorithm header, for example: "x-amz-sdk-checksum-algorithm:CRC32" Note this is different from + * {@link #headerName(String)} which is the checksum header, "x-amz-checksum-crc32:zc3xbw==" + */ + public Builder requestAlgorithmHeader(String requestAlgorithmHeader) { + this.requestAlgorithmHeader = requestAlgorithmHeader; + return this; + } + public ChecksumSpecs build() { return new ChecksumSpecs(this); } diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/checksums/RequestChecksumCalculation.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/checksums/RequestChecksumCalculation.java new file mode 100644 index 000000000000..b364b699c733 --- /dev/null +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/checksums/RequestChecksumCalculation.java @@ -0,0 +1,57 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.core.checksums; + +import software.amazon.awssdk.annotations.SdkPublicApi; + +/** + * Enum class for request checksum calculation setting. + */ +@SdkPublicApi +public enum RequestChecksumCalculation { + + /** + * Checksum will be calculated for request if supported. Default setting. + */ + WHEN_SUPPORTED, + + /** + * Checksum will only be calculated for request if required. + */ + WHEN_REQUIRED, + ; + + /** + * Returns the appropriate RequestChecksumCalculation value after parsing the parameter. + * @param s RequestChecksumCalculation in String format. + * @return RequestChecksumCalculation enum value. + * @throws IllegalArgumentException Unrecognized value for request checksum calculation. + */ + public static RequestChecksumCalculation fromValue(String s) { + if (s == null) { + return null; + } + + for (RequestChecksumCalculation value : values()) { + if (value.name().equalsIgnoreCase(s)) { + return value; + } + } + + throw new IllegalArgumentException("Unrecognized value for request checksum calculation: " + s + "\n Valid values are: " + + "when_supported and when_required"); + } +} diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/checksums/RequestChecksumCalculationResolver.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/checksums/RequestChecksumCalculationResolver.java new file mode 100644 index 000000000000..c6d8ec1dec1b --- /dev/null +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/checksums/RequestChecksumCalculationResolver.java @@ -0,0 +1,99 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.core.checksums; + +import java.util.Optional; +import java.util.function.Supplier; +import software.amazon.awssdk.annotations.SdkProtectedApi; +import software.amazon.awssdk.core.SdkSystemSetting; +import software.amazon.awssdk.profiles.ProfileFile; +import software.amazon.awssdk.profiles.ProfileProperty; +import software.amazon.awssdk.utils.OptionalUtils; + +/** + * Allows customizing the variables used during determination of a {@link RequestChecksumCalculation}. + * Created via{@link #create()}. + */ +@SdkProtectedApi +public final class RequestChecksumCalculationResolver { + + private static final RequestChecksumCalculation SDK_DEFAULT_CHECKSUM_CALCULATION = RequestChecksumCalculation.WHEN_SUPPORTED; + + private Supplier profileFile; + private String profileName; + private RequestChecksumCalculation defaultChecksumCalculation; + + private RequestChecksumCalculationResolver() { + } + + public static RequestChecksumCalculationResolver create() { + return new RequestChecksumCalculationResolver(); + } + + /** + * Configure the profile file that should be used when determining the {@link RequestChecksumCalculation}. The supplier is + * only consulted if a higher-priority determinant (e.g. environment variables) does not find the setting. + */ + public RequestChecksumCalculationResolver profileFile(Supplier profileFile) { + this.profileFile = profileFile; + return this; + } + + /** + * Configure the profile file name should be used when determining the {@link RequestChecksumCalculation}. + */ + public RequestChecksumCalculationResolver profileName(String profileName) { + this.profileName = profileName; + return this; + } + + /** + * Configure the {@link RequestChecksumCalculation} that should be used if the mode is not specified anywhere else. + */ + public RequestChecksumCalculationResolver defaultChecksumCalculation(RequestChecksumCalculation defaultChecksumCalculation) { + this.defaultChecksumCalculation = defaultChecksumCalculation; + return this; + } + + /** + * Resolve which request checksum calculation setting should be used, based on the configured values. + */ + public RequestChecksumCalculation resolve() { + return OptionalUtils.firstPresent(fromSystemSettings(), + () -> fromProfileFile(profileFile, profileName)) + .orElseGet(this::fromDefaultChecksumCalculation); + } + + private Optional fromSystemSettings() { + return SdkSystemSetting.AWS_REQUEST_CHECKSUM_CALCULATION.getStringValue() + .flatMap(this::stringToEnum); + } + + private Optional fromProfileFile(Supplier profileFile, String profileName) { + return profileFile.get() + .profile(profileName) + .flatMap(p -> p.property(ProfileProperty.REQUEST_CHECKSUM_CALCULATION)) + .flatMap(this::stringToEnum); + } + + private RequestChecksumCalculation fromDefaultChecksumCalculation() { + return defaultChecksumCalculation != null ? defaultChecksumCalculation : SDK_DEFAULT_CHECKSUM_CALCULATION; + } + + private Optional stringToEnum(String value) { + return Optional.of(RequestChecksumCalculation.fromValue(value)); + } +} diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/checksums/ResponseChecksumValidation.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/checksums/ResponseChecksumValidation.java new file mode 100644 index 000000000000..d0dc1a878f31 --- /dev/null +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/checksums/ResponseChecksumValidation.java @@ -0,0 +1,57 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.core.checksums; + +import software.amazon.awssdk.annotations.SdkPublicApi; + +/** + * Enum class for response checksum validation setting. + */ +@SdkPublicApi +public enum ResponseChecksumValidation { + + /** + * Checksum will be validated for response if supported. Default setting. + */ + WHEN_SUPPORTED, + + /** + * Checksum will only be validated for response if required. + */ + WHEN_REQUIRED, + ; + + /** + * Returns the appropriate ResponseChecksumValidation value after parsing the parameter. + * @param s ResponseChecksumValidation in String format. + * @return ResponseChecksumValidation enum value. + * @throws IllegalArgumentException Unrecognized value for response checksum validation. + */ + public static ResponseChecksumValidation fromValue(String s) { + if (s == null) { + return null; + } + + for (ResponseChecksumValidation value : values()) { + if (value.name().equalsIgnoreCase(s)) { + return value; + } + } + + throw new IllegalArgumentException("Unrecognized value for response checksum validation: " + s + "\n Valid values are: " + + "when_supported and when_required"); + } +} diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/checksums/ResponseChecksumValidationResolver.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/checksums/ResponseChecksumValidationResolver.java new file mode 100644 index 000000000000..fac3494b9500 --- /dev/null +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/checksums/ResponseChecksumValidationResolver.java @@ -0,0 +1,99 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.core.checksums; + +import java.util.Optional; +import java.util.function.Supplier; +import software.amazon.awssdk.annotations.SdkProtectedApi; +import software.amazon.awssdk.core.SdkSystemSetting; +import software.amazon.awssdk.profiles.ProfileFile; +import software.amazon.awssdk.profiles.ProfileProperty; +import software.amazon.awssdk.utils.OptionalUtils; + +/** + * Allows customizing the variables used during determination of a {@link ResponseChecksumValidation}. + * Created via{@link #create()}. + */ +@SdkProtectedApi +public final class ResponseChecksumValidationResolver { + + private static final ResponseChecksumValidation SDK_DEFAULT_CHECKSUM_VALIDATION = ResponseChecksumValidation.WHEN_SUPPORTED; + + private Supplier profileFile; + private String profileName; + private ResponseChecksumValidation defaultChecksumValidation; + + private ResponseChecksumValidationResolver() { + } + + public static ResponseChecksumValidationResolver create() { + return new ResponseChecksumValidationResolver(); + } + + /** + * Configure the profile file that should be used when determining the {@link ResponseChecksumValidation}. The supplier is + * only consulted if a higher-priority determinant (e.g. environment variables) does not find the setting. + */ + public ResponseChecksumValidationResolver profileFile(Supplier profileFile) { + this.profileFile = profileFile; + return this; + } + + /** + * Configure the profile file name should be used when determining the {@link ResponseChecksumValidation}. + */ + public ResponseChecksumValidationResolver profileName(String profileName) { + this.profileName = profileName; + return this; + } + + /** + * Configure the {@link ResponseChecksumValidation} that should be used if the mode is not specified anywhere else. + */ + public ResponseChecksumValidationResolver defaultChecksumValidation(ResponseChecksumValidation defaultChecksumValidation) { + this.defaultChecksumValidation = defaultChecksumValidation; + return this; + } + + /** + * Resolve which response checksum validation setting should be used, based on the configured values. + */ + public ResponseChecksumValidation resolve() { + return OptionalUtils.firstPresent(fromSystemSettings(), + () -> fromProfileFile(profileFile, profileName)) + .orElseGet(this::fromDefaultChecksumValidation); + } + + private Optional fromSystemSettings() { + return SdkSystemSetting.AWS_RESPONSE_CHECKSUM_VALIDATION.getStringValue() + .flatMap(this::stringToEnum); + } + + private Optional fromProfileFile(Supplier profileFile, String profileName) { + return profileFile.get() + .profile(profileName) + .flatMap(p -> p.property(ProfileProperty.RESPONSE_CHECKSUM_VALIDATION)) + .flatMap(this::stringToEnum); + } + + private ResponseChecksumValidation fromDefaultChecksumValidation() { + return defaultChecksumValidation != null ? defaultChecksumValidation : SDK_DEFAULT_CHECKSUM_VALIDATION; + } + + private Optional stringToEnum(String value) { + return Optional.of(ResponseChecksumValidation.fromValue(value)); + } +} diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/config/SdkClientOption.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/config/SdkClientOption.java index fd6c6a30340e..58def071bc64 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/config/SdkClientOption.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/client/config/SdkClientOption.java @@ -28,6 +28,8 @@ import software.amazon.awssdk.core.CompressionConfiguration; import software.amazon.awssdk.core.SdkClient; import software.amazon.awssdk.core.ServiceConfiguration; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidation; import software.amazon.awssdk.core.interceptor.ExecutionAttributes; import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; import software.amazon.awssdk.core.internal.useragent.SdkClientUserAgentProperties; @@ -329,11 +331,23 @@ public final class SdkClientOption extends ClientOption { new SdkClientOption<>(CompressionConfiguration.class); /** - * An optional identification value to be appended to the user agent header. - * The value should be less than 50 characters in length and is null by default. + * The request checksum calculation setting. The default value is WHEN_SUPPORTED. + */ + public static final SdkClientOption REQUEST_CHECKSUM_CALCULATION = + new SdkClientOption<>(RequestChecksumCalculation.class); + + /** + * The response checksum validation setting. The default value is WHEN_SUPPORTED. + */ + public static final SdkClientOption RESPONSE_CHECKSUM_VALIDATION = + new SdkClientOption<>(ResponseChecksumValidation.class); + + /** + * An optional identification value to be appended to the user agent header. The value should be less than 50 characters in + * length and is null by default. *

- * Users can additionally supply the appId value through environment and JVM settings, and - * it will be resolved using the following order of precedence (highest first): + * Users can additionally supply the appId value through environment and JVM settings, and it will be resolved using the + * following order of precedence (highest first): *

    *
  1. This client option configuration
  2. *
  3. The {@code AWS_SDK_UA_APP_ID} environment variable
  4. diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/interceptor/SdkExecutionAttribute.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/interceptor/SdkExecutionAttribute.java index 83bfb111def8..7bfcd8807075 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/interceptor/SdkExecutionAttribute.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/interceptor/SdkExecutionAttribute.java @@ -15,10 +15,6 @@ package software.amazon.awssdk.core.interceptor; -import static software.amazon.awssdk.checksums.DefaultChecksumAlgorithm.CRC32; -import static software.amazon.awssdk.checksums.DefaultChecksumAlgorithm.CRC32C; -import static software.amazon.awssdk.checksums.DefaultChecksumAlgorithm.SHA1; -import static software.amazon.awssdk.checksums.DefaultChecksumAlgorithm.SHA256; import static software.amazon.awssdk.http.auth.aws.internal.signer.util.ChecksumUtil.checksumHeaderName; import java.net.URI; @@ -47,7 +43,6 @@ import software.amazon.awssdk.metrics.MetricCollector; import software.amazon.awssdk.profiles.ProfileFile; import software.amazon.awssdk.utils.CompletableFutureUtils; -import software.amazon.awssdk.utils.ImmutableMap; /** * Contains attributes attached to the execution. This information is available to {@link ExecutionInterceptor}s and @@ -153,31 +148,25 @@ public class SdkExecutionAttribute { .build(); /** - * The Algorithm used for checksum validation of a response. + * The algorithm used for checksum validation of a response. + * @deprecated use {@link #HTTP_CHECKSUM_VALIDATION_ALGORITHM_V2} instead */ + @Deprecated public static final ExecutionAttribute HTTP_CHECKSUM_VALIDATION_ALGORITHM = new ExecutionAttribute<>( "HttpChecksumValidationAlgorithm"); + /** + * The algorithm used for checksum validation of a response. + */ + public static final ExecutionAttribute HTTP_CHECKSUM_VALIDATION_ALGORITHM_V2 = new ExecutionAttribute<>( + "HttpChecksumValidationAlgorithmV2"); + /** * Provides the status of {@link ChecksumValidation} performed on the response. */ public static final ExecutionAttribute HTTP_RESPONSE_CHECKSUM_VALIDATION = new ExecutionAttribute<>( "HttpResponseChecksumValidation"); - private static final ImmutableMap ALGORITHM_MAP = ImmutableMap.of( - SHA256, Algorithm.SHA256, - SHA1, Algorithm.SHA1, - CRC32, Algorithm.CRC32, - CRC32C, Algorithm.CRC32C - ); - - private static final ImmutableMap CHECKSUM_ALGORITHM_MAP = ImmutableMap.of( - Algorithm.SHA256, SHA256, - Algorithm.SHA1, SHA1, - Algorithm.CRC32, CRC32, - Algorithm.CRC32C, CRC32C - ); - protected SdkExecutionAttribute() { } @@ -194,12 +183,13 @@ private static ChecksumSpecs signerChecksumReadMapping(Chec authScheme.authSchemeOption().signerProperty(AwsV4FamilyHttpSigner.CHECKSUM_ALGORITHM); return ChecksumSpecs.builder() - .algorithm(checksumAlgorithm != null ? ALGORITHM_MAP.get(checksumAlgorithm) : null) + .algorithmV2(checksumAlgorithm) .isRequestStreaming(checksumSpecs.isRequestStreaming()) .isRequestChecksumRequired(checksumSpecs.isRequestChecksumRequired()) .isValidationEnabled(checksumSpecs.isValidationEnabled()) .headerName(checksumAlgorithm != null ? checksumHeaderName(checksumAlgorithm) : null) - .responseValidationAlgorithms(checksumSpecs.responseValidationAlgorithms()) + .responseValidationAlgorithmsV2(checksumSpecs.responseValidationAlgorithmsV2()) + .requestAlgorithmHeader(checksumSpecs.requestAlgorithmHeader()) .build(); } @@ -209,7 +199,7 @@ private static ChecksumSpecs signerChecksumReadMapping(Chec private static SelectedAuthScheme signerChecksumWriteMapping(SelectedAuthScheme authScheme, ChecksumSpecs checksumSpecs) { ChecksumAlgorithm checksumAlgorithm = checksumSpecs == null ? null : - CHECKSUM_ALGORITHM_MAP.get(checksumSpecs.algorithm()); + checksumSpecs.algorithmV2(); if (authScheme == null) { // This is an unusual use-case. diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/interceptor/SdkInternalExecutionAttribute.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/interceptor/SdkInternalExecutionAttribute.java index cafc686556bc..08f890bd8333 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/interceptor/SdkInternalExecutionAttribute.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/interceptor/SdkInternalExecutionAttribute.java @@ -23,6 +23,8 @@ import software.amazon.awssdk.core.SdkProtocolMetadata; import software.amazon.awssdk.core.SelectedAuthScheme; import software.amazon.awssdk.core.checksums.ChecksumSpecs; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidation; import software.amazon.awssdk.core.interceptor.trait.HttpChecksum; import software.amazon.awssdk.core.interceptor.trait.HttpChecksumRequired; import software.amazon.awssdk.core.internal.interceptor.trait.RequestCompression; @@ -175,6 +177,18 @@ public final class SdkInternalExecutionAttribute extends SdkExecutionAttribute { public static final ExecutionAttribute SDK_CLIENT = new ExecutionAttribute<>("SdkClient"); + /** + * The request checksum calculation setting. + */ + public static final ExecutionAttribute REQUEST_CHECKSUM_CALCULATION = new ExecutionAttribute<>( + "RequestChecksumCalculation"); + + /** + * The response checksum validation setting. + */ + public static final ExecutionAttribute RESPONSE_CHECKSUM_VALIDATION = new ExecutionAttribute<>( + "ResponseChecksumValidation"); + /** * The backing attribute for RESOLVED_CHECKSUM_SPECS. * This holds the real ChecksumSpecs value, and is used to map to the ChecksumAlgorithm signer property diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/interceptor/trait/HttpChecksum.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/interceptor/trait/HttpChecksum.java index 355ac9859155..660a305120c0 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/interceptor/trait/HttpChecksum.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/interceptor/trait/HttpChecksum.java @@ -18,21 +18,25 @@ import java.util.Arrays; import java.util.List; import java.util.Objects; -import software.amazon.awssdk.annotations.SdkInternalApi; +import java.util.stream.Collectors; +import software.amazon.awssdk.annotations.SdkProtectedApi; +import software.amazon.awssdk.checksums.DefaultChecksumAlgorithm; +import software.amazon.awssdk.checksums.spi.ChecksumAlgorithm; -@SdkInternalApi +@SdkProtectedApi public class HttpChecksum { - private final boolean requestChecksumRequired; private final String requestAlgorithm; + private final String requestAlgorithmHeader; + private final String requestValidationMode; private final boolean isRequestStreaming; - private final List responseAlgorithms; + private final List responseAlgorithms; private HttpChecksum(Builder builder) { this.requestChecksumRequired = builder.requestChecksumRequired; @@ -40,9 +44,9 @@ private HttpChecksum(Builder builder) { this.requestValidationMode = builder.requestValidationMode; this.responseAlgorithms = builder.responseAlgorithms; this.isRequestStreaming = builder.isRequestStreaming; + this.requestAlgorithmHeader = builder.requestAlgorithmHeader; } - public boolean isRequestChecksumRequired() { return requestChecksumRequired; } @@ -51,7 +55,23 @@ public String requestAlgorithm() { return requestAlgorithm; } + public String requestAlgorithmHeader() { + return requestAlgorithmHeader; + } + + /** + * @deprecated use {@link #responseAlgorithmsV2()} instead + */ + @Deprecated public List responseAlgorithms() { + if (responseAlgorithms == null) { + return null; + } + + return responseAlgorithms.stream().map(ChecksumAlgorithm::algorithmId).collect(Collectors.toList()); + } + + public List responseAlgorithmsV2() { return responseAlgorithms; } @@ -76,10 +96,11 @@ public static final class Builder { private String requestValidationMode; - private List responseAlgorithms; + private List responseAlgorithms; private boolean isRequestStreaming; + private String requestAlgorithmHeader; public Builder requestChecksumRequired(boolean requestChecksumRequired) { this.requestChecksumRequired = requestChecksumRequired; @@ -91,23 +112,44 @@ public Builder requestAlgorithm(String requestAlgorithm) { return this; } + public Builder requestAlgorithmHeader(String requestAlgorithmHeader) { + this.requestAlgorithmHeader = requestAlgorithmHeader; + return this; + } + public Builder requestValidationMode(String requestValidationMode) { this.requestValidationMode = requestValidationMode; return this; } + /** + * @deprecated use {@link #responseAlgorithmsV2(ChecksumAlgorithm...)} instead + */ + @Deprecated public Builder responseAlgorithms(List responseAlgorithms) { - this.responseAlgorithms = responseAlgorithms; + this.responseAlgorithms = responseAlgorithms.stream() + .map(algo -> DefaultChecksumAlgorithm.fromValue(algo)) + .collect(Collectors.toList()); return this; } + /** + * @deprecated use {@link #responseAlgorithmsV2(ChecksumAlgorithm...)} instead + */ + @Deprecated public Builder responseAlgorithms(String... responseAlgorithms) { if (responseAlgorithms != null) { - this.responseAlgorithms = Arrays.asList(responseAlgorithms); + return responseAlgorithms(Arrays.asList(responseAlgorithms)); } return this; } + public Builder responseAlgorithmsV2(ChecksumAlgorithm... responseAlgorithms) { + if (responseAlgorithms != null) { + this.responseAlgorithms = Arrays.asList(responseAlgorithms); + } + return this; + } public Builder isRequestStreaming(boolean isRequestStreaming) { this.isRequestStreaming = isRequestStreaming; diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/ChecksumCalculatingAsyncRequestBody.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/ChecksumCalculatingAsyncRequestBody.java index 9d6b18afbfc5..f1f787733c74 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/ChecksumCalculatingAsyncRequestBody.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/ChecksumCalculatingAsyncRequestBody.java @@ -28,11 +28,13 @@ import org.reactivestreams.Subscriber; import org.reactivestreams.Subscription; import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.checksums.SdkChecksum; +import software.amazon.awssdk.checksums.spi.ChecksumAlgorithm; import software.amazon.awssdk.core.async.AsyncRequestBody; import software.amazon.awssdk.core.async.SdkPublisher; import software.amazon.awssdk.core.checksums.Algorithm; -import software.amazon.awssdk.core.checksums.SdkChecksum; import software.amazon.awssdk.core.exception.SdkException; +import software.amazon.awssdk.core.internal.util.HttpChecksumUtils; import software.amazon.awssdk.utils.BinaryUtils; import software.amazon.awssdk.utils.Validate; import software.amazon.awssdk.utils.async.DelegatingSubscriber; @@ -41,6 +43,8 @@ /** * Wrapper class to wrap an AsyncRequestBody. * This will read the data in chunk format and append Checksum as trailer at the end. + * TODO(sra-identity-and-auth): Checksum calculating logic for async client is still here and should be in + * "http-auth-aws", more specifically, AwsChunkedV4PayloadSigner#signAsync */ @SdkInternalApi public class ChecksumCalculatingAsyncRequestBody implements AsyncRequestBody { @@ -48,7 +52,7 @@ public class ChecksumCalculatingAsyncRequestBody implements AsyncRequestBody { private static final byte[] FINAL_BYTE = new byte[0]; private final AsyncRequestBody wrapped; private final SdkChecksum sdkChecksum; - private final Algorithm algorithm; + private final ChecksumAlgorithm algorithm; private final String trailerHeader; private final long totalBytes; @@ -61,8 +65,15 @@ private ChecksumCalculatingAsyncRequestBody(DefaultBuilder builder) { this.algorithm = builder.algorithm; this.sdkChecksum = builder.algorithm != null ? SdkChecksum.forAlgorithm(algorithm) : null; this.trailerHeader = builder.trailerHeader; - this.totalBytes = wrapped.contentLength() - .orElseThrow(() -> new UnsupportedOperationException("Content length must be supplied.")); + this.totalBytes = initTotalBytes(wrapped, builder.contentLengthHeader); + } + + static long initTotalBytes(AsyncRequestBody wrapped, Long contentLengthHeader) { + if (contentLengthHeader != null) { + return contentLengthHeader; + } + return wrapped.contentLength() + .orElseThrow(() -> new UnsupportedOperationException("Content length must be supplied.")); } /** @@ -88,7 +99,7 @@ public interface Builder extends SdkBuilder contentLength() { - if (wrapped.contentLength().isPresent() && algorithm != null) { - return Optional.of(calculateChunkLength(wrapped.contentLength().get()) + if (algorithm != null) { + Algorithm legacyAlgo = HttpChecksumUtils.toLegacyChecksumAlgorithm(algorithm); + return Optional.of(calculateChunkLength(totalBytes) + LAST_CHUNK_LEN - + calculateChecksumTrailerLength(algorithm, trailerHeader)); + + calculateChecksumTrailerLength(legacyAlgo, trailerHeader)); } - return wrapped.contentLength(); + return Optional.of(totalBytes); } @Override diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/ChecksumValidatingPublisher.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/ChecksumValidatingPublisher.java index 0a135115c4e9..a1c265b81f6b 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/ChecksumValidatingPublisher.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/ChecksumValidatingPublisher.java @@ -20,8 +20,8 @@ import org.reactivestreams.Subscriber; import org.reactivestreams.Subscription; import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.checksums.SdkChecksum; import software.amazon.awssdk.core.async.SdkPublisher; -import software.amazon.awssdk.core.checksums.SdkChecksum; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.utils.BinaryUtils; diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/ChunkBuffer.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/ChunkBuffer.java index d9fe0e0bdf14..23101302695a 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/ChunkBuffer.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/ChunkBuffer.java @@ -91,19 +91,38 @@ private boolean isCurrentBufferFull() { * Splits the input ByteBuffer to multiple chunks and add them to the iterable. */ private void splitRemainingInputByteBuffer(ByteBuffer inputByteBuffer, List byteBuffers) { + long numTransferredBytes = transferredBytes.get(); while (inputByteBuffer.hasRemaining()) { - ByteBuffer inputByteBufferCopy = inputByteBuffer.asReadOnlyBuffer(); - if (inputByteBuffer.remaining() < chunkSize) { + if (inputByteBuffer.remaining() < chunkSize || wouldExceedTotalByte(numTransferredBytes)) { + limitBufferToTotalBytes(inputByteBuffer, numTransferredBytes); currentBuffer.put(inputByteBuffer); break; } + ByteBuffer inputByteBufferCopy = inputByteBuffer.asReadOnlyBuffer(); + int newLimit = inputByteBufferCopy.position() + chunkSize; inputByteBufferCopy.limit(newLimit); inputByteBuffer.position(newLimit); byteBuffers.add(inputByteBufferCopy); - transferredBytes.addAndGet(chunkSize); + numTransferredBytes = transferredBytes.addAndGet(chunkSize); + } + } + + private void limitBufferToTotalBytes(ByteBuffer buff, long transferred) { + if (totalBytes == null) { + return; } + long remainingForTotalBytes = totalBytes - transferred; + int newLimit = (int) Math.min(buff.limit(), buff.position() + remainingForTotalBytes); + buff.limit(newLimit); + } + + private boolean wouldExceedTotalByte(long transferredBytes) { + if (totalBytes == null) { + return false; + } + return transferredBytes + chunkSize > totalBytes; } /** @@ -127,6 +146,7 @@ private boolean isLastChunk() { if (totalBytes == null) { return false; } + long remainingBytes = totalBytes - transferredBytes.get(); return remainingBytes != 0 && remainingBytes == currentBuffer.position(); } @@ -134,8 +154,14 @@ private boolean isLastChunk() { private void addCurrentBufferToIterable(List byteBuffers) { Optional bufferedChunk = getBufferedData(); if (bufferedChunk.isPresent()) { - byteBuffers.add(bufferedChunk.get()); - transferredBytes.addAndGet(bufferedChunk.get().remaining()); + ByteBuffer chunk = bufferedChunk.get(); + if (totalBytes != null) { + long remainingBytes = totalBytes - transferredBytes.get(); + int newLimit = Math.toIntExact(Math.min(chunk.capacity(), remainingBytes)); + chunk.limit(newLimit); + } + byteBuffers.add(chunk); + transferredBytes.addAndGet(chunk.remaining()); currentBuffer.clear(); } } diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/AmazonAsyncHttpClient.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/AmazonAsyncHttpClient.java index f81e6f003f54..8dd6db8acf1c 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/AmazonAsyncHttpClient.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/AmazonAsyncHttpClient.java @@ -37,7 +37,7 @@ import software.amazon.awssdk.core.internal.http.pipeline.stages.AsyncApiCallTimeoutTrackingStage; import software.amazon.awssdk.core.internal.http.pipeline.stages.AsyncBeforeTransmissionExecutionInterceptorsStage; import software.amazon.awssdk.core.internal.http.pipeline.stages.AsyncExecutionFailureExceptionReportingStage; -import software.amazon.awssdk.core.internal.http.pipeline.stages.AsyncRetryableStage2; +import software.amazon.awssdk.core.internal.http.pipeline.stages.AsyncRetryableStage; import software.amazon.awssdk.core.internal.http.pipeline.stages.AsyncSigningStage; import software.amazon.awssdk.core.internal.http.pipeline.stages.CompressRequestStage; import software.amazon.awssdk.core.internal.http.pipeline.stages.HttpChecksumStage; @@ -205,8 +205,8 @@ public CompletableFuture execute( .then(AsyncBeforeTransmissionExecutionInterceptorsStage::new) .then(d -> new MakeAsyncHttpRequestStage<>(responseHandler, d)) .wrappedWith(AsyncApiCallAttemptMetricCollectionStage::new) - .wrappedWith((deps, wrapped) -> new AsyncRetryableStage2<>(responseHandler, deps, - wrapped)) + .wrappedWith((deps, wrapped) -> new AsyncRetryableStage<>(responseHandler, deps, + wrapped)) .then(async(() -> new UnwrapResponseContainer<>())) .then(async(() -> new AfterExecutionInterceptorsStage<>())) .wrappedWith(AsyncExecutionFailureExceptionReportingStage::new) diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/AmazonSyncHttpClient.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/AmazonSyncHttpClient.java index f9d954962864..21fb5cbe1306 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/AmazonSyncHttpClient.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/AmazonSyncHttpClient.java @@ -46,7 +46,7 @@ import software.amazon.awssdk.core.internal.http.pipeline.stages.MergeCustomHeadersStage; import software.amazon.awssdk.core.internal.http.pipeline.stages.MergeCustomQueryParamsStage; import software.amazon.awssdk.core.internal.http.pipeline.stages.QueryParametersToBodyStage; -import software.amazon.awssdk.core.internal.http.pipeline.stages.RetryableStage2; +import software.amazon.awssdk.core.internal.http.pipeline.stages.RetryableStage; import software.amazon.awssdk.core.internal.http.pipeline.stages.SigningStage; import software.amazon.awssdk.core.internal.http.pipeline.stages.TimeoutExceptionHandlingStage; import software.amazon.awssdk.core.internal.http.pipeline.stages.UnwrapResponseContainer; @@ -199,7 +199,7 @@ public OutputT execute(HttpResponseHandler> response .wrappedWith(ApiCallAttemptTimeoutTrackingStage::new) .wrappedWith(TimeoutExceptionHandlingStage::new) .wrappedWith((deps, wrapped) -> new ApiCallAttemptMetricCollectionStage<>(wrapped)) - .wrappedWith(RetryableStage2::new)::build) + .wrappedWith(RetryableStage::new)::build) .wrappedWith(StreamManagingStage::new) .wrappedWith(ApiCallTimeoutTrackingStage::new)::build) .wrappedWith((deps, wrapped) -> new ApiCallMetricCollectionStage<>(wrapped)) diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/AsyncRetryableStage.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/AsyncRetryableStage.java index 154cf93b72f4..d92c264a1b39 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/AsyncRetryableStage.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/AsyncRetryableStage.java @@ -19,22 +19,19 @@ import java.io.IOException; import java.time.Duration; -import java.util.OptionalDouble; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ScheduledExecutorService; import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.annotations.SdkTestInternalApi; import software.amazon.awssdk.core.Response; import software.amazon.awssdk.core.async.AsyncRequestBody; import software.amazon.awssdk.core.client.config.SdkClientOption; -import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.core.exception.SdkException; import software.amazon.awssdk.core.internal.http.HttpClientDependencies; import software.amazon.awssdk.core.internal.http.RequestExecutionContext; import software.amazon.awssdk.core.internal.http.TransformingAsyncResponseHandler; import software.amazon.awssdk.core.internal.http.pipeline.RequestPipeline; import software.amazon.awssdk.core.internal.http.pipeline.stages.utils.RetryableStageHelper; -import software.amazon.awssdk.core.internal.retry.RateLimitingTokenBucket; import software.amazon.awssdk.http.SdkHttpFullRequest; import software.amazon.awssdk.utils.CompletableFutureUtils; @@ -49,7 +46,6 @@ public final class AsyncRetryableStage implements RequestPipeline>> requestPipeline; private final ScheduledExecutorService scheduledExecutor; private final HttpClientDependencies dependencies; - private final RateLimitingTokenBucket rateLimitingTokenBucket; public AsyncRetryableStage(TransformingAsyncResponseHandler> responseHandler, HttpClientDependencies dependencies, @@ -57,29 +53,16 @@ public AsyncRetryableStage(TransformingAsyncResponseHandler> r this.responseHandler = responseHandler; this.dependencies = dependencies; this.scheduledExecutor = dependencies.clientConfiguration().option(SdkClientOption.SCHEDULED_EXECUTOR_SERVICE); - this.rateLimitingTokenBucket = new RateLimitingTokenBucket(); this.requestPipeline = requestPipeline; } - @SdkTestInternalApi - public AsyncRetryableStage(TransformingAsyncResponseHandler> responseHandler, - HttpClientDependencies dependencies, - RequestPipeline>> requestPipeline, - RateLimitingTokenBucket rateLimitingTokenBucket) { - this.responseHandler = responseHandler; - this.dependencies = dependencies; - this.scheduledExecutor = dependencies.clientConfiguration().option(SdkClientOption.SCHEDULED_EXECUTOR_SERVICE); - this.requestPipeline = requestPipeline; - this.rateLimitingTokenBucket = rateLimitingTokenBucket; - } - @Override public CompletableFuture> execute(SdkHttpFullRequest request, RequestExecutionContext context) throws Exception { return new RetryingExecutor(request, context).execute(); } - private class RetryingExecutor { + private final class RetryingExecutor { private final AsyncRequestBody originalRequestBody; private final RequestExecutionContext context; private final RetryableStageHelper retryableStageHelper; @@ -87,59 +70,30 @@ private class RetryingExecutor { private RetryingExecutor(SdkHttpFullRequest request, RequestExecutionContext context) { this.originalRequestBody = context.requestProvider(); this.context = context; - this.retryableStageHelper = new RetryableStageHelper(request, context, rateLimitingTokenBucket, dependencies); + this.retryableStageHelper = new RetryableStageHelper(request, context, dependencies); } - public CompletableFuture> execute() throws Exception { + public CompletableFuture> execute() { CompletableFuture> future = new CompletableFuture<>(); - maybeAttemptExecute(future); + attemptFirstExecute(future); return future; } - public void maybeAttemptExecute(CompletableFuture> future) { - retryableStageHelper.startingAttempt(); - - if (!retryableStageHelper.retryPolicyAllowsRetry()) { - future.completeExceptionally(retryableStageHelper.retryPolicyDisallowedRetryException()); - return; - } - - if (retryableStageHelper.getAttemptNumber() > 1) { - // We failed the last attempt, but will retry. The response handler wants to know when that happens. - responseHandler.onError(retryableStageHelper.getLastException()); - - // Reset the request provider to the original one before retries, in case it was modified downstream. - context.requestProvider(originalRequestBody); - } - - Duration backoffDelay = retryableStageHelper.getBackoffDelay(); - - OptionalDouble tokenAcquireTimeSeconds = retryableStageHelper.getSendTokenNonBlocking(); - if (!tokenAcquireTimeSeconds.isPresent()) { - String errorMessage = "Unable to acquire a send token immediately without waiting. This indicates that ADAPTIVE " - + "retry mode is enabled, fast fail rate limiting is enabled, and that rate limiting is " - + "engaged because of prior throttled requests. The request will not be executed."; - future.completeExceptionally(SdkClientException.create(errorMessage)); - return; - } - long tokenAcquireTimeMillis = (long) (tokenAcquireTimeSeconds.getAsDouble() * 1000); - - if (!backoffDelay.isZero()) { + public void attemptFirstExecute(CompletableFuture> future) { + Duration backoffDelay = retryableStageHelper.acquireInitialToken(); + if (backoffDelay.isZero()) { + attemptExecute(future); + } else { retryableStageHelper.logBackingOff(backoffDelay); - } - - long totalDelayMillis = backoffDelay.toMillis() + tokenAcquireTimeMillis; - - if (totalDelayMillis > 0) { + long totalDelayMillis = backoffDelay.toMillis(); scheduledExecutor.schedule(() -> attemptExecute(future), totalDelayMillis, MILLISECONDS); - } else { - attemptExecute(future); } } private void attemptExecute(CompletableFuture> future) { CompletableFuture> responseFuture; try { + retryableStageHelper.startingAttempt(); retryableStageHelper.logSendingRequest(); responseFuture = requestPipeline.execute(retryableStageHelper.requestToSend(), context); @@ -164,23 +118,37 @@ private void attemptExecute(CompletableFuture> future) { } retryableStageHelper.setLastResponse(response.httpResponse()); - if (!response.isSuccess()) { retryableStageHelper.adjustClockIfClockSkew(response); maybeRetryExecute(future, response.exception()); return; } - retryableStageHelper.updateClientSendingRateForSuccessResponse(); - - retryableStageHelper.attemptSucceeded(); + retryableStageHelper.recordAttemptSucceeded(); future.complete(response); }); } + public void maybeAttemptExecute(CompletableFuture> future) { + Optional delay = retryableStageHelper.tryRefreshToken(Duration.ZERO); + if (!delay.isPresent()) { + future.completeExceptionally(retryableStageHelper.retryPolicyDisallowedRetryException()); + return; + } + // We failed the last attempt, but will retry. The response handler wants to know when that happens. + responseHandler.onError(retryableStageHelper.getLastException()); + + // Reset the request provider to the original one before retries, in case it was modified downstream. + context.requestProvider(originalRequestBody); + + Duration backoffDelay = delay.get(); + retryableStageHelper.logBackingOff(backoffDelay); + long totalDelayMillis = backoffDelay.toMillis(); + scheduledExecutor.schedule(() -> attemptExecute(future), totalDelayMillis, MILLISECONDS); + } + private void maybeRetryExecute(CompletableFuture> future, Exception exception) { retryableStageHelper.setLastException(exception); - retryableStageHelper.updateClientSendingRateForErrorResponse(); maybeAttemptExecute(future); } } diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/AsyncRetryableStage2.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/AsyncRetryableStage2.java deleted file mode 100644 index ff598d27832e..000000000000 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/AsyncRetryableStage2.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -package software.amazon.awssdk.core.internal.http.pipeline.stages; - -import static java.util.concurrent.TimeUnit.MILLISECONDS; - -import java.io.IOException; -import java.time.Duration; -import java.util.Optional; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ScheduledExecutorService; -import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.core.Response; -import software.amazon.awssdk.core.async.AsyncRequestBody; -import software.amazon.awssdk.core.client.config.SdkClientOption; -import software.amazon.awssdk.core.exception.SdkException; -import software.amazon.awssdk.core.internal.http.HttpClientDependencies; -import software.amazon.awssdk.core.internal.http.RequestExecutionContext; -import software.amazon.awssdk.core.internal.http.TransformingAsyncResponseHandler; -import software.amazon.awssdk.core.internal.http.pipeline.RequestPipeline; -import software.amazon.awssdk.core.internal.http.pipeline.stages.utils.RetryableStageHelper2; -import software.amazon.awssdk.http.SdkHttpFullRequest; -import software.amazon.awssdk.utils.CompletableFutureUtils; - -/** - * Wrapper around the pipeline for a single request to provide retry, clockskew and request throttling functionality. - */ -@SdkInternalApi -public final class AsyncRetryableStage2 implements RequestPipeline>> { - - private final TransformingAsyncResponseHandler> responseHandler; - private final RequestPipeline>> requestPipeline; - private final ScheduledExecutorService scheduledExecutor; - private final HttpClientDependencies dependencies; - - public AsyncRetryableStage2(TransformingAsyncResponseHandler> responseHandler, - HttpClientDependencies dependencies, - RequestPipeline>> requestPipeline) { - this.responseHandler = responseHandler; - this.dependencies = dependencies; - this.scheduledExecutor = dependencies.clientConfiguration().option(SdkClientOption.SCHEDULED_EXECUTOR_SERVICE); - this.requestPipeline = requestPipeline; - } - - @Override - public CompletableFuture> execute(SdkHttpFullRequest request, - RequestExecutionContext context) throws Exception { - return new RetryingExecutor(request, context).execute(); - } - - private final class RetryingExecutor { - private final AsyncRequestBody originalRequestBody; - private final RequestExecutionContext context; - private final RetryableStageHelper2 retryableStageHelper; - - private RetryingExecutor(SdkHttpFullRequest request, RequestExecutionContext context) { - this.originalRequestBody = context.requestProvider(); - this.context = context; - this.retryableStageHelper = new RetryableStageHelper2(request, context, dependencies); - } - - public CompletableFuture> execute() { - CompletableFuture> future = new CompletableFuture<>(); - attemptFirstExecute(future); - return future; - } - - public void attemptFirstExecute(CompletableFuture> future) { - Duration backoffDelay = retryableStageHelper.acquireInitialToken(); - if (backoffDelay.isZero()) { - attemptExecute(future); - } else { - retryableStageHelper.logBackingOff(backoffDelay); - long totalDelayMillis = backoffDelay.toMillis(); - scheduledExecutor.schedule(() -> attemptExecute(future), totalDelayMillis, MILLISECONDS); - } - } - - private void attemptExecute(CompletableFuture> future) { - CompletableFuture> responseFuture; - try { - retryableStageHelper.startingAttempt(); - retryableStageHelper.logSendingRequest(); - responseFuture = requestPipeline.execute(retryableStageHelper.requestToSend(), context); - - // If the result future fails, go ahead and fail the response future. - CompletableFutureUtils.forwardExceptionTo(future, responseFuture); - } catch (SdkException | IOException e) { - maybeRetryExecute(future, e); - return; - } catch (Throwable e) { - future.completeExceptionally(e); - return; - } - - responseFuture.whenComplete((response, exception) -> { - if (exception != null) { - if (exception instanceof Exception) { - maybeRetryExecute(future, (Exception) exception); - } else { - future.completeExceptionally(exception); - } - return; - } - - retryableStageHelper.setLastResponse(response.httpResponse()); - if (!response.isSuccess()) { - retryableStageHelper.adjustClockIfClockSkew(response); - maybeRetryExecute(future, response.exception()); - return; - } - - retryableStageHelper.recordAttemptSucceeded(); - future.complete(response); - }); - } - - public void maybeAttemptExecute(CompletableFuture> future) { - Optional delay = retryableStageHelper.tryRefreshToken(Duration.ZERO); - if (!delay.isPresent()) { - future.completeExceptionally(retryableStageHelper.retryPolicyDisallowedRetryException()); - return; - } - // We failed the last attempt, but will retry. The response handler wants to know when that happens. - responseHandler.onError(retryableStageHelper.getLastException()); - - // Reset the request provider to the original one before retries, in case it was modified downstream. - context.requestProvider(originalRequestBody); - - Duration backoffDelay = delay.get(); - retryableStageHelper.logBackingOff(backoffDelay); - long totalDelayMillis = backoffDelay.toMillis(); - scheduledExecutor.schedule(() -> attemptExecute(future), totalDelayMillis, MILLISECONDS); - } - - private void maybeRetryExecute(CompletableFuture> future, Exception exception) { - retryableStageHelper.setLastException(exception); - maybeAttemptExecute(future); - } - } -} diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/HttpChecksumStage.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/HttpChecksumStage.java index ed57ed8ab18f..d7bb3c699fb5 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/HttpChecksumStage.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/HttpChecksumStage.java @@ -18,22 +18,30 @@ import static software.amazon.awssdk.core.HttpChecksumConstant.AWS_CHUNKED_HEADER; import static software.amazon.awssdk.core.HttpChecksumConstant.CONTENT_SHA_256_FOR_UNSIGNED_TRAILER; import static software.amazon.awssdk.core.HttpChecksumConstant.DEFAULT_ASYNC_CHUNK_SIZE; +import static software.amazon.awssdk.core.HttpChecksumConstant.HEADER_FOR_TRAILER_REFERENCE; import static software.amazon.awssdk.core.HttpChecksumConstant.SIGNING_METHOD; +import static software.amazon.awssdk.core.interceptor.SdkExecutionAttribute.RESOLVED_CHECKSUM_SPECS; import static software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute.AUTH_SCHEMES; -import static software.amazon.awssdk.core.internal.io.AwsChunkedEncodingInputStream.DEFAULT_CHUNK_SIZE; +import static software.amazon.awssdk.core.internal.io.AwsChunkedInputStream.DEFAULT_CHUNK_SIZE; import static software.amazon.awssdk.core.internal.util.ChunkContentUtils.calculateChecksumTrailerLength; import static software.amazon.awssdk.core.internal.util.ChunkContentUtils.calculateStreamContentLength; import static software.amazon.awssdk.core.internal.util.HttpChecksumResolver.getResolvedChecksumSpecs; +import static software.amazon.awssdk.core.internal.util.HttpChecksumUtils.isHttpChecksumCalculationNeeded; +import static software.amazon.awssdk.core.internal.util.HttpChecksumUtils.isStreamingUnsignedPayload; import static software.amazon.awssdk.http.Header.CONTENT_LENGTH; import java.io.IOException; import java.io.InputStream; import java.io.UncheckedIOException; +import java.util.Optional; import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.checksums.DefaultChecksumAlgorithm; +import software.amazon.awssdk.checksums.spi.ChecksumAlgorithm; import software.amazon.awssdk.core.ClientType; -import software.amazon.awssdk.core.HttpChecksumConstant; +import software.amazon.awssdk.core.async.AsyncRequestBody; +import software.amazon.awssdk.core.checksums.Algorithm; import software.amazon.awssdk.core.checksums.ChecksumSpecs; -import software.amazon.awssdk.core.checksums.SdkChecksum; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; import software.amazon.awssdk.core.interceptor.InterceptorContext; import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute; import software.amazon.awssdk.core.internal.async.ChecksumCalculatingAsyncRequestBody; @@ -44,6 +52,8 @@ import software.amazon.awssdk.http.ContentStreamProvider; import software.amazon.awssdk.http.Header; import software.amazon.awssdk.http.SdkHttpFullRequest; +import software.amazon.awssdk.http.SdkHttpRequest; +import software.amazon.awssdk.http.auth.aws.internal.signer.util.ChecksumUtil; import software.amazon.awssdk.utils.BinaryUtils; import software.amazon.awssdk.utils.IoUtils; import software.amazon.awssdk.utils.Md5Utils; @@ -53,6 +63,7 @@ */ @SdkInternalApi public class HttpChecksumStage implements MutableRequestToRequestPipeline { + private static final ChecksumAlgorithm DEFAULT_ALGORITHM = DefaultChecksumAlgorithm.CRC32; private final ClientType clientType; @@ -63,25 +74,61 @@ public HttpChecksumStage(ClientType clientType) { @Override public SdkHttpFullRequest.Builder execute(SdkHttpFullRequest.Builder request, RequestExecutionContext context) throws Exception { + + if (sraSigningEnabled(context)) { + return sraChecksum(request, context); + } + + return legacyChecksum(request, context); + } + + private SdkHttpFullRequest.Builder legacyChecksum(SdkHttpFullRequest.Builder request, RequestExecutionContext context) { + ChecksumSpecs resolvedChecksumSpecs = getResolvedChecksumSpecs(context.executionAttributes()); + if (md5ChecksumRequired(request, context)) { addMd5ChecksumInHeader(request); return request; } - ChecksumSpecs resolvedChecksumSpecs = getResolvedChecksumSpecs(context.executionAttributes()); - if (flexibleChecksumInTrailerRequired(context, resolvedChecksumSpecs)) { addFlexibleChecksumInTrailer(request, context, resolvedChecksumSpecs); return request; } - // If SRA is enabled, skip flexible checksum in header, since it is handled by SRA signer - if (sraSigningEnabled(context)) { + if (flexibleChecksumInHeaderRequired(context, resolvedChecksumSpecs)) { + addFlexibleChecksumInHeader(request, context, resolvedChecksumSpecs); return request; } - if (flexibleChecksumInHeaderRequired(context, resolvedChecksumSpecs)) { - addFlexibleChecksumInHeader(request, context, resolvedChecksumSpecs); + return request; + } + + private SdkHttpFullRequest.Builder sraChecksum(SdkHttpFullRequest.Builder request, RequestExecutionContext context) { + ExecutionAttributes executionAttributes = context.executionAttributes(); + if (!isHttpChecksumCalculationNeeded(request, executionAttributes)) { + return request; + } + + ChecksumSpecs resolvedChecksumSpecs = executionAttributes.getAttribute(RESOLVED_CHECKSUM_SPECS); + + if (resolvedChecksumSpecs == null || resolvedChecksumSpecs.algorithmV2() == null) { + resolvedChecksumSpecs = checksumSpecsWithDefaultAlgorithm(resolvedChecksumSpecs); + if (resolvedChecksumSpecs.requestAlgorithmHeader() != null) { + request.putHeader(resolvedChecksumSpecs.requestAlgorithmHeader(), DEFAULT_ALGORITHM.algorithmId()); + } + } + executionAttributes.putAttribute(RESOLVED_CHECKSUM_SPECS, resolvedChecksumSpecs); + + SdkHttpRequest httpRequest = context.executionContext().interceptorContext().httpRequest(); + + // TODO(sra-identity-and-auth): payload checksum calculation (trailer) for sync is done in AwsChunkedV4PayloadSigner, + // but async is still in this class. We should first add chunked encoding support for async to + // AwsChunkedV4PayloadSigner + // and remove the logic here. Details in https://github.com/aws/aws-sdk-java-v2/pull/4568 + if (clientType == ClientType.ASYNC && + isStreamingUnsignedPayload(httpRequest, executionAttributes, resolvedChecksumSpecs, + resolvedChecksumSpecs.isRequestStreaming())) { + addFlexibleChecksumInTrailer(request, context, resolvedChecksumSpecs); return request; } @@ -133,19 +180,16 @@ private void addMd5ChecksumInHeader(SdkHttpFullRequest.Builder request) { } } - private boolean flexibleChecksumInTrailerRequired(RequestExecutionContext context, ChecksumSpecs checksumSpecs) { + private static ChecksumSpecs checksumSpecsWithDefaultAlgorithm(ChecksumSpecs resolvedChecksumSpecs) { + return (resolvedChecksumSpecs == null ? ChecksumSpecs.builder() : resolvedChecksumSpecs.toBuilder()) + .algorithmV2(DEFAULT_ALGORITHM) + .headerName(ChecksumUtil.checksumHeaderName(DEFAULT_ALGORITHM)) + .build(); + } - // If SRA is enabled and it's sync client, skip flexible checksum trailer, since it is handled in SRA signer - if (sraSigningEnabled(context) && clientType == ClientType.SYNC) { - return false; - } + private boolean flexibleChecksumInTrailerRequired(RequestExecutionContext context, ChecksumSpecs checksumSpecs) { - boolean hasRequestBody = true; - if (clientType == ClientType.SYNC) { - hasRequestBody = context.executionContext().interceptorContext().requestBody().isPresent(); - } else if (clientType == ClientType.ASYNC) { - hasRequestBody = context.executionContext().interceptorContext().asyncRequestBody().isPresent(); - } + boolean hasRequestBody = hasRequestBody(context); boolean isContentStreaming = context.executionContext().interceptorContext().requestBody() .map(requestBody -> requestBody.contentStreamProvider() != null).orElse(false); @@ -158,8 +202,19 @@ private boolean flexibleChecksumInTrailerRequired(RequestExecutionContext contex clientType, checksumSpecs, hasRequestBody, isContentStreaming); } + private boolean hasRequestBody(RequestExecutionContext context) { + switch (clientType) { + case ASYNC: + return context.executionContext().interceptorContext().asyncRequestBody().isPresent(); + case SYNC: + return context.executionContext().interceptorContext().requestBody().isPresent(); + default: throw new UnsupportedOperationException("Unsupported client type: " + clientType); + } + } + private static boolean sraSigningEnabled(RequestExecutionContext context) { - return context.executionAttributes().getAttribute(AUTH_SCHEMES) != null; + return context.executionAttributes().getAttribute(AUTH_SCHEMES) != null + && context.signer() == null; } /** @@ -185,20 +240,28 @@ private void addFlexibleChecksumInTrailer(SdkHttpFullRequest.Builder request, Re chunkSize = DEFAULT_CHUNK_SIZE; } else if (clientType == ClientType.ASYNC) { if (context.requestProvider() != null) { - context.requestProvider(ChecksumCalculatingAsyncRequestBody.builder() - .asyncRequestBody(context.requestProvider()) - .algorithm(checksumSpecs.algorithm()) - .trailerHeader(checksumSpecs.headerName()).build()); - originalContentLength = - context.executionContext().interceptorContext().asyncRequestBody().get().contentLength().orElse(0L); + ChecksumCalculatingAsyncRequestBody.Builder checksumBodyBuilder = + ChecksumCalculatingAsyncRequestBody.builder() + .asyncRequestBody(context.requestProvider()) + .algorithm(checksumSpecs.algorithmV2()) + .trailerHeader(checksumSpecs.headerName()); + Optional maybeContentLengthHeader = request.firstMatchingHeader("Content-Length") + .map(Long::parseLong); + maybeContentLengthHeader.ifPresent(checksumBodyBuilder::contentLengthHeader); + context.requestProvider(checksumBodyBuilder.build()); + originalContentLength = maybeContentLengthHeader + .orElseGet(() -> context.executionContext().interceptorContext().asyncRequestBody() + .flatMap(AsyncRequestBody::contentLength) + .orElse(0L)); chunkSize = DEFAULT_ASYNC_CHUNK_SIZE; } } - long checksumContentLength = calculateChecksumTrailerLength(checksumSpecs.algorithm(), checksumSpecs.headerName()); + Algorithm legacyAlgo = checksumSpecs.algorithm(); + long checksumContentLength = calculateChecksumTrailerLength(legacyAlgo, checksumSpecs.headerName()); long contentLen = checksumContentLength + calculateStreamContentLength(originalContentLength, chunkSize); - request.putHeader(HttpChecksumConstant.HEADER_FOR_TRAILER_REFERENCE, checksumSpecs.headerName()) + request.putHeader(HEADER_FOR_TRAILER_REFERENCE, checksumSpecs.headerName()) .appendHeader("Content-encoding", AWS_CHUNKED_HEADER) .putHeader("x-amz-content-sha256", CONTENT_SHA_256_FOR_UNSIGNED_TRAILER) .putHeader("x-amz-decoded-content-length", Long.toString(originalContentLength)) @@ -246,9 +309,10 @@ private boolean flexibleChecksumInHeaderRequired(RequestExecutionContext context private void addFlexibleChecksumInHeader(SdkHttpFullRequest.Builder request, RequestExecutionContext context, ChecksumSpecs checksumSpecs) { try { + Algorithm legacyAlgorithm = checksumSpecs.algorithm(); String payloadChecksum = BinaryUtils.toBase64(HttpChecksumUtils.computeChecksum( context.executionContext().interceptorContext().requestBody().get().contentStreamProvider().newStream(), - checksumSpecs.algorithm())); + legacyAlgorithm)); request.putHeader(checksumSpecs.headerName(), payloadChecksum); } catch (IOException e) { throw new UncheckedIOException(e); @@ -260,12 +324,13 @@ static final class ChecksumCalculatingStreamProvider implements ContentStreamPro private final String checksumHeaderForTrailer; private final ChecksumSpecs checksumSpecs; private InputStream currentStream; - private SdkChecksum sdkChecksum; + private software.amazon.awssdk.core.checksums.SdkChecksum sdkChecksum; ChecksumCalculatingStreamProvider(ContentStreamProvider underlyingInputStreamProvider, ChecksumSpecs checksumSpecs) { this.underlyingInputStreamProvider = underlyingInputStreamProvider; - this.sdkChecksum = SdkChecksum.forAlgorithm(checksumSpecs.algorithm()); + this.sdkChecksum = software.amazon.awssdk.core.checksums.SdkChecksum.forAlgorithm( + checksumSpecs.algorithm()); this.checksumHeaderForTrailer = checksumSpecs.headerName(); this.checksumSpecs = checksumSpecs; } @@ -282,7 +347,8 @@ public InputStream newStream() { } private void closeCurrentStream() { - sdkChecksum = SdkChecksum.forAlgorithm(checksumSpecs.algorithm()); + sdkChecksum = software.amazon.awssdk.core.checksums.SdkChecksum.forAlgorithm( + checksumSpecs.algorithm()); if (currentStream != null) { IoUtils.closeQuietly(currentStream, null); currentStream = null; diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/RetryableStage.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/RetryableStage.java index f432855ecf88..a545cb4b088e 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/RetryableStage.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/RetryableStage.java @@ -17,9 +17,9 @@ import java.io.IOException; import java.time.Duration; +import java.util.Optional; import java.util.concurrent.TimeUnit; import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.annotations.SdkTestInternalApi; import software.amazon.awssdk.core.Response; import software.amazon.awssdk.core.exception.SdkException; import software.amazon.awssdk.core.internal.http.HttpClientDependencies; @@ -27,77 +27,119 @@ import software.amazon.awssdk.core.internal.http.pipeline.RequestPipeline; import software.amazon.awssdk.core.internal.http.pipeline.RequestToResponsePipeline; import software.amazon.awssdk.core.internal.http.pipeline.stages.utils.RetryableStageHelper; -import software.amazon.awssdk.core.internal.retry.RateLimitingTokenBucket; import software.amazon.awssdk.http.SdkHttpFullRequest; +import software.amazon.awssdk.http.SdkHttpFullResponse; /** * Wrapper around the pipeline for a single request to provide retry, clock-skew and request throttling functionality. */ @SdkInternalApi public final class RetryableStage implements RequestToResponsePipeline { + private static final String RETRY_AFTER_HEADER = "Retry-After"; private final RequestPipeline> requestPipeline; private final HttpClientDependencies dependencies; - private final RateLimitingTokenBucket rateLimitingTokenBucket; public RetryableStage(HttpClientDependencies dependencies, RequestPipeline> requestPipeline) { this.dependencies = dependencies; this.requestPipeline = requestPipeline; - this.rateLimitingTokenBucket = null; - } - - @SdkTestInternalApi - public RetryableStage(HttpClientDependencies dependencies, - RequestPipeline> requestPipeline, - RateLimitingTokenBucket rateLimitingTokenBucket) { - this.dependencies = dependencies; - this.requestPipeline = requestPipeline; - this.rateLimitingTokenBucket = rateLimitingTokenBucket; } @Override public Response execute(SdkHttpFullRequest request, RequestExecutionContext context) throws Exception { - RetryableStageHelper retryableStageHelper = new RetryableStageHelper(request, context, rateLimitingTokenBucket, - dependencies); - + RetryableStageHelper retryableStageHelper = new RetryableStageHelper(request, context, dependencies); + Duration initialDelay = retryableStageHelper.acquireInitialToken(); + TimeUnit.MILLISECONDS.sleep(initialDelay.toMillis()); while (true) { - retryableStageHelper.startingAttempt(); - - if (!retryableStageHelper.retryPolicyAllowsRetry()) { - throw retryableStageHelper.retryPolicyDisallowedRetryException(); + try { + retryableStageHelper.startingAttempt(); + Response response = executeRequest(retryableStageHelper, context); + retryableStageHelper.recordAttemptSucceeded(); + return response; + } catch (SdkExceptionWithRetryAfterHint | SdkException | IOException e) { + Throwable throwable = e; + if (e instanceof SdkExceptionWithRetryAfterHint) { + SdkExceptionWithRetryAfterHint wrapper = (SdkExceptionWithRetryAfterHint) e; + throwable = wrapper.cause(); + } + retryableStageHelper.setLastException(throwable); + Duration suggestedDelay = suggestedDelay(e); + Optional backoffDelay = retryableStageHelper.tryRefreshToken(suggestedDelay); + if (backoffDelay.isPresent()) { + Duration delay = backoffDelay.get(); + retryableStageHelper.logBackingOff(delay); + TimeUnit.MILLISECONDS.sleep(delay.toMillis()); + } else { + throw retryableStageHelper.retryPolicyDisallowedRetryException(); + } } + } + } - retryableStageHelper.getSendToken(); + private Duration suggestedDelay(Exception e) { + if (e instanceof SdkExceptionWithRetryAfterHint) { + SdkExceptionWithRetryAfterHint except = (SdkExceptionWithRetryAfterHint) e; + return Duration.ofSeconds(except.retryAfter()); + } + return Duration.ZERO; + } - Duration backoffDelay = retryableStageHelper.getBackoffDelay(); - if (!backoffDelay.isZero()) { - retryableStageHelper.logBackingOff(backoffDelay); - TimeUnit.MILLISECONDS.sleep(backoffDelay.toMillis()); - } + /** + * Executes the requests and returns the result. If the response is not successful throws the wrapped exception. + */ + private Response executeRequest(RetryableStageHelper retryableStageHelper, + RequestExecutionContext context) throws Exception { + retryableStageHelper.logSendingRequest(); + Response response = requestPipeline.execute(retryableStageHelper.requestToSend(), context); + retryableStageHelper.setLastResponse(response.httpResponse()); + if (!response.isSuccess()) { + retryableStageHelper.adjustClockIfClockSkew(response); + throw responseException(response); + } + return response; + } + + private RuntimeException responseException(Response response) { + Optional optionalRetryAfter = retryAfter(response.httpResponse()); + if (optionalRetryAfter.isPresent()) { + return new SdkExceptionWithRetryAfterHint(optionalRetryAfter.get(), response.exception()); + } + return response.exception(); + } - Response response; + private Optional retryAfter(SdkHttpFullResponse response) { + Optional optionalRetryAfterHeader = response.firstMatchingHeader(RETRY_AFTER_HEADER); + if (optionalRetryAfterHeader.isPresent()) { + String retryAfterHeader = optionalRetryAfterHeader.get(); try { - retryableStageHelper.logSendingRequest(); - response = requestPipeline.execute(retryableStageHelper.requestToSend(), context); - } catch (SdkException | IOException e) { - retryableStageHelper.setLastException(e); - retryableStageHelper.updateClientSendingRateForErrorResponse(); - continue; + return Optional.of(Integer.parseInt(retryAfterHeader)); + } catch (NumberFormatException e) { + // Ignore and fallback to returning empty. } + } + return Optional.empty(); + } - retryableStageHelper.setLastResponse(response.httpResponse()); + // This probably should go directly into SdkException + static class SdkExceptionWithRetryAfterHint extends RuntimeException { + private final SdkException cause; + private final int seconds; - if (!response.isSuccess()) { - retryableStageHelper.adjustClockIfClockSkew(response); - retryableStageHelper.setLastException(response.exception()); - retryableStageHelper.updateClientSendingRateForErrorResponse(); - continue; - } + SdkExceptionWithRetryAfterHint(int seconds, SdkException cause) { + this.seconds = seconds; + this.cause = cause; + } - retryableStageHelper.updateClientSendingRateForSuccessResponse(); + public int retryAfter() { + return seconds; + } + + public SdkException cause() { + return cause; + } - retryableStageHelper.attemptSucceeded(); - return response; + public int seconds() { + return seconds; } } } diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/RetryableStage2.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/RetryableStage2.java deleted file mode 100644 index d12c444afa73..000000000000 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/RetryableStage2.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -package software.amazon.awssdk.core.internal.http.pipeline.stages; - -import java.io.IOException; -import java.time.Duration; -import java.util.Optional; -import java.util.concurrent.TimeUnit; -import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.core.Response; -import software.amazon.awssdk.core.exception.SdkException; -import software.amazon.awssdk.core.internal.http.HttpClientDependencies; -import software.amazon.awssdk.core.internal.http.RequestExecutionContext; -import software.amazon.awssdk.core.internal.http.pipeline.RequestPipeline; -import software.amazon.awssdk.core.internal.http.pipeline.RequestToResponsePipeline; -import software.amazon.awssdk.core.internal.http.pipeline.stages.utils.RetryableStageHelper2; -import software.amazon.awssdk.http.SdkHttpFullRequest; -import software.amazon.awssdk.http.SdkHttpFullResponse; - -/** - * Wrapper around the pipeline for a single request to provide retry, clock-skew and request throttling functionality. - */ -@SdkInternalApi -public final class RetryableStage2 implements RequestToResponsePipeline { - private static final String RETRY_AFTER_HEADER = "Retry-After"; - private final RequestPipeline> requestPipeline; - private final HttpClientDependencies dependencies; - - public RetryableStage2(HttpClientDependencies dependencies, - RequestPipeline> requestPipeline) { - this.dependencies = dependencies; - this.requestPipeline = requestPipeline; - } - - @Override - public Response execute(SdkHttpFullRequest request, RequestExecutionContext context) throws Exception { - RetryableStageHelper2 retryableStageHelper = new RetryableStageHelper2(request, context, dependencies); - Duration initialDelay = retryableStageHelper.acquireInitialToken(); - TimeUnit.MILLISECONDS.sleep(initialDelay.toMillis()); - while (true) { - try { - retryableStageHelper.startingAttempt(); - Response response = executeRequest(retryableStageHelper, context); - retryableStageHelper.recordAttemptSucceeded(); - return response; - } catch (SdkExceptionWithRetryAfterHint | SdkException | IOException e) { - Throwable throwable = e; - if (e instanceof SdkExceptionWithRetryAfterHint) { - SdkExceptionWithRetryAfterHint wrapper = (SdkExceptionWithRetryAfterHint) e; - throwable = wrapper.cause(); - } - retryableStageHelper.setLastException(throwable); - Duration suggestedDelay = suggestedDelay(e); - Optional backoffDelay = retryableStageHelper.tryRefreshToken(suggestedDelay); - if (backoffDelay.isPresent()) { - Duration delay = backoffDelay.get(); - retryableStageHelper.logBackingOff(delay); - TimeUnit.MILLISECONDS.sleep(delay.toMillis()); - } else { - throw retryableStageHelper.retryPolicyDisallowedRetryException(); - } - } - } - } - - private Duration suggestedDelay(Exception e) { - if (e instanceof SdkExceptionWithRetryAfterHint) { - SdkExceptionWithRetryAfterHint except = (SdkExceptionWithRetryAfterHint) e; - return Duration.ofSeconds(except.retryAfter()); - } - return Duration.ZERO; - } - - /** - * Executes the requests and returns the result. If the response is not successful throws the wrapped exception. - */ - private Response executeRequest(RetryableStageHelper2 retryableStageHelper, - RequestExecutionContext context) throws Exception { - retryableStageHelper.logSendingRequest(); - Response response = requestPipeline.execute(retryableStageHelper.requestToSend(), context); - retryableStageHelper.setLastResponse(response.httpResponse()); - if (!response.isSuccess()) { - retryableStageHelper.adjustClockIfClockSkew(response); - throw responseException(response); - } - return response; - } - - private RuntimeException responseException(Response response) { - Optional optionalRetryAfter = retryAfter(response.httpResponse()); - if (optionalRetryAfter.isPresent()) { - return new SdkExceptionWithRetryAfterHint(optionalRetryAfter.get(), response.exception()); - } - return response.exception(); - } - - private Optional retryAfter(SdkHttpFullResponse response) { - Optional optionalRetryAfterHeader = response.firstMatchingHeader(RETRY_AFTER_HEADER); - if (optionalRetryAfterHeader.isPresent()) { - String retryAfterHeader = optionalRetryAfterHeader.get(); - try { - return Optional.of(Integer.parseInt(retryAfterHeader)); - } catch (NumberFormatException e) { - // Ignore and fallback to returning empty. - } - } - return Optional.empty(); - } - - // This probably should go directly into SdkException - static class SdkExceptionWithRetryAfterHint extends RuntimeException { - private final SdkException cause; - private final int seconds; - - SdkExceptionWithRetryAfterHint(int seconds, SdkException cause) { - this.seconds = seconds; - this.cause = cause; - } - - public int retryAfter() { - return seconds; - } - - public SdkException cause() { - return cause; - } - - public int seconds() { - return seconds; - } - } -} diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/utils/RetryableStageHelper.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/utils/RetryableStageHelper.java index e9511e9b0743..3fcf04c88b5e 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/utils/RetryableStageHelper.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/utils/RetryableStageHelper.java @@ -15,72 +15,76 @@ package software.amazon.awssdk.core.internal.http.pipeline.stages.utils; +import static software.amazon.awssdk.core.internal.InternalCoreExecutionAttribute.EXECUTION_ATTEMPT; +import static software.amazon.awssdk.core.internal.InternalCoreExecutionAttribute.RETRY_TOKEN; +import static software.amazon.awssdk.core.metrics.CoreMetric.RETRY_COUNT; + import java.time.Duration; import java.util.ArrayList; import java.util.List; -import java.util.OptionalDouble; +import java.util.Optional; import java.util.concurrent.CompletionException; import software.amazon.awssdk.annotations.SdkInternalApi; import software.amazon.awssdk.core.Response; import software.amazon.awssdk.core.SdkStandardLogger; import software.amazon.awssdk.core.client.config.SdkClientOption; -import software.amazon.awssdk.core.exception.NonRetryableException; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.core.exception.SdkException; import software.amazon.awssdk.core.interceptor.ExecutionAttribute; -import software.amazon.awssdk.core.internal.InternalCoreExecutionAttribute; import software.amazon.awssdk.core.internal.http.HttpClientDependencies; import software.amazon.awssdk.core.internal.http.RequestExecutionContext; -import software.amazon.awssdk.core.internal.http.pipeline.stages.AsyncRetryableStage; -import software.amazon.awssdk.core.internal.http.pipeline.stages.RetryableStage; import software.amazon.awssdk.core.internal.retry.ClockSkewAdjuster; -import software.amazon.awssdk.core.internal.retry.RateLimitingTokenBucket; -import software.amazon.awssdk.core.metrics.CoreMetric; -import software.amazon.awssdk.core.retry.RetryMode; +import software.amazon.awssdk.core.internal.retry.RetryPolicyAdapter; import software.amazon.awssdk.core.retry.RetryPolicy; import software.amazon.awssdk.core.retry.RetryPolicyContext; -import software.amazon.awssdk.core.retry.RetryUtils; import software.amazon.awssdk.http.SdkHttpFullRequest; import software.amazon.awssdk.http.SdkHttpResponse; +import software.amazon.awssdk.retries.AdaptiveRetryStrategy; +import software.amazon.awssdk.retries.api.AcquireInitialTokenRequest; +import software.amazon.awssdk.retries.api.AcquireInitialTokenResponse; +import software.amazon.awssdk.retries.api.RecordSuccessRequest; +import software.amazon.awssdk.retries.api.RefreshRetryTokenRequest; +import software.amazon.awssdk.retries.api.RefreshRetryTokenResponse; +import software.amazon.awssdk.retries.api.RetryStrategy; +import software.amazon.awssdk.retries.api.RetryToken; +import software.amazon.awssdk.retries.api.TokenAcquisitionFailedException; /** * Contains the logic shared by {@link RetryableStage} and {@link AsyncRetryableStage} when querying and interacting with a - * {@link RetryPolicy}. + * {@link RetryStrategy}. */ @SdkInternalApi -public class RetryableStageHelper { +public final class RetryableStageHelper { public static final String SDK_RETRY_INFO_HEADER = "amz-sdk-request"; - public static final ExecutionAttribute LAST_BACKOFF_DELAY_DURATION = new ExecutionAttribute<>("LastBackoffDuration"); private final SdkHttpFullRequest request; private final RequestExecutionContext context; - private final RetryPolicy retryPolicy; - private final RateLimitingTokenBucket rateLimitingTokenBucket; + private RetryPolicyAdapter retryPolicyAdapter; + private final RetryStrategy retryStrategy; private final HttpClientDependencies dependencies; private final List exceptionMessageHistory = new ArrayList<>(); - private int attemptNumber = 0; - private SdkHttpResponse lastResponse = null; - private SdkException lastException = null; + private SdkHttpResponse lastResponse; + private SdkException lastException; public RetryableStageHelper(SdkHttpFullRequest request, RequestExecutionContext context, - RateLimitingTokenBucket rateLimitingTokenBucket, HttpClientDependencies dependencies) { this.request = request; this.context = context; - this.retryPolicy = dependencies.clientConfiguration().option(SdkClientOption.RETRY_POLICY); - this.dependencies = dependencies; - - if (rateLimitingTokenBucket != null) { - this.rateLimitingTokenBucket = rateLimitingTokenBucket; - } else if (isRateLimitingEnabled()) { - this.rateLimitingTokenBucket = new RateLimitingTokenBucket(); - } else { - this.rateLimitingTokenBucket = null; + RetryPolicy retryPolicy = dependencies.clientConfiguration().option(SdkClientOption.RETRY_POLICY); + RetryStrategy retryStrategy = dependencies.clientConfiguration().option(SdkClientOption.RETRY_STRATEGY); + if (retryPolicy != null) { + retryPolicyAdapter = RetryPolicyAdapter.builder() + .retryPolicy(retryPolicy) + .build(); + } else if (retryStrategy instanceof RetryPolicyAdapter) { + retryPolicyAdapter = (RetryPolicyAdapter) retryStrategy; } + this.retryStrategy = retryStrategy; + this.dependencies = dependencies; } /** @@ -88,37 +92,71 @@ public RetryableStageHelper(SdkHttpFullRequest request, */ public void startingAttempt() { ++attemptNumber; - context.executionAttributes().putAttribute(InternalCoreExecutionAttribute.EXECUTION_ATTEMPT, attemptNumber); + context.executionAttributes().putAttribute(EXECUTION_ATTEMPT, attemptNumber); } /** - * Returns true if the retry policy allows this attempt. This will always return true if the current attempt is not a retry - * (i.e. it's the first request in the execution). + * Invoke when starting the first attempt. This method will acquire the initial token and store it as an execution attribute. + * This method returns a delay that the caller have to wait before attempting the first request. If this method returns + * {@link Duration#ZERO} if the calling code does not have to wait. As of today the only strategy that might return a non-zero + * value is {@link AdaptiveRetryStrategy}. */ - public boolean retryPolicyAllowsRetry() { - if (isInitialAttempt()) { - return true; - } - - if (lastException instanceof NonRetryableException) { - return false; - } + public Duration acquireInitialToken() { + String scope = "GLOBAL"; + AcquireInitialTokenRequest acquireRequest = AcquireInitialTokenRequest.create(scope); + AcquireInitialTokenResponse acquireResponse = retryStrategy().acquireInitialToken(acquireRequest); + RetryToken retryToken = acquireResponse.token(); + Duration delay = acquireResponse.delay(); + context.executionAttributes().putAttribute(RETRY_TOKEN, retryToken); + context.executionAttributes().putAttribute(LAST_BACKOFF_DELAY_DURATION, delay); + return delay; + } - RetryPolicyContext context = retryPolicyContext(true); + /** + * Notify the retry strategy that the request attempt succeeded. + */ + public void recordAttemptSucceeded() { + RetryToken retryToken = context.executionAttributes().getAttribute(RETRY_TOKEN); + RecordSuccessRequest recordSuccessRequest = RecordSuccessRequest.create(retryToken); + retryStrategy().recordSuccess(recordSuccessRequest); + context.executionContext().metricCollector().reportMetric(RETRY_COUNT, retriesAttemptedSoFar()); + } - boolean willRetry = retryPolicy.aggregateRetryCondition().shouldRetry(context); - if (!willRetry) { - retryPolicy.aggregateRetryCondition().requestWillNotBeRetried(context); + /** + * Invoked after a failed attempt and before retrying. The returned optional will be non-empty if the client can retry or + * empty if the retry-strategy disallows the retry. The calling code is expected to wait the delay represented in the duration + * if present before retrying the request. + * + * @param suggestedDelay A suggested delay, presumably coming from the server response. The response when present will be at + * least this amount. + * @return An optional time to wait. If the value is not present the retry strategy disallowed the retry and the calling code + * should not retry. + */ + public Optional tryRefreshToken(Duration suggestedDelay) { + RetryToken retryToken = context.executionAttributes().getAttribute(RETRY_TOKEN); + RefreshRetryTokenResponse refreshResponse; + try { + RefreshRetryTokenRequest refreshRequest = RefreshRetryTokenRequest.builder() + .failure(this.lastException) + .token(retryToken) + .suggestedDelay(suggestedDelay) + .build(); + refreshResponse = retryStrategy().refreshRetryToken(refreshRequest); + } catch (TokenAcquisitionFailedException e) { + context.executionAttributes().putAttribute(RETRY_TOKEN, e.token()); + return Optional.empty(); } - - return willRetry; + Duration delay = refreshResponse.delay(); + context.executionAttributes().putAttribute(RETRY_TOKEN, refreshResponse.token()); + context.executionAttributes().putAttribute(LAST_BACKOFF_DELAY_DURATION, delay); + return Optional.of(delay); } /** - * Return the exception that should be thrown, because the retry policy did not allow the request to be retried. + * Return the exception that should be thrown, because the retry strategy did not allow the request to be retried. */ public SdkException retryPolicyDisallowedRetryException() { - context.executionContext().metricCollector().reportMetric(CoreMetric.RETRY_COUNT, retriesAttemptedSoFar(true)); + context.executionContext().metricCollector().reportMetric(RETRY_COUNT, retriesAttemptedSoFar()); for (int i = 0; i < exceptionMessageHistory.size() - 1; i++) { SdkClientException pastException = SdkClientException.builder() @@ -130,26 +168,6 @@ public SdkException retryPolicyDisallowedRetryException() { return lastException; } - /** - * Get the amount of time that the request should be delayed before being sent. This may be {@link Duration#ZERO}, such as - * for the first request in the request series. - */ - public Duration getBackoffDelay() { - Duration result; - if (isInitialAttempt()) { - result = Duration.ZERO; - } else { - RetryPolicyContext context = retryPolicyContext(true); - if (RetryUtils.isThrottlingException(lastException)) { - result = retryPolicy.throttlingBackoffStrategy().computeDelayBeforeNextRetry(context); - } else { - result = retryPolicy.backoffStrategy().computeDelayBeforeNextRetry(context); - } - } - context.executionAttributes().putAttribute(LAST_BACKOFF_DELAY_DURATION, result); - return result; - } - /** * Log a message to the user at the debug level to indicate how long we will wait before retrying the request. */ @@ -164,7 +182,8 @@ public void logBackingOff(Duration backoffDelay) { */ public SdkHttpFullRequest requestToSend() { return request.toBuilder() - .putHeader(SDK_RETRY_INFO_HEADER, "attempt=" + attemptNumber + "; max=" + (retryPolicy.numRetries() + 1)) + .putHeader(SDK_RETRY_INFO_HEADER, "attempt=" + attemptNumber + + "; max=" + retryStrategy().maxAttempts()) .build(); } @@ -186,21 +205,6 @@ public void adjustClockIfClockSkew(Response response) { } } - /** - * Notify the retry policy that the request attempt succeeded. - */ - public void attemptSucceeded() { - retryPolicy.aggregateRetryCondition().requestSucceeded(retryPolicyContext(false)); - context.executionContext().metricCollector().reportMetric(CoreMetric.RETRY_COUNT, retriesAttemptedSoFar(false)); - } - - /** - * Retrieve the current attempt number, updated whenever {@link #startingAttempt()} is invoked. - */ - public int getAttemptNumber() { - return attemptNumber; - } - /** * Retrieve the last call failure exception encountered by this execution, updated whenever {@link #setLastException} is * invoked. @@ -210,8 +214,8 @@ public SdkException getLastException() { } /** - * Update the {@link #getLastException()} value for this helper. This will be used to determine whether the request should - * be retried. + * Update the {@link #getLastException()} value for this helper. This will be used to determine whether the request should be + * retried. */ public void setLastException(Throwable lastException) { if (lastException instanceof CompletionException) { @@ -234,109 +238,58 @@ public void setLastResponse(SdkHttpResponse lastResponse) { } /** - * Whether rate limiting is enabled. Only {@link RetryMode#ADAPTIVE} enables rate limiting. + * Returns true if this is the first attempt. */ - private boolean isRateLimitingEnabled() { - return retryPolicy.retryMode() == RetryMode.ADAPTIVE; + private boolean isInitialAttempt() { + return attemptNumber == 1; } /** - * Whether rate limiting should fast fail. + * Retrieve the current attempt number, updated whenever {@link #startingAttempt()} is invoked. */ - public boolean isFastFailRateLimiting() { - return Boolean.TRUE.equals(retryPolicy.isFastFailRateLimiting()); - } - - public boolean isLastExceptionThrottlingException() { - if (lastException == null) { - return false; - } - - return RetryUtils.isThrottlingException(lastException); + public int getAttemptNumber() { + return attemptNumber; } /** - * Acquire a send token from the rate limiter. Returns immediately if rate limiting is not enabled. + * Retrieve the number of retries sent so far in the request execution. */ - public void getSendToken() { - if (!isRateLimitingEnabled()) { - return; - } - - boolean acquired = rateLimitingTokenBucket.acquire(1.0, isFastFailRateLimiting()); - - if (!acquired) { - String errorMessage = "Unable to acquire a send token immediately without waiting. This indicates that ADAPTIVE " - + "retry mode is enabled, fast fail rate limiting is enabled, and that rate limiting is " - + "engaged because of prior throttled requests. The request will not be executed."; - throw SdkClientException.create(errorMessage); - } + private int retriesAttemptedSoFar() { + return Math.max(0, attemptNumber - 1); } /** - * Acquire a send token from the rate limiter in a non blocking manner. See - * {@link RateLimitingTokenBucket#acquireNonBlocking(double, boolean)} for documentation on how to interpret the returned - * value. + * Returns the {@link RetryStrategy} to be used by this class. If there's a client configured retry-policy then an adapter to + * wrap it is returned. This allows this code to be backwards compatible with previously configured retry-policies by the + * calling code. */ - public OptionalDouble getSendTokenNonBlocking() { - if (!isRateLimitingEnabled()) { - return OptionalDouble.of(0.0); - } - - return rateLimitingTokenBucket.acquireNonBlocking(1.0, isFastFailRateLimiting()); - } - - /** - * Conditionally updates the sending rate of the rate limiter when an error response is received. This operation is a noop - * if rate limiting is not enabled. - */ - public void updateClientSendingRateForErrorResponse() { - if (!isRateLimitingEnabled()) { - return; - } - // Only throttling errors affect the sending rate. For non error - // responses, they're handled by - // updateClientSendingRateForSuccessResponse() - if (isLastExceptionThrottlingException()) { - rateLimitingTokenBucket.updateClientSendingRate(true); + private RetryStrategy retryStrategy() { + if (retryPolicyAdapter != null) { + if (retryPolicyAdapter.isInitialized()) { + retryPolicyAdapter = retryPolicyAdapter.toBuilder() + .retryPolicyContext(retryPolicyContext()) + .build(); + } else { + retryPolicyAdapter = retryPolicyAdapter.toBuilder() + .initialize(retryPolicyContext()) + .build(); + } + return retryPolicyAdapter; } + return retryStrategy; } /** - * Conditionally updates the sending rate of the rate limiter when an error response is received. This operation is a noop - * if rate limiting is not enabled. + * Creates a RetryPolicyContext to be used when the using the retry policy to strategy adapter. */ - public void updateClientSendingRateForSuccessResponse() { - if (!isRateLimitingEnabled()) { - return; - } - rateLimitingTokenBucket.updateClientSendingRate(false); - } - - private boolean isInitialAttempt() { - return attemptNumber == 1; - } - - private RetryPolicyContext retryPolicyContext(boolean isBeforeAttemptSent) { + private RetryPolicyContext retryPolicyContext() { return RetryPolicyContext.builder() .request(request) .originalRequest(context.originalRequest()) .exception(lastException) - .retriesAttempted(retriesAttemptedSoFar(isBeforeAttemptSent)) + .retriesAttempted(retriesAttemptedSoFar()) .executionAttributes(context.executionAttributes()) .httpStatusCode(lastResponse == null ? null : lastResponse.statusCode()) .build(); } - - /** - * Retrieve the number of retries sent so far in the request execution. This depends on whether or not we've actually - * sent the request yet during this attempt. - * - * Assuming we're executing attempt 3, the number of retries attempted varies based on whether the request has been sent to - * the service yet. Before we send the request, the number of retries is 1 (from attempt 2). After we send the request, the - * number of retries is 2 (from attempt 2 and attempt 3). - */ - private int retriesAttemptedSoFar(boolean isBeforeAttemptSent) { - return Math.max(0, isBeforeAttemptSent ? attemptNumber - 2 : attemptNumber - 1); - } } diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/utils/RetryableStageHelper2.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/utils/RetryableStageHelper2.java deleted file mode 100644 index 13cbb601789b..000000000000 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/utils/RetryableStageHelper2.java +++ /dev/null @@ -1,294 +0,0 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -package software.amazon.awssdk.core.internal.http.pipeline.stages.utils; - -import static software.amazon.awssdk.core.internal.InternalCoreExecutionAttribute.EXECUTION_ATTEMPT; -import static software.amazon.awssdk.core.internal.InternalCoreExecutionAttribute.RETRY_TOKEN; -import static software.amazon.awssdk.core.internal.http.pipeline.stages.utils.RetryableStageHelper.LAST_BACKOFF_DELAY_DURATION; -import static software.amazon.awssdk.core.metrics.CoreMetric.RETRY_COUNT; - -import java.time.Duration; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.CompletionException; -import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.core.Response; -import software.amazon.awssdk.core.SdkStandardLogger; -import software.amazon.awssdk.core.client.config.SdkClientOption; -import software.amazon.awssdk.core.exception.SdkClientException; -import software.amazon.awssdk.core.exception.SdkException; -import software.amazon.awssdk.core.internal.http.HttpClientDependencies; -import software.amazon.awssdk.core.internal.http.RequestExecutionContext; -import software.amazon.awssdk.core.internal.http.pipeline.stages.AsyncRetryableStage; -import software.amazon.awssdk.core.internal.http.pipeline.stages.RetryableStage; -import software.amazon.awssdk.core.internal.retry.ClockSkewAdjuster; -import software.amazon.awssdk.core.internal.retry.RetryPolicyAdapter; -import software.amazon.awssdk.core.retry.RetryPolicy; -import software.amazon.awssdk.core.retry.RetryPolicyContext; -import software.amazon.awssdk.http.SdkHttpFullRequest; -import software.amazon.awssdk.http.SdkHttpResponse; -import software.amazon.awssdk.retries.AdaptiveRetryStrategy; -import software.amazon.awssdk.retries.api.AcquireInitialTokenRequest; -import software.amazon.awssdk.retries.api.AcquireInitialTokenResponse; -import software.amazon.awssdk.retries.api.RecordSuccessRequest; -import software.amazon.awssdk.retries.api.RefreshRetryTokenRequest; -import software.amazon.awssdk.retries.api.RefreshRetryTokenResponse; -import software.amazon.awssdk.retries.api.RetryStrategy; -import software.amazon.awssdk.retries.api.RetryToken; -import software.amazon.awssdk.retries.api.TokenAcquisitionFailedException; - -/** - * Contains the logic shared by {@link RetryableStage} and {@link AsyncRetryableStage} when querying and interacting with a - * {@link RetryStrategy}. - */ -@SdkInternalApi -public final class RetryableStageHelper2 { - public static final String SDK_RETRY_INFO_HEADER = "amz-sdk-request"; - private final SdkHttpFullRequest request; - private final RequestExecutionContext context; - private RetryPolicyAdapter retryPolicyAdapter; - private final RetryStrategy retryStrategy; - private final HttpClientDependencies dependencies; - private final List exceptionMessageHistory = new ArrayList<>(); - private int attemptNumber = 0; - private SdkHttpResponse lastResponse; - private SdkException lastException; - - public RetryableStageHelper2(SdkHttpFullRequest request, - RequestExecutionContext context, - HttpClientDependencies dependencies) { - this.request = request; - this.context = context; - RetryPolicy retryPolicy = dependencies.clientConfiguration().option(SdkClientOption.RETRY_POLICY); - RetryStrategy retryStrategy = dependencies.clientConfiguration().option(SdkClientOption.RETRY_STRATEGY); - if (retryPolicy != null) { - retryPolicyAdapter = RetryPolicyAdapter.builder() - .retryPolicy(retryPolicy) - .build(); - } else if (retryStrategy instanceof RetryPolicyAdapter) { - retryPolicyAdapter = (RetryPolicyAdapter) retryStrategy; - } - this.retryStrategy = retryStrategy; - this.dependencies = dependencies; - } - - /** - * Invoke when starting a request attempt, before querying the retry policy. - */ - public void startingAttempt() { - ++attemptNumber; - context.executionAttributes().putAttribute(EXECUTION_ATTEMPT, attemptNumber); - } - - /** - * Invoke when starting the first attempt. This method will acquire the initial token and store it as an execution attribute. - * This method returns a delay that the caller have to wait before attempting the first request. If this method returns - * {@link Duration#ZERO} if the calling code does not have to wait. As of today the only strategy that might return a non-zero - * value is {@link AdaptiveRetryStrategy}. - */ - public Duration acquireInitialToken() { - String scope = "GLOBAL"; - AcquireInitialTokenRequest acquireRequest = AcquireInitialTokenRequest.create(scope); - AcquireInitialTokenResponse acquireResponse = retryStrategy().acquireInitialToken(acquireRequest); - RetryToken retryToken = acquireResponse.token(); - Duration delay = acquireResponse.delay(); - context.executionAttributes().putAttribute(RETRY_TOKEN, retryToken); - context.executionAttributes().putAttribute(LAST_BACKOFF_DELAY_DURATION, delay); - return delay; - } - - /** - * Notify the retry strategy that the request attempt succeeded. - */ - public void recordAttemptSucceeded() { - RetryToken retryToken = context.executionAttributes().getAttribute(RETRY_TOKEN); - RecordSuccessRequest recordSuccessRequest = RecordSuccessRequest.create(retryToken); - retryStrategy().recordSuccess(recordSuccessRequest); - context.executionContext().metricCollector().reportMetric(RETRY_COUNT, retriesAttemptedSoFar()); - } - - /** - * Invoked after a failed attempt and before retrying. The returned optional will be non-empty if the client can retry or - * empty if the retry-strategy disallows the retry. The calling code is expected to wait the delay represented in the duration - * if present before retrying the request. - * - * @param suggestedDelay A suggested delay, presumably coming from the server response. The response when present will be at - * least this amount. - * @return An optional time to wait. If the value is not present the retry strategy disallowed the retry and the calling code - * should not retry. - */ - public Optional tryRefreshToken(Duration suggestedDelay) { - RetryToken retryToken = context.executionAttributes().getAttribute(RETRY_TOKEN); - RefreshRetryTokenResponse refreshResponse; - try { - RefreshRetryTokenRequest refreshRequest = RefreshRetryTokenRequest.builder() - .failure(this.lastException) - .token(retryToken) - .suggestedDelay(suggestedDelay) - .build(); - refreshResponse = retryStrategy().refreshRetryToken(refreshRequest); - } catch (TokenAcquisitionFailedException e) { - context.executionAttributes().putAttribute(RETRY_TOKEN, e.token()); - return Optional.empty(); - } - Duration delay = refreshResponse.delay(); - context.executionAttributes().putAttribute(RETRY_TOKEN, refreshResponse.token()); - context.executionAttributes().putAttribute(LAST_BACKOFF_DELAY_DURATION, delay); - return Optional.of(delay); - } - - /** - * Return the exception that should be thrown, because the retry strategy did not allow the request to be retried. - */ - public SdkException retryPolicyDisallowedRetryException() { - context.executionContext().metricCollector().reportMetric(RETRY_COUNT, retriesAttemptedSoFar()); - for (int i = 0; i < exceptionMessageHistory.size() - 1; i++) { - SdkClientException pastException = - SdkClientException.builder() - .message("Request attempt " + (i + 1) + " failure: " + exceptionMessageHistory.get(i)) - .writableStackTrace(false) - .build(); - lastException.addSuppressed(pastException); - } - return lastException; - } - - /** - * Log a message to the user at the debug level to indicate how long we will wait before retrying the request. - */ - public void logBackingOff(Duration backoffDelay) { - SdkStandardLogger.REQUEST_LOGGER.debug(() -> "Retryable error detected. Will retry in " + - backoffDelay.toMillis() + "ms. Request attempt number " + - attemptNumber, lastException); - } - - /** - * Retrieve the request to send to the service, including any detailed retry information headers. - */ - public SdkHttpFullRequest requestToSend() { - return request.toBuilder() - .putHeader(SDK_RETRY_INFO_HEADER, "attempt=" + attemptNumber - + "; max=" + retryStrategy().maxAttempts()) - .build(); - } - - /** - * Log a message to the user at the debug level to indicate that we are sending the request to the service. - */ - public void logSendingRequest() { - SdkStandardLogger.REQUEST_LOGGER.debug(() -> (isInitialAttempt() ? "Sending" : "Retrying") + " Request: " + request); - } - - /** - * Adjust the client-side clock skew if the provided response indicates that there is a large skew between the client and - * service. This will allow a retried request to be signed with what is likely to be a more accurate time. - */ - public void adjustClockIfClockSkew(Response response) { - ClockSkewAdjuster clockSkewAdjuster = dependencies.clockSkewAdjuster(); - if (!response.isSuccess() && clockSkewAdjuster.shouldAdjust(response.exception())) { - dependencies.updateTimeOffset(clockSkewAdjuster.getAdjustmentInSeconds(response.httpResponse())); - } - } - - /** - * Retrieve the last call failure exception encountered by this execution, updated whenever {@link #setLastException} is - * invoked. - */ - public SdkException getLastException() { - return lastException; - } - - /** - * Update the {@link #getLastException()} value for this helper. This will be used to determine whether the request should be - * retried. - */ - public void setLastException(Throwable lastException) { - if (lastException instanceof CompletionException) { - setLastException(lastException.getCause()); - } else if (lastException instanceof SdkException) { - this.lastException = (SdkException) lastException; - exceptionMessageHistory.add(this.lastException.getMessage()); - } else { - this.lastException = SdkClientException.create("Unable to execute HTTP request: " + lastException.getMessage(), - lastException); - exceptionMessageHistory.add(this.lastException.getMessage()); - } - } - - /** - * Set the last HTTP response returned by the service. This will be used to determine whether the request should be retried. - */ - public void setLastResponse(SdkHttpResponse lastResponse) { - this.lastResponse = lastResponse; - } - - /** - * Returns true if this is the first attempt. - */ - private boolean isInitialAttempt() { - return attemptNumber == 1; - } - - /** - * Retrieve the current attempt number, updated whenever {@link #startingAttempt()} is invoked. - */ - public int getAttemptNumber() { - return attemptNumber; - } - - /** - * Retrieve the number of retries sent so far in the request execution. - */ - private int retriesAttemptedSoFar() { - return Math.max(0, attemptNumber - 1); - } - - /** - * Returns the {@link RetryStrategy} to be used by this class. If there's a client configured retry-policy then an adapter to - * wrap it is returned. This allows this code to be backwards compatible with previously configured retry-policies by the - * calling code. - */ - private RetryStrategy retryStrategy() { - if (retryPolicyAdapter != null) { - if (retryPolicyAdapter.isInitialized()) { - retryPolicyAdapter = retryPolicyAdapter.toBuilder() - .retryPolicyContext(retryPolicyContext()) - .build(); - } else { - retryPolicyAdapter = retryPolicyAdapter.toBuilder() - .initialize(retryPolicyContext()) - .build(); - } - return retryPolicyAdapter; - } - return retryStrategy; - } - - /** - * Creates a RetryPolicyContext to be used when the using the retry policy to strategy adapter. - */ - private RetryPolicyContext retryPolicyContext() { - return RetryPolicyContext.builder() - .request(request) - .originalRequest(context.originalRequest()) - .exception(lastException) - .retriesAttempted(retriesAttemptedSoFar()) - .executionAttributes(context.executionAttributes()) - .httpStatusCode(lastResponse == null ? null : lastResponse.statusCode()) - .build(); - } -} diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/interceptor/HttpChecksumValidationInterceptor.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/interceptor/HttpChecksumValidationInterceptor.java index b5af1a33bbe9..c64047df2989 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/interceptor/HttpChecksumValidationInterceptor.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/interceptor/HttpChecksumValidationInterceptor.java @@ -25,11 +25,10 @@ import java.util.function.Predicate; import org.reactivestreams.Publisher; import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.core.ClientType; -import software.amazon.awssdk.core.checksums.Algorithm; +import software.amazon.awssdk.checksums.SdkChecksum; +import software.amazon.awssdk.checksums.spi.ChecksumAlgorithm; import software.amazon.awssdk.core.checksums.ChecksumSpecs; import software.amazon.awssdk.core.checksums.ChecksumValidation; -import software.amazon.awssdk.core.checksums.SdkChecksum; import software.amazon.awssdk.core.interceptor.Context; import software.amazon.awssdk.core.interceptor.ExecutionAttributes; import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; @@ -43,6 +42,8 @@ /** * Interceptor to intercepts Sync and Async responses. * The Http Checksum is computed and validated with the one that is passed in the header of the response. + * + * // TODO: convert this to a stage (JAVA-7963) */ @SdkInternalApi public final class HttpChecksumValidationInterceptor implements ExecutionInterceptor { @@ -55,11 +56,15 @@ public final class HttpChecksumValidationInterceptor implements ExecutionInterce public Optional modifyHttpResponseContent(Context.ModifyHttpResponse context, ExecutionAttributes executionAttributes) { + if (executionAttributes.getAttribute(SdkExecutionAttribute.CLIENT_TYPE) == ASYNC) { + return context.responseBody(); + } + ChecksumSpecs resolvedChecksumSpecs = HttpChecksumResolver.getResolvedChecksumSpecs(executionAttributes); if (resolvedChecksumSpecs != null && - isFlexibleChecksumValidationForResponse(executionAttributes, resolvedChecksumSpecs, SYNC)) { + isFlexibleChecksumValidationForResponse(executionAttributes, resolvedChecksumSpecs)) { - Pair algorithmChecksumPair = getAlgorithmChecksumValuePair( + Pair algorithmChecksumPair = getAlgorithmChecksumValuePair( context.httpResponse(), resolvedChecksumSpecs); updateContextWithChecksumValidationStatus(executionAttributes, algorithmChecksumPair); @@ -75,11 +80,16 @@ public Optional modifyHttpResponseContent(Context.ModifyHttpRespons @Override public Optional> modifyAsyncHttpResponseContent(Context.ModifyHttpResponse context, ExecutionAttributes executionAttributes) { + + if (executionAttributes.getAttribute(SdkExecutionAttribute.CLIENT_TYPE) == SYNC) { + return context.responsePublisher(); + } + ChecksumSpecs resolvedChecksumSpecs = HttpChecksumResolver.getResolvedChecksumSpecs(executionAttributes); if (resolvedChecksumSpecs != null && - isFlexibleChecksumValidationForResponse(executionAttributes, resolvedChecksumSpecs, ASYNC)) { - Pair algorithmChecksumPair = getAlgorithmChecksumValuePair(context.httpResponse(), - resolvedChecksumSpecs); + isFlexibleChecksumValidationForResponse(executionAttributes, resolvedChecksumSpecs)) { + Pair algorithmChecksumPair = getAlgorithmChecksumValuePair(context.httpResponse(), + resolvedChecksumSpecs); updateContextWithChecksumValidationStatus(executionAttributes, algorithmChecksumPair); if (algorithmChecksumPair != null && context.responsePublisher().isPresent()) { return Optional.of(new ChecksumValidatingPublisher(context.responsePublisher().get(), @@ -91,24 +101,22 @@ public Optional> modifyAsyncHttpResponseContent(Context.Mo } private void updateContextWithChecksumValidationStatus(ExecutionAttributes executionAttributes, - Pair algorithmChecksumPair) { + Pair algorithmChecksumPair) { if (algorithmChecksumPair == null || algorithmChecksumPair.left() == null) { executionAttributes.putAttribute(SdkExecutionAttribute.HTTP_RESPONSE_CHECKSUM_VALIDATION, ChecksumValidation.CHECKSUM_ALGORITHM_NOT_FOUND); } else { executionAttributes.putAttribute(SdkExecutionAttribute.HTTP_RESPONSE_CHECKSUM_VALIDATION, ChecksumValidation.VALIDATED); - executionAttributes.putAttribute(SdkExecutionAttribute.HTTP_CHECKSUM_VALIDATION_ALGORITHM, + executionAttributes.putAttribute(SdkExecutionAttribute.HTTP_CHECKSUM_VALIDATION_ALGORITHM_V2, algorithmChecksumPair.left()); } } private boolean isFlexibleChecksumValidationForResponse(ExecutionAttributes executionAttributes, - ChecksumSpecs checksumSpecs, - ClientType clientType) { + ChecksumSpecs checksumSpecs) { return HttpChecksumUtils.isHttpChecksumValidationEnabled(checksumSpecs) && - executionAttributes.getAttribute(SdkExecutionAttribute.CLIENT_TYPE).equals(clientType) && !IS_FORCE_SKIPPED_VALIDATION.test(executionAttributes); } } \ No newline at end of file diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/io/ChecksumValidatingInputStream.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/io/ChecksumValidatingInputStream.java index 8817408eda9d..f73393619a08 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/io/ChecksumValidatingInputStream.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/io/ChecksumValidatingInputStream.java @@ -18,7 +18,7 @@ import java.io.IOException; import java.io.InputStream; import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.core.checksums.SdkChecksum; +import software.amazon.awssdk.checksums.SdkChecksum; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.http.Abortable; import software.amazon.awssdk.utils.BinaryUtils; diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/util/HttpChecksumResolver.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/util/HttpChecksumResolver.java index c204c7a4fc4e..08281f06f1d6 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/util/HttpChecksumResolver.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/util/HttpChecksumResolver.java @@ -15,10 +15,8 @@ package software.amazon.awssdk.core.internal.util; -import java.util.ArrayList; -import java.util.List; import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.core.checksums.Algorithm; +import software.amazon.awssdk.checksums.DefaultChecksumAlgorithm; import software.amazon.awssdk.core.checksums.ChecksumSpecs; import software.amazon.awssdk.core.interceptor.ExecutionAttributes; import software.amazon.awssdk.core.interceptor.SdkExecutionAttribute; @@ -50,31 +48,19 @@ public static ChecksumSpecs resolveChecksumSpecs(ExecutionAttributes executionAt boolean hasRequestValidation = hasRequestValidationMode(httpChecksumTraitInOperation); String requestAlgorithm = httpChecksumTraitInOperation.requestAlgorithm(); String checksumHeaderName = requestAlgorithm != null ? HttpChecksumUtils.httpChecksumHeader(requestAlgorithm) : null; - List responseValidationAlgorithms = getResponseValidationAlgorithms(httpChecksumTraitInOperation); return ChecksumSpecs.builder() - .algorithm(Algorithm.fromValue(httpChecksumTraitInOperation.requestAlgorithm())) + .algorithmV2(DefaultChecksumAlgorithm.fromValue(requestAlgorithm)) .headerName(checksumHeaderName) - .responseValidationAlgorithms(responseValidationAlgorithms) + .responseValidationAlgorithmsV2(httpChecksumTraitInOperation.responseAlgorithmsV2()) .isValidationEnabled(hasRequestValidation) .isRequestChecksumRequired(httpChecksumTraitInOperation.isRequestChecksumRequired()) .isRequestStreaming(httpChecksumTraitInOperation.isRequestStreaming()) + .requestAlgorithmHeader(httpChecksumTraitInOperation.requestAlgorithmHeader()) .build(); } private static boolean hasRequestValidationMode(HttpChecksum httpChecksum) { return httpChecksum.requestValidationMode() != null; } - - private static List getResponseValidationAlgorithms(HttpChecksum httpChecksumTraitInOperation) { - List responseAlgorithms = httpChecksumTraitInOperation.responseAlgorithms(); - if (responseAlgorithms != null && !responseAlgorithms.isEmpty()) { - List responseValidationAlgorithms = new ArrayList<>(responseAlgorithms.size()); - for (String algorithmName : responseAlgorithms) { - responseValidationAlgorithms.add(Algorithm.fromValue(algorithmName)); - } - return responseValidationAlgorithms; - } - return null; - } } diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/util/HttpChecksumUtils.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/util/HttpChecksumUtils.java index 9316ca3b6377..cb46be59b3c6 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/util/HttpChecksumUtils.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/util/HttpChecksumUtils.java @@ -15,45 +15,92 @@ package software.amazon.awssdk.core.internal.util; +import static software.amazon.awssdk.checksums.DefaultChecksumAlgorithm.CRC32; +import static software.amazon.awssdk.checksums.DefaultChecksumAlgorithm.CRC32C; +import static software.amazon.awssdk.checksums.DefaultChecksumAlgorithm.CRC64NVME; +import static software.amazon.awssdk.checksums.DefaultChecksumAlgorithm.SHA1; +import static software.amazon.awssdk.checksums.DefaultChecksumAlgorithm.SHA256; +import static software.amazon.awssdk.core.HttpChecksumConstant.HEADER_FOR_TRAILER_REFERENCE; +import static software.amazon.awssdk.core.HttpChecksumConstant.HTTP_CHECKSUM_HEADER_PREFIX; import static software.amazon.awssdk.core.HttpChecksumConstant.SIGNING_METHOD; import static software.amazon.awssdk.core.HttpChecksumConstant.X_AMZ_TRAILER; +import static software.amazon.awssdk.core.interceptor.SdkExecutionAttribute.RESOLVED_CHECKSUM_SPECS; import static software.amazon.awssdk.core.internal.util.HttpChecksumResolver.getResolvedChecksumSpecs; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; -import java.util.Objects; import java.util.Optional; import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.checksums.spi.ChecksumAlgorithm; import software.amazon.awssdk.core.ClientType; -import software.amazon.awssdk.core.HttpChecksumConstant; import software.amazon.awssdk.core.checksums.Algorithm; import software.amazon.awssdk.core.checksums.ChecksumSpecs; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; import software.amazon.awssdk.core.checksums.SdkChecksum; import software.amazon.awssdk.core.interceptor.ExecutionAttributes; import software.amazon.awssdk.core.interceptor.SdkExecutionAttribute; +import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute; import software.amazon.awssdk.core.internal.signer.SigningMethod; +import software.amazon.awssdk.http.SdkHttpFullRequest; import software.amazon.awssdk.http.SdkHttpRequest; import software.amazon.awssdk.http.SdkHttpResponse; +import software.amazon.awssdk.utils.ClassLoaderHelper; +import software.amazon.awssdk.utils.ImmutableMap; +import software.amazon.awssdk.utils.Lazy; +import software.amazon.awssdk.utils.Logger; import software.amazon.awssdk.utils.Pair; import software.amazon.awssdk.utils.StringUtils; @SdkInternalApi public final class HttpChecksumUtils { + private static final Logger log = Logger.loggerFor(HttpChecksumUtils.class); private static final int CHECKSUM_BUFFER_SIZE = 16 * 1024; + private static final ImmutableMap NEW_CHECKSUM_TO_LEGACY = ImmutableMap.of( + SHA256, Algorithm.SHA256, + SHA1, Algorithm.SHA1, + CRC32, Algorithm.CRC32, + CRC32C, Algorithm.CRC32C, + CRC64NVME, Algorithm.CRC64NVME + ); + + private static final ImmutableMap LEGACY_CHECKSUM_TO_NEW = ImmutableMap.of( + Algorithm.SHA256, SHA256, + Algorithm.SHA1, SHA1, + Algorithm.CRC32, CRC32, + Algorithm.CRC32C, CRC32C, + Algorithm.CRC64NVME, CRC64NVME + ); + + private static Lazy isCrc64NvmeAvailable = new Lazy<>(() -> { + try { + ClassLoaderHelper.loadClass("software.amazon.awssdk.crt.checksums.CRC64NVME", false); + } catch (ClassNotFoundException e) { + return false; + } + return true; + }); + private HttpChecksumUtils() { } + public static Algorithm toLegacyChecksumAlgorithm(ChecksumAlgorithm checksumAlgorithm) { + return NEW_CHECKSUM_TO_LEGACY.get(checksumAlgorithm); + } + + public static ChecksumAlgorithm toNewChecksumAlgorithm(Algorithm checksumAlgorithm) { + return LEGACY_CHECKSUM_TO_NEW.get(checksumAlgorithm); + } + /** * @param algorithmName Checksum Algorithm Name * @return Http Checksum header for a given Algorithm. */ public static String httpChecksumHeader(String algorithmName) { - return String.format("%s-%s", HttpChecksumConstant.HTTP_CHECKSUM_HEADER_PREFIX, - StringUtils.lowerCase(algorithmName)); + return HTTP_CHECKSUM_HEADER_PREFIX + "-" + StringUtils.lowerCase(algorithmName); } /** @@ -163,6 +210,64 @@ public static boolean isMd5ChecksumRequired(ExecutionAttributes executionAttribu } + public static boolean hasLegacyChecksumRequiredTrait(ExecutionAttributes executionAttributes) { + return executionAttributes.getAttribute(SdkInternalExecutionAttribute.HTTP_CHECKSUM_REQUIRED) != null; + } + + /** + * HTTP checksum calculation is needed if one of the following conditions is met: + * 1. checksum is required per legacy httpRequired trait or the new HttpChecksum trait OR + * 2. user has specified a checksum algorithm OR + * 3. checksum is optional per new HttpChecksum trait AND RequestChecksumCalculation == when_supported + * + * HTTP checksum calculation is not needed if one of the following conditions is met: + * 1. the operation does not have legacy httpRequired trait or the new HttpChecksum trait OR + * 2. user has provided a checksum value (any header prefixed with "x-amz-checksum-") OR + * 3. checksum is not required AND RequestChecksumCalculation == when_required + */ + public static boolean isHttpChecksumCalculationNeeded(SdkHttpFullRequest.Builder request, + ExecutionAttributes executionAttributes) { + + ChecksumSpecs checksumSpecs = executionAttributes.getAttribute(RESOLVED_CHECKSUM_SPECS); + boolean hasFlexibleChecksumTrait = checksumSpecs != null; + + if (!hasLegacyChecksumRequiredTrait(executionAttributes) && !hasFlexibleChecksumTrait) { + return false; + } + + if (requestAlreadyHasChecksum(request)) { + return false; + } + + boolean checksumAlgorithmSpecified = + hasFlexibleChecksumTrait && checksumSpecs.algorithmV2() != null; + + if (checksumAlgorithmSpecified) { + return true; + } + + boolean isHttpChecksumRequired = + hasLegacyChecksumRequiredTrait(executionAttributes) || + hasFlexibleChecksumTrait && checksumSpecs.isRequestChecksumRequired(); + + if (isHttpChecksumRequired) { + return true; + } + + RequestChecksumCalculation requestChecksumCalculation = + executionAttributes.getAttribute(SdkInternalExecutionAttribute.REQUEST_CHECKSUM_CALCULATION); + + return requestChecksumCalculation == RequestChecksumCalculation.WHEN_SUPPORTED; + } + + private static boolean requestAlreadyHasChecksum(SdkHttpFullRequest.Builder request) { + if (request.firstMatchingHeader(HEADER_FOR_TRAILER_REFERENCE).isPresent()) { + return true; + } + + return request.anyMatchingHeader(k -> k.startsWith(HTTP_CHECKSUM_HEADER_PREFIX)); + } + private static boolean isTrailerChecksumPresent(SdkHttpRequest sdkHttpRequest, ChecksumSpecs checksumSpec) { Optional trailerBasedChecksum = sdkHttpRequest.firstMatchingHeader(X_AMZ_TRAILER); if (trailerBasedChecksum.isPresent()) { @@ -209,18 +314,27 @@ public static boolean isTrailerBasedChecksumForClientType( } /** - * Loops through the Supported list of checksum for the operation, and gets the Header value for the checksum header. + * Loops through the supported list of checksum for the operation, and gets the header value for the checksum header. * @param sdkHttpResponse response from service. * @param resolvedChecksumSpecs Resolved checksum specification for the operation. * @return Algorithm and its corresponding checksum value as sent by the service. */ - public static Pair getAlgorithmChecksumValuePair(SdkHttpResponse sdkHttpResponse, - ChecksumSpecs resolvedChecksumSpecs) { - return resolvedChecksumSpecs.responseValidationAlgorithms().stream().map( - algorithm -> { - Optional firstMatchingHeader = sdkHttpResponse.firstMatchingHeader(httpChecksumHeader(algorithm.name())); - return firstMatchingHeader.map(s -> Pair.of(algorithm, s)).orElse(null); - }).filter(Objects::nonNull).findFirst().orElse(null); + public static Pair getAlgorithmChecksumValuePair(SdkHttpResponse sdkHttpResponse, + ChecksumSpecs resolvedChecksumSpecs) { + for (ChecksumAlgorithm checksumAlgorithm : resolvedChecksumSpecs.responseValidationAlgorithmsV2()) { + Optional firstMatchingHeader = + sdkHttpResponse.firstMatchingHeader(httpChecksumHeader(checksumAlgorithm.algorithmId())); + + if (firstMatchingHeader.isPresent()) { + if (checksumAlgorithm.equals(CRC64NVME) && !isCrc64NvmeAvailable.getValue()) { + log.debug(() -> "Skip CRC64NVME checksum validation because CRT is not on the classpath and CRC64NVME is " + + "not available"); + continue; + } + return Pair.of(checksumAlgorithm, firstMatchingHeader.get()); + } + } + return null; } /** diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/async/ChecksumCalculatingAsyncRequestBodyTckTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/async/ChecksumCalculatingAsyncRequestBodyTckTest.java index 0671abefc31e..3a3fed322c82 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/async/ChecksumCalculatingAsyncRequestBodyTckTest.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/async/ChecksumCalculatingAsyncRequestBodyTckTest.java @@ -1,5 +1,7 @@ package software.amazon.awssdk.core.async; +import com.google.common.jimfs.Configuration; +import com.google.common.jimfs.Jimfs; import java.io.IOException; import java.io.OutputStream; import java.io.UncheckedIOException; @@ -7,12 +9,10 @@ import java.nio.file.FileSystem; import java.nio.file.Files; import java.nio.file.Path; -import com.google.common.jimfs.Configuration; -import com.google.common.jimfs.Jimfs; import org.reactivestreams.Publisher; import org.reactivestreams.tck.PublisherVerification; import org.reactivestreams.tck.TestEnvironment; -import software.amazon.awssdk.core.checksums.Algorithm; +import software.amazon.awssdk.checksums.DefaultChecksumAlgorithm; import software.amazon.awssdk.core.internal.async.ChecksumCalculatingAsyncRequestBody; public class ChecksumCalculatingAsyncRequestBodyTckTest extends PublisherVerification { @@ -36,7 +36,7 @@ public long maxElementsFromPublisher() { public Publisher createPublisher(long n) { return ChecksumCalculatingAsyncRequestBody.builder() .asyncRequestBody(AsyncRequestBody.fromFile(fileOfNChunks(n))) - .algorithm(Algorithm.CRC32) + .algorithm(DefaultChecksumAlgorithm.CRC32) .trailerHeader("x-amz-checksum-crc32") .build(); } diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/async/ChecksumValidatingPublisherTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/async/ChecksumValidatingPublisherTest.java index 2a80f166a789..959bf277326e 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/async/ChecksumValidatingPublisherTest.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/async/ChecksumValidatingPublisherTest.java @@ -20,8 +20,9 @@ import org.reactivestreams.Publisher; import org.reactivestreams.Subscriber; import org.reactivestreams.Subscription; -import software.amazon.awssdk.core.checksums.Algorithm; -import software.amazon.awssdk.core.checksums.SdkChecksum; +import software.amazon.awssdk.checksums.DefaultChecksumAlgorithm; +import software.amazon.awssdk.checksums.SdkChecksum; +import software.amazon.awssdk.checksums.spi.ChecksumAlgorithm; import software.amazon.awssdk.core.internal.async.ChecksumValidatingPublisher; import java.nio.ByteBuffer; @@ -49,7 +50,8 @@ public void testSinglePacket() { final TestPublisher driver = new TestPublisher(); final TestSubscriber s = new TestSubscriber(Arrays.copyOfRange(testData, 0, testData.length)); final ChecksumValidatingPublisher p = new ChecksumValidatingPublisher(driver, - SdkChecksum.forAlgorithm(Algorithm.SHA256), SHA256_OF_HELLO_WORLD); + SdkChecksum.forAlgorithm(DefaultChecksumAlgorithm.SHA256), + SHA256_OF_HELLO_WORLD); p.subscribe(s); driver.doOnNext(ByteBuffer.wrap(testData)); @@ -64,7 +66,7 @@ public void testTwoPackets() { for (int i = 1; i < testData.length - 1; i++) { final TestPublisher driver = new TestPublisher(); final TestSubscriber s = new TestSubscriber(Arrays.copyOfRange(testData, 0, testData.length)); - final ChecksumValidatingPublisher p = new ChecksumValidatingPublisher(driver, SdkChecksum.forAlgorithm(Algorithm.SHA256), SHA256_OF_HELLO_WORLD); + final ChecksumValidatingPublisher p = new ChecksumValidatingPublisher(driver, SdkChecksum.forAlgorithm(DefaultChecksumAlgorithm.SHA256), SHA256_OF_HELLO_WORLD); p.subscribe(s); driver.doOnNext(ByteBuffer.wrap(testData, 0, i)); @@ -81,7 +83,7 @@ public void testTinyPackets() { for (int packetSize = 1; packetSize < 2; packetSize++) { final TestPublisher driver = new TestPublisher(); final TestSubscriber s = new TestSubscriber(Arrays.copyOfRange(testData, 0, testData.length)); - final ChecksumValidatingPublisher p = new ChecksumValidatingPublisher(driver, SdkChecksum.forAlgorithm(Algorithm.SHA256), + final ChecksumValidatingPublisher p = new ChecksumValidatingPublisher(driver, SdkChecksum.forAlgorithm(DefaultChecksumAlgorithm.SHA256), SHA256_OF_HELLO_WORLD); p.subscribe(s); int currOffset = 0; @@ -100,7 +102,7 @@ public void testTinyPackets() { public void testUnknownLength() { final TestPublisher driver = new TestPublisher(); final TestSubscriber s = new TestSubscriber(Arrays.copyOfRange(testData, 0, testData.length)); - final ChecksumValidatingPublisher p = new ChecksumValidatingPublisher(driver, SdkChecksum.forAlgorithm(Algorithm.SHA256), SHA256_OF_HELLO_WORLD); + final ChecksumValidatingPublisher p = new ChecksumValidatingPublisher(driver, SdkChecksum.forAlgorithm(DefaultChecksumAlgorithm.SHA256), SHA256_OF_HELLO_WORLD); p.subscribe(s); byte[] randomChecksumData = new byte[testData.length]; System.arraycopy(testData, 0, randomChecksumData, 0, testData.length); @@ -117,7 +119,7 @@ public void testUnknownLength() { public void checksumValidationFailure_throwsSdkClientException() { final TestPublisher driver = new TestPublisher(); final TestSubscriber s = new TestSubscriber(Arrays.copyOfRange(testData, 0, testData.length)); - final ChecksumValidatingPublisher p = new ChecksumValidatingPublisher(driver, SdkChecksum.forAlgorithm(Algorithm.SHA256), + final ChecksumValidatingPublisher p = new ChecksumValidatingPublisher(driver, SdkChecksum.forAlgorithm(DefaultChecksumAlgorithm.SHA256), "someInvalidData"); p.subscribe(s); driver.doOnNext(ByteBuffer.wrap(testData)); diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/async/ChunkBufferTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/async/ChunkBufferTest.java index 136c28695511..d0c194360f36 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/async/ChunkBufferTest.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/async/ChunkBufferTest.java @@ -23,6 +23,7 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collection; +import java.util.List; import java.util.Optional; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; @@ -41,6 +42,44 @@ class ChunkBufferTest { + @Test + void totalBytesSmallerThanInput_OneChunk_shouldLimitLastChunkToTotalBytes() { + int chunkSize = 1024; + int totalBytes = 16; + int inputBufferSize = 64; + ChunkBuffer chunkBuffer = ChunkBuffer.builder() + .totalBytes(totalBytes) + .bufferSize(chunkSize) + .build(); + + String inputString = RandomStringUtils.randomAscii(inputBufferSize); + ByteBuffer inputBuffer = ByteBuffer.wrap(inputString.getBytes()); + List buffers = (List) chunkBuffer.split(inputBuffer); + assertThat(buffers).hasSize(1); + ByteBuffer buff = buffers.get(0); + assertThat(buff).isEqualByComparingTo(ByteBuffer.wrap(inputString.substring(0, totalBytes).getBytes())); + } + + @Test + void totalBytesLessThanInput_MoreThanOneChunk_shouldLimitLastChunkToTotalBytes() { + int chunkSize = 20; + int totalBytes = 50; + int inputBufferSize = 70; + + // we should split the input into 20-20-10 + ChunkBuffer chunkBuffer = ChunkBuffer.builder() + .bufferSize(chunkSize) + .totalBytes(totalBytes) + .build(); + String inputString = RandomStringUtils.randomAscii(inputBufferSize); + ByteBuffer inputBuffer = ByteBuffer.wrap(inputString.getBytes()); + List buffers = (List) chunkBuffer.split(inputBuffer); + assertThat(buffers).hasSize(3); + assertThat(buffers.get(0).remaining()).isEqualTo(20); + assertThat(buffers.get(1).remaining()).isEqualTo(20); + assertThat(buffers.get(2).remaining()).isEqualTo(10); + } + @ParameterizedTest @ValueSource(ints = {1, 6, 10, 23, 25}) void numberOfChunk_Not_MultipleOfTotalBytes_KnownLength(int totalBytes) { @@ -281,4 +320,33 @@ void concurrentTreads_calling_bufferAndCreateChunks_knownLength() throws Executi assertThat(remainderBytesBuffers.get()).isOne(); assertThat(otherSizeBuffers.get()).isZero(); } + + @Test + void doesNotOverflow_whenInputBufferRemainingBytesPlusPositionExceedTotalBytes() { + int inputBufferSize = 2000; + int totalBytes = 500; + int chunkSize = 128; + int troublePosition = 127; + + ChunkBuffer chunkBuffer = ChunkBuffer.builder() + .totalBytes(totalBytes) + .bufferSize(chunkSize) + .build(); + + String inputString = RandomStringUtils.randomAscii(inputBufferSize); + ByteBuffer inputBuffer = ByteBuffer.wrap(inputString.getBytes()); + inputBuffer.position(troublePosition); + Iterable buffers = chunkBuffer.split(inputBuffer); + + AtomicInteger total = new AtomicInteger(0); + buffers.forEach(b -> total.addAndGet(b.remaining())); + assertThat(total.get()).isEqualTo(totalBytes); + + ByteBuffer actualFullBuffer = ByteBuffer.allocate(totalBytes); + buffers.forEach(actualFullBuffer::put); + actualFullBuffer.position(0); + assertThat(actualFullBuffer).isEqualByComparingTo( + ByteBuffer.wrap(inputString.substring(troublePosition, troublePosition + totalBytes).getBytes()) + ); + } } diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/async/ChecksumCalculatingAsyncRequestBodyTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/async/ChecksumCalculatingAsyncRequestBodyTest.java index 29857d059192..b0137206ad33 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/async/ChecksumCalculatingAsyncRequestBodyTest.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/async/ChecksumCalculatingAsyncRequestBodyTest.java @@ -39,6 +39,7 @@ import org.reactivestreams.Publisher; import org.reactivestreams.Subscriber; import org.reactivestreams.Subscription; +import software.amazon.awssdk.checksums.DefaultChecksumAlgorithm; import software.amazon.awssdk.core.async.AsyncRequestBody; import software.amazon.awssdk.core.checksums.Algorithm; import software.amazon.awssdk.core.internal.util.Mimetype; @@ -108,7 +109,7 @@ private static Stream publishers() { private static ChecksumCalculatingAsyncRequestBody checksumPublisher(AsyncRequestBody sourcePublisher) { return ChecksumCalculatingAsyncRequestBody.builder() .asyncRequestBody(sourcePublisher) - .algorithm(Algorithm.CRC32) + .algorithm(DefaultChecksumAlgorithm.CRC32) .trailerHeader("x-amz-checksum-crc32").build(); } @@ -167,7 +168,7 @@ public void onComplete() { public void constructor_asyncRequestBodyFromString_hasCorrectContentType() { AsyncRequestBody requestBody = ChecksumCalculatingAsyncRequestBody.builder() .asyncRequestBody(AsyncRequestBody.fromString("Hello world")) - .algorithm(Algorithm.CRC32) + .algorithm(DefaultChecksumAlgorithm.CRC32) .trailerHeader("x-amz-checksum-crc32") .build(); assertThat(requestBody.contentType()).startsWith(Mimetype.MIMETYPE_TEXT_PLAIN); @@ -177,7 +178,7 @@ public void constructor_asyncRequestBodyFromString_hasCorrectContentType() { public void constructor_asyncRequestBodyFromFile_hasCorrectContentType() { AsyncRequestBody requestBody = ChecksumCalculatingAsyncRequestBody.builder() .asyncRequestBody(AsyncRequestBody.fromFile(path)) - .algorithm(Algorithm.CRC32) + .algorithm(DefaultChecksumAlgorithm.CRC32) .trailerHeader("x-amz-checksum-crc32") .build(); assertThat(requestBody.contentType()).isEqualTo(Mimetype.MIMETYPE_OCTET_STREAM); @@ -187,7 +188,7 @@ public void constructor_asyncRequestBodyFromFile_hasCorrectContentType() { public void constructor_asyncRequestBodyFromBytes_hasCorrectContentType() { AsyncRequestBody requestBody = ChecksumCalculatingAsyncRequestBody.builder() .asyncRequestBody(AsyncRequestBody.fromBytes("hello world".getBytes())) - .algorithm(Algorithm.CRC32) + .algorithm(DefaultChecksumAlgorithm.CRC32) .trailerHeader("x-amz-checksum-crc32") .build(); assertThat(requestBody.contentType()).isEqualTo(Mimetype.MIMETYPE_OCTET_STREAM); @@ -198,7 +199,7 @@ public void constructor_asyncRequestBodyFromByteBuffer_hasCorrectContentType() { ByteBuffer byteBuffer = ByteBuffer.wrap("hello world".getBytes()); AsyncRequestBody requestBody = ChecksumCalculatingAsyncRequestBody.builder() .asyncRequestBody(AsyncRequestBody.fromByteBuffer(byteBuffer)) - .algorithm(Algorithm.CRC32) + .algorithm(DefaultChecksumAlgorithm.CRC32) .trailerHeader("x-amz-checksum-crc32") .build(); assertThat(requestBody.contentType()).isEqualTo(Mimetype.MIMETYPE_OCTET_STREAM); @@ -208,7 +209,7 @@ public void constructor_asyncRequestBodyFromByteBuffer_hasCorrectContentType() { public void constructor_asyncRequestBodyFromEmpty_hasCorrectContentType() { AsyncRequestBody requestBody = ChecksumCalculatingAsyncRequestBody.builder() .asyncRequestBody(AsyncRequestBody.empty()) - .algorithm(Algorithm.CRC32) + .algorithm(DefaultChecksumAlgorithm.CRC32) .trailerHeader("x-amz-checksum-crc32") .build(); assertThat(requestBody.contentType()).isEqualTo(Mimetype.MIMETYPE_OCTET_STREAM); @@ -224,7 +225,7 @@ public void constructor_asyncRequestBodyFromPublisher_NoContentLength_throwsExce ChecksumCalculatingAsyncRequestBody.Builder builder = ChecksumCalculatingAsyncRequestBody.builder() .asyncRequestBody(AsyncRequestBody.fromPublisher(bodyPublisher)) - .algorithm(Algorithm.SHA1) + .algorithm(DefaultChecksumAlgorithm.SHA1) .trailerHeader("x-amz-checksum-sha1"); assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> builder.build()); @@ -243,7 +244,7 @@ public void constructor_checksumIsNull_throwsException() { public void constructor_asyncRequestBodyIsNull_throwsException() { assertThatExceptionOfType(NullPointerException.class).isThrownBy( () -> ChecksumCalculatingAsyncRequestBody.builder() - .algorithm(Algorithm.CRC32) + .algorithm(DefaultChecksumAlgorithm.CRC32) .trailerHeader("x-amzn-checksum-crc32") .build()).withMessage("wrapped AsyncRequestBody cannot be null"); } @@ -252,7 +253,7 @@ public void constructor_asyncRequestBodyIsNull_throwsException() { public void constructor_trailerHeaderIsNull_throwsException() { assertThatExceptionOfType(NullPointerException.class).isThrownBy( () -> ChecksumCalculatingAsyncRequestBody.builder() - .algorithm(Algorithm.CRC32) + .algorithm(DefaultChecksumAlgorithm.CRC32) .asyncRequestBody(AsyncRequestBody.fromString("Hello world")) .build()).withMessage("trailerHeader cannot be null"); @@ -270,7 +271,7 @@ public void fromBytes_byteArrayNotNullChecksumSupplied() { System.arraycopy(original, 0, toModify, 0, original.length); AsyncRequestBody body = ChecksumCalculatingAsyncRequestBody.builder() .asyncRequestBody(AsyncRequestBody.fromBytes(toModify)) - .algorithm(Algorithm.CRC32) + .algorithm(DefaultChecksumAlgorithm.CRC32) .trailerHeader("x-amzn-checksum-crc32") .build(); for (int i = 0; i < toModify.length; ++i) { diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/checksum/CrtBasedChecksumTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/checksums/CrtBasedChecksumTest.java similarity index 95% rename from core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/checksum/CrtBasedChecksumTest.java rename to core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/checksums/CrtBasedChecksumTest.java index f46b5d2a9b4d..ba2e8315a4ed 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/checksum/CrtBasedChecksumTest.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/checksums/CrtBasedChecksumTest.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.core.internal.checksum; +package software.amazon.awssdk.core.internal.checksums; import static org.assertj.core.api.Assertions.assertThat; diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/checksums/RequestChecksumCalculationResolverTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/checksums/RequestChecksumCalculationResolverTest.java new file mode 100644 index 000000000000..a25b0b3d185c --- /dev/null +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/checksums/RequestChecksumCalculationResolverTest.java @@ -0,0 +1,134 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.core.internal.checksums; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static software.amazon.awssdk.core.checksums.RequestChecksumCalculation.WHEN_REQUIRED; +import static software.amazon.awssdk.core.checksums.RequestChecksumCalculation.WHEN_SUPPORTED; + +import java.util.Arrays; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; +import software.amazon.awssdk.core.SdkSystemSetting; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculationResolver; +import software.amazon.awssdk.profiles.ProfileFile; +import software.amazon.awssdk.profiles.ProfileProperty; +import software.amazon.awssdk.testutils.EnvironmentVariableHelper; +import software.amazon.awssdk.utils.Pair; +import software.amazon.awssdk.utils.StringInputStream; + +public class RequestChecksumCalculationResolverTest { + private static final EnvironmentVariableHelper ENVIRONMENT_VARIABLE_HELPER = new EnvironmentVariableHelper(); + private static final String PROFILE = "test"; + + @BeforeEach + public void methodSetup() { + ENVIRONMENT_VARIABLE_HELPER.reset(); + System.clearProperty(SdkSystemSetting.AWS_REQUEST_CHECKSUM_CALCULATION.property()); + } + + @ParameterizedTest(name = "{index} - EXPECTED:{3} (sys:{0}, env:{1}, cfg:{2})") + @MethodSource("configValues") + void resolveChecksumCalculation_whenValidValues_resolvesCorrectly( + String systemProperty, String envVar, ProfileFile profileFile, RequestChecksumCalculation expected) { + + setUpSystemSettings(systemProperty, envVar); + + RequestChecksumCalculationResolver resolver = RequestChecksumCalculationResolver.create() + .profileFile(() -> profileFile) + .profileName(PROFILE); + assertThat(resolver.resolve()).isEqualTo(expected); + } + + private static Stream configValues() { + ProfileFile emptyProfile = configFile("profile test", Pair.of("foo", "bar")); + + Function testProfileConfig = + s -> configFile("profile test", Pair.of(ProfileProperty.REQUEST_CHECKSUM_CALCULATION, s)); + + return Stream.of( + Arguments.of(null, null, emptyProfile, WHEN_SUPPORTED), + Arguments.of("when_supported", null, null, WHEN_SUPPORTED), + Arguments.of("when_required", null, null, WHEN_REQUIRED), + Arguments.of(null, "when_supported", null, WHEN_SUPPORTED), + Arguments.of(null, "when_required", null, WHEN_REQUIRED), + Arguments.of(null, "when_required", testProfileConfig.apply("when_supported"), WHEN_REQUIRED), + Arguments.of(null, null, testProfileConfig.apply("when_supported"), WHEN_SUPPORTED), + Arguments.of(null, null, testProfileConfig.apply("when_required"), WHEN_REQUIRED), + Arguments.of(null, null, configFile("profile test", Pair.of("bar", "baz")), WHEN_SUPPORTED), + Arguments.of(null, null, configFile("profile foo", Pair.of(ProfileProperty.REQUEST_CHECKSUM_CALCULATION, "when_required")), + WHEN_SUPPORTED) + ); + } + + @ParameterizedTest(name = "{index} - sys:{0}, env:{1}, cfg:{2}") + @MethodSource("invalidConfigValues") + void resolveChecksumCalculation_whenInvalidConfig_throws( + String systemProperty, String envVar, ProfileFile profileFile) { + + setUpSystemSettings(systemProperty, envVar); + + RequestChecksumCalculationResolver resolver = RequestChecksumCalculationResolver.create() + .profileFile(() -> profileFile) + .profileName(PROFILE); + assertThatThrownBy(resolver::resolve).isInstanceOf(IllegalArgumentException.class); + } + + private static Stream invalidConfigValues() { + Function testProfileConfig = + s -> configFile("profile test", Pair.of(ProfileProperty.REQUEST_CHECKSUM_CALCULATION, s)); + + return Stream.of( + Arguments.of("foo", null, null), + Arguments.of(null, "foo", null), + Arguments.of(null, null, testProfileConfig.apply("foo")) + ); + } + + private static void setUpSystemSettings(String systemProperty, String envVar) { + if (systemProperty != null) { + System.setProperty(SdkSystemSetting.AWS_REQUEST_CHECKSUM_CALCULATION.property(), systemProperty); + + } + if (envVar != null) { + ENVIRONMENT_VARIABLE_HELPER.set(SdkSystemSetting.AWS_REQUEST_CHECKSUM_CALCULATION.environmentVariable(), + envVar); + } + } + + private static ProfileFile configFile(String name, Pair... pairs) { + String values = Arrays.stream(pairs) + .map(pair -> String.format("%s=%s", pair.left(), pair.right())) + .collect(Collectors.joining(System.lineSeparator())); + String contents = String.format("[%s]\n%s", name, values); + + return configFile(contents); + } + + private static ProfileFile configFile(String credentialFile) { + return ProfileFile.builder() + .content(new StringInputStream(credentialFile)) + .type(ProfileFile.Type.CONFIGURATION) + .build(); + } +} diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/checksums/ResponseChecksumValidationResolverTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/checksums/ResponseChecksumValidationResolverTest.java new file mode 100644 index 000000000000..9bed17ceb469 --- /dev/null +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/checksums/ResponseChecksumValidationResolverTest.java @@ -0,0 +1,134 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.core.internal.checksums; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static software.amazon.awssdk.core.checksums.ResponseChecksumValidation.WHEN_REQUIRED; +import static software.amazon.awssdk.core.checksums.ResponseChecksumValidation.WHEN_SUPPORTED; + +import java.util.Arrays; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import software.amazon.awssdk.core.SdkSystemSetting; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidation; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidationResolver; +import software.amazon.awssdk.profiles.ProfileFile; +import software.amazon.awssdk.profiles.ProfileProperty; +import software.amazon.awssdk.testutils.EnvironmentVariableHelper; +import software.amazon.awssdk.utils.Pair; +import software.amazon.awssdk.utils.StringInputStream; + +public class ResponseChecksumValidationResolverTest { + private static final EnvironmentVariableHelper ENVIRONMENT_VARIABLE_HELPER = new EnvironmentVariableHelper(); + private static final String PROFILE = "test"; + + @BeforeEach + public void methodSetup() { + ENVIRONMENT_VARIABLE_HELPER.reset(); + System.clearProperty(SdkSystemSetting.AWS_RESPONSE_CHECKSUM_VALIDATION.property()); + } + + @ParameterizedTest(name = "{index} - EXPECTED:{3} (sys:{0}, env:{1}, cfg:{2})") + @MethodSource("configValues") + void resolveChecksumValidation_whenValidValues_resolvesCorrectly( + String systemProperty, String envVar, ProfileFile profileFile, ResponseChecksumValidation expected) { + + setUpSystemSettings(systemProperty, envVar); + + ResponseChecksumValidationResolver resolver = ResponseChecksumValidationResolver.create() + .profileFile(() -> profileFile) + .profileName(PROFILE); + assertThat(resolver.resolve()).isEqualTo(expected); + } + + private static Stream configValues() { + ProfileFile emptyProfile = configFile("profile test", Pair.of("foo", "bar")); + + Function testProfileConfig = + s -> configFile("profile test", Pair.of(ProfileProperty.RESPONSE_CHECKSUM_VALIDATION, s)); + + return Stream.of( + Arguments.of(null, null, emptyProfile, WHEN_SUPPORTED), + Arguments.of("when_supported", null, null, WHEN_SUPPORTED), + Arguments.of("when_required", null, null, WHEN_REQUIRED), + Arguments.of(null, "when_supported", null, WHEN_SUPPORTED), + Arguments.of(null, "when_required", null, WHEN_REQUIRED), + Arguments.of(null, "when_required", testProfileConfig.apply("when_supported"), WHEN_REQUIRED), + Arguments.of(null, null, testProfileConfig.apply("when_supported"), WHEN_SUPPORTED), + Arguments.of(null, null, testProfileConfig.apply("when_required"), WHEN_REQUIRED), + Arguments.of(null, null, configFile("profile test", Pair.of("bar", "baz")), WHEN_SUPPORTED), + Arguments.of(null, null, configFile("profile foo", Pair.of(ProfileProperty.RESPONSE_CHECKSUM_VALIDATION, "when_required")), + WHEN_SUPPORTED) + ); + } + + @ParameterizedTest(name = "{index} - sys:{0}, env:{1}, cfg:{2}") + @MethodSource("invalidConfigValues") + void resolveChecksumValidation_whenInvalidConfig_throws( + String systemProperty, String envVar, ProfileFile profileFile) { + + setUpSystemSettings(systemProperty, envVar); + + ResponseChecksumValidationResolver resolver = ResponseChecksumValidationResolver.create() + .profileFile(() -> profileFile) + .profileName(PROFILE); + assertThatThrownBy(resolver::resolve).isInstanceOf(IllegalArgumentException.class); + } + + private static Stream invalidConfigValues() { + Function testProfileConfig = + s -> configFile("profile test", Pair.of(ProfileProperty.RESPONSE_CHECKSUM_VALIDATION, s)); + + return Stream.of( + Arguments.of("foo", null, null), + Arguments.of(null, "foo", null), + Arguments.of(null, null, testProfileConfig.apply("foo")) + ); + } + + private static void setUpSystemSettings(String systemProperty, String envVar) { + if (systemProperty != null) { + System.setProperty(SdkSystemSetting.AWS_RESPONSE_CHECKSUM_VALIDATION.property(), systemProperty); + + } + if (envVar != null) { + ENVIRONMENT_VARIABLE_HELPER.set(SdkSystemSetting.AWS_RESPONSE_CHECKSUM_VALIDATION.environmentVariable(), + envVar); + } + } + + private static ProfileFile configFile(String name, Pair... pairs) { + String values = Arrays.stream(pairs) + .map(pair -> String.format("%s=%s", pair.left(), pair.right())) + .collect(Collectors.joining(System.lineSeparator())); + String contents = String.format("[%s]\n%s", name, values); + + return configFile(contents); + } + + private static ProfileFile configFile(String credentialFile) { + return ProfileFile.builder() + .content(new StringInputStream(credentialFile)) + .type(ProfileFile.Type.CONFIGURATION) + .build(); + } +} diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/AsyncRetryableStageAdaptiveModeTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/AsyncRetryableStageAdaptiveModeTest.java deleted file mode 100644 index cf40f145a42e..000000000000 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/AsyncRetryableStageAdaptiveModeTest.java +++ /dev/null @@ -1,321 +0,0 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -package software.amazon.awssdk.core.internal.http.pipeline.stages; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyDouble; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import java.time.Duration; -import java.util.OptionalDouble; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.Spy; -import org.mockito.junit.MockitoJUnitRunner; -import org.mockito.stubbing.Answer; -import software.amazon.awssdk.core.Response; -import software.amazon.awssdk.core.client.config.SdkClientConfiguration; -import software.amazon.awssdk.core.client.config.SdkClientOption; -import software.amazon.awssdk.core.exception.SdkClientException; -import software.amazon.awssdk.core.exception.SdkException; -import software.amazon.awssdk.core.exception.SdkServiceException; -import software.amazon.awssdk.core.http.ExecutionContext; -import software.amazon.awssdk.core.http.NoopTestRequest; -import software.amazon.awssdk.core.interceptor.ExecutionAttributes; -import software.amazon.awssdk.core.internal.http.HttpClientDependencies; -import software.amazon.awssdk.core.internal.http.RequestExecutionContext; -import software.amazon.awssdk.core.internal.http.pipeline.RequestPipeline; -import software.amazon.awssdk.core.internal.retry.RateLimitingTokenBucket; -import software.amazon.awssdk.core.retry.RetryMode; -import software.amazon.awssdk.core.retry.RetryPolicy; -import software.amazon.awssdk.http.HttpStatusCode; -import software.amazon.awssdk.http.SdkHttpFullRequest; -import software.amazon.awssdk.http.SdkHttpMethod; -import software.amazon.awssdk.metrics.NoOpMetricCollector; -import software.amazon.awssdk.utils.CompletableFutureUtils; - -@RunWith(MockitoJUnitRunner.class) -public class AsyncRetryableStageAdaptiveModeTest { - @Spy - private RateLimitingTokenBucket tokenBucket; - private AsyncRetryableStage retryableStage; - - @Mock - private RequestPipeline>> mockChildPipeline; - - @Mock - private ScheduledExecutorService scheduledExecutorService; - - @Before - public void setup() throws Exception { - when(scheduledExecutorService.schedule(any(Runnable.class), anyLong(), any(TimeUnit.class))) - .thenAnswer((Answer>) invocationOnMock -> { - Runnable runnable = invocationOnMock.getArgument(0, Runnable.class); - runnable.run(); - return null; - }); - } - - @Test - public void execute_acquiresToken() throws Exception { - retryableStage = createStage(false); - mockChildResponse(createSuccessResponse()); - retryableStage.execute(createHttpRequest(), createExecutionContext()).join(); - - verify(tokenBucket).acquireNonBlocking(1.0, false); - } - - @Test - public void execute_acquireReturnsNonZeroValue_waitsForGivenTime() throws Exception { - retryableStage = createStage(false); - mockChildResponse(createSuccessResponse()); - - Duration waitTime = Duration.ofSeconds(3); - when(tokenBucket.acquireNonBlocking(anyDouble(), anyBoolean())).thenReturn(OptionalDouble.of(waitTime.getSeconds())); - - retryableStage.execute(createHttpRequest(), createExecutionContext()).join(); - - verify(scheduledExecutorService).schedule(any(Runnable.class), eq(waitTime.toMillis()), eq(TimeUnit.MILLISECONDS)); - } - - @Test - public void execute_fastFailEnabled_propagatesSettingToBucket() throws Exception { - retryableStage = createStage(true); - mockChildResponse(createSuccessResponse()); - retryableStage.execute(createHttpRequest(), createExecutionContext()).join(); - - verify(tokenBucket).acquireNonBlocking(1.0, true); - } - - @Test - public void execute_retryModeStandard_doesNotAcquireToken() throws Exception { - RetryPolicy retryPolicy = RetryPolicy.builder(RetryMode.STANDARD).build(); - mockChildResponse(createSuccessResponse()); - retryableStage = createStage(retryPolicy); - retryableStage.execute(createHttpRequest(), createExecutionContext()).join(); - - verifyNoMoreInteractions(tokenBucket); - } - - @Test - public void execute_retryModeLegacy_doesNotAcquireToken() throws Exception { - RetryPolicy retryPolicy = RetryPolicy.builder(RetryMode.LEGACY).build(); - mockChildResponse(createSuccessResponse()); - retryableStage = createStage(retryPolicy); - retryableStage.execute(createHttpRequest(), createExecutionContext()).join(); - - verifyNoMoreInteractions(tokenBucket); - } - - @Test - public void execute_acquireReturnsFalse_throws() throws Exception { - when(tokenBucket.acquireNonBlocking(anyDouble(), anyBoolean())).thenReturn(OptionalDouble.empty()); - retryableStage = createStage(false); - - SdkHttpFullRequest httpRequest = createHttpRequest(); - RequestExecutionContext executionContext = createExecutionContext(); - assertThatThrownBy(() -> retryableStage.execute(httpRequest, executionContext).join()) - .hasCauseInstanceOf(SdkClientException.class) - .hasMessageContaining("Unable to acquire a send token"); - } - @Test - public void execute_responseSuccessful_updatesWithThrottlingFalse() throws Exception { - retryableStage = createStage(false); - mockChildResponse(createSuccessResponse()); - retryableStage.execute(createHttpRequest(), createExecutionContext()); - - verify(tokenBucket).updateClientSendingRate(false); - verify(tokenBucket, never()).updateClientSendingRate(true); - } - - @Test - public void execute_nonThrottlingServiceException_doesNotUpdateRate() throws Exception { - SdkServiceException exception = SdkServiceException.builder() - .statusCode(500) - .build(); - mockChildResponse(exception); - retryableStage = createStage(false); - - SdkHttpFullRequest httpRequest = createHttpRequest(); - RequestExecutionContext executionContext = createExecutionContext(); - assertThatThrownBy(() -> retryableStage.execute(httpRequest, executionContext).join()) - .hasCauseInstanceOf(SdkServiceException.class); - - verify(tokenBucket, never()).updateClientSendingRate(anyBoolean()); - } - - @Test - public void execute_throttlingServiceException_updatesRate() throws Exception { - SdkServiceException exception = SdkServiceException.builder() - .statusCode(HttpStatusCode.THROTTLING) - .build(); - - RetryPolicy retryPolicy = RetryPolicy.builder(RetryMode.ADAPTIVE) - .numRetries(0) - .build(); - - mockChildResponse(exception); - retryableStage = createStage(retryPolicy); - - SdkHttpFullRequest httpRequest = createHttpRequest(); - RequestExecutionContext executionContext = createExecutionContext(); - assertThatThrownBy(() -> retryableStage.execute(httpRequest, executionContext).join()) - .hasCauseInstanceOf(SdkServiceException.class); - - verify(tokenBucket).updateClientSendingRate(true); - verify(tokenBucket, never()).updateClientSendingRate(false); - } - - @Test - public void execute_errorShouldNotBeWrapped() throws Exception { - RetryPolicy retryPolicy = RetryPolicy.builder(RetryMode.ADAPTIVE) - .numRetries(0) - .build(); - - mockChildResponse(new OutOfMemoryError()); - retryableStage = createStage(retryPolicy); - - SdkHttpFullRequest httpRequest = createHttpRequest(); - RequestExecutionContext executionContext = createExecutionContext(); - assertThatThrownBy(() -> retryableStage.execute(httpRequest, executionContext).join()) - .hasCauseInstanceOf(Error.class); - } - - - @Test - public void execute_unsuccessfulResponse_nonThrottlingError_doesNotUpdateRate() throws Exception { - retryableStage = createStage(false); - - SdkServiceException error = SdkServiceException.builder() - .statusCode(500) - .build(); - - mockChildResponse(createUnsuccessfulResponse(error)); - - SdkHttpFullRequest httpRequest = createHttpRequest(); - RequestExecutionContext executionContext = createExecutionContext(); - assertThatThrownBy(() -> retryableStage.execute(httpRequest, executionContext).join()) - .hasCauseInstanceOf(SdkServiceException.class); - - verify(tokenBucket, never()).updateClientSendingRate(anyBoolean()); - } - - @Test - public void execute_unsuccessfulResponse_throttlingError_updatesRate() throws Exception { - RetryPolicy retryPolicy = RetryPolicy.builder(RetryMode.ADAPTIVE) - .numRetries(0) - .build(); - - retryableStage = createStage(retryPolicy); - - SdkServiceException error = SdkServiceException.builder() - .statusCode(HttpStatusCode.THROTTLING) - .build(); - - mockChildResponse(createUnsuccessfulResponse(error)); - - SdkHttpFullRequest httpRequest = createHttpRequest(); - RequestExecutionContext executionContext = createExecutionContext(); - assertThatThrownBy(() -> retryableStage.execute(httpRequest, executionContext).join()) - .hasCauseInstanceOf(SdkServiceException.class); - - verify(tokenBucket).updateClientSendingRate(true); - verify(tokenBucket, never()).updateClientSendingRate(false); - } - - private AsyncRetryableStage createStage(boolean failFast) { - RetryPolicy retryPolicy = RetryPolicy.builder(RetryMode.ADAPTIVE) - .fastFailRateLimiting(failFast) - .build(); - - return createStage(retryPolicy); - } - - private AsyncRetryableStage createStage(RetryPolicy retryPolicy) { - return new AsyncRetryableStage<>(null, clientDependencies(retryPolicy), mockChildPipeline, tokenBucket); - } - - private Response createSuccessResponse() { - return Response.builder() - .isSuccess(true) - .build(); - } - - public Response createUnsuccessfulResponse(SdkException exception) { - return Response.builder() - .isSuccess(false) - .exception(exception) - .build(); - } - - private HttpClientDependencies clientDependencies(RetryPolicy retryPolicy) { - - SdkClientConfiguration clientConfiguration = SdkClientConfiguration.builder() - .option(SdkClientOption.RETRY_POLICY, retryPolicy) - .option(SdkClientOption.SCHEDULED_EXECUTOR_SERVICE, scheduledExecutorService) - .build(); - - return HttpClientDependencies.builder() - .clientConfiguration(clientConfiguration) - .build(); - } - - private static RequestExecutionContext createExecutionContext() { - return RequestExecutionContext.builder() - .originalRequest(NoopTestRequest.builder().build()) - .executionContext(ExecutionContext.builder() - .executionAttributes(new ExecutionAttributes()) - .metricCollector(NoOpMetricCollector.create()) - .build()) - .build(); - } - - private static SdkHttpFullRequest createHttpRequest() { - return SdkHttpFullRequest.builder() - .method(SdkHttpMethod.GET) - .protocol("https") - .host("amazon.com") - .build(); - } - - private void mockChildResponse(Response response) throws Exception { - CompletableFuture> result = CompletableFuture.completedFuture(response); - when(mockChildPipeline.execute(any(SdkHttpFullRequest.class), any(RequestExecutionContext.class))).thenReturn(result); - } - - private void mockChildResponse(Exception error) throws Exception { - CompletableFuture> errorResult = CompletableFutureUtils.failedFuture(error); - when(mockChildPipeline.execute(any(SdkHttpFullRequest.class), any(RequestExecutionContext.class))).thenReturn(errorResult); - } - - private void mockChildResponse(Error error) throws Exception { - CompletableFuture> errorResult = CompletableFutureUtils.failedFuture(error); - when(mockChildPipeline.execute(any(SdkHttpFullRequest.class), any(RequestExecutionContext.class))).thenReturn(errorResult); - } -} diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/HttpChecksumStageTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/HttpChecksumStageNonSraTest.java similarity index 74% rename from core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/HttpChecksumStageTest.java rename to core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/HttpChecksumStageNonSraTest.java index 10b862384c41..0e1b9efe07e1 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/HttpChecksumStageTest.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/HttpChecksumStageNonSraTest.java @@ -26,9 +26,9 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.junit.MockitoJUnitRunner; +import software.amazon.awssdk.checksums.DefaultChecksumAlgorithm; import software.amazon.awssdk.core.ClientType; import software.amazon.awssdk.core.async.AsyncRequestBody; -import software.amazon.awssdk.core.checksums.Algorithm; import software.amazon.awssdk.core.checksums.ChecksumSpecs; import software.amazon.awssdk.core.http.ExecutionContext; import software.amazon.awssdk.core.http.NoopTestRequest; @@ -38,12 +38,13 @@ import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute; import software.amazon.awssdk.core.interceptor.trait.HttpChecksumRequired; import software.amazon.awssdk.core.internal.http.RequestExecutionContext; +import software.amazon.awssdk.core.signer.NoOpSigner; import software.amazon.awssdk.core.sync.RequestBody; import software.amazon.awssdk.http.SdkHttpFullRequest; import utils.ValidSdkObjects; @RunWith(MockitoJUnitRunner.class) -public class HttpChecksumStageTest { +public class HttpChecksumStageNonSraTest { private static final String CHECKSUM_SPECS_HEADER = "x-amz-checksum-sha256"; private static final RequestBody REQUEST_BODY = RequestBody.fromString("TestBody"); private static final AsyncRequestBody ASYNC_REQUEST_BODY = AsyncRequestBody.fromString("TestBody"); @@ -100,6 +101,42 @@ public void async_streaming_md5Required_throws_IllegalArgumentException() throws + "calculated for non-blocking content."); } + @Test + public void syncWithCustomSigner_flexibleChecksumInTrailerRequired_addsFlexibleChecksumInTrailer() throws Exception { + SdkHttpFullRequest.Builder requestBuilder = createHttpRequestBuilder(); + + RequestExecutionContext ctx = noOpSignerRequestContext(ClientType.SYNC); + + syncStage.execute(requestBuilder, ctx); + + assertThat(requestBuilder.headers().get(HEADER_FOR_TRAILER_REFERENCE)).containsExactly(CHECKSUM_SPECS_HEADER); + assertThat(requestBuilder.headers().get("Content-encoding")).containsExactly("aws-chunked"); + assertThat(requestBuilder.headers().get("x-amz-content-sha256")).containsExactly("STREAMING-UNSIGNED-PAYLOAD-TRAILER"); + assertThat(requestBuilder.headers().get("x-amz-decoded-content-length")).containsExactly("8"); + assertThat(requestBuilder.headers().get(CONTENT_LENGTH)).containsExactly("86"); + + assertThat(requestBuilder.firstMatchingHeader(CONTENT_MD5)).isEmpty(); + assertThat(requestBuilder.firstMatchingHeader(CHECKSUM_SPECS_HEADER)).isEmpty(); + } + + @Test + public void asyncWithCustomSigner_flexibleChecksumInTrailerRequired_addsFlexibleChecksumInTrailer() throws Exception { + SdkHttpFullRequest.Builder requestBuilder = createHttpRequestBuilder(); + + RequestExecutionContext ctx = noOpSignerRequestContext(ClientType.ASYNC); + + asyncStage.execute(requestBuilder, ctx); + + assertThat(requestBuilder.headers().get(HEADER_FOR_TRAILER_REFERENCE)).containsExactly(CHECKSUM_SPECS_HEADER); + assertThat(requestBuilder.headers().get("Content-encoding")).containsExactly("aws-chunked"); + assertThat(requestBuilder.headers().get("x-amz-content-sha256")).containsExactly("STREAMING-UNSIGNED-PAYLOAD-TRAILER"); + assertThat(requestBuilder.headers().get("x-amz-decoded-content-length")).containsExactly("8"); + assertThat(requestBuilder.headers().get(CONTENT_LENGTH)).containsExactly("86"); + + assertThat(requestBuilder.firstMatchingHeader(CONTENT_MD5)).isEmpty(); + assertThat(requestBuilder.firstMatchingHeader(CHECKSUM_SPECS_HEADER)).isEmpty(); + } + @Test public void sync_flexibleChecksumInTrailerRequired_addsFlexibleChecksumInTrailer_doesNotAddMd5ChecksumAndFlexibleChecksumInHeader() throws Exception { SdkHttpFullRequest.Builder requestBuilder = createHttpRequestBuilder(); @@ -197,7 +234,7 @@ private RequestExecutionContext syncFlexibleChecksumRequiredRequestContext(boole .headerName(CHECKSUM_SPECS_HEADER) // true = trailer, false = header .isRequestStreaming(isStreaming) - .algorithm(Algorithm.SHA256) + .algorithmV2(DefaultChecksumAlgorithm.SHA256) .build(); ExecutionAttributes executionAttributes = @@ -222,7 +259,7 @@ private RequestExecutionContext asyncFlexibleChecksumRequiredRequestContext(bool .headerName(CHECKSUM_SPECS_HEADER) // true = trailer, false = header .isRequestStreaming(isStreaming) - .algorithm(Algorithm.SHA256) + .algorithmV2(DefaultChecksumAlgorithm.SHA256) .build(); ExecutionAttributes executionAttributes = @@ -248,10 +285,18 @@ private RequestExecutionContext asyncFlexibleChecksumRequiredRequestContext(bool private RequestExecutionContext createRequestExecutionContext(ExecutionAttributes executionAttributes, InterceptorContext interceptorContext, boolean isAsyncStreaming) { - ExecutionContext executionContext = ExecutionContext.builder() - .executionAttributes(executionAttributes) - .interceptorContext(interceptorContext) - .build(); + return createRequestExecutionContext(executionAttributes, interceptorContext, isAsyncStreaming, + ExecutionContext.builder()); + } + + private RequestExecutionContext createRequestExecutionContext(ExecutionAttributes executionAttributes, + InterceptorContext interceptorContext, + boolean isAsyncStreaming, + ExecutionContext.Builder executionContextBuilder) { + ExecutionContext executionContext = executionContextBuilder + .executionAttributes(executionAttributes) + .interceptorContext(interceptorContext) + .build(); RequestExecutionContext.Builder builder = RequestExecutionContext.builder() .executionContext(executionContext) .originalRequest(NoopTestRequest.builder().build()); @@ -260,4 +305,36 @@ private RequestExecutionContext createRequestExecutionContext(ExecutionAttribute } return builder.build(); } + + private RequestExecutionContext noOpSignerRequestContext(ClientType clientType) { + ChecksumSpecs checksumSpecs = ChecksumSpecs.builder() + .headerName(CHECKSUM_SPECS_HEADER) + .isRequestStreaming(true) + .algorithmV2(DefaultChecksumAlgorithm.SHA256) + .build(); + + ExecutionAttributes executionAttributes = + ExecutionAttributes.builder() + .put(SdkExecutionAttribute.RESOLVED_CHECKSUM_SPECS, checksumSpecs) + .put(SdkExecutionAttribute.CLIENT_TYPE, clientType) + .put(SIGNING_METHOD, UNSIGNED_PAYLOAD) + .build(); + + InterceptorContext.Builder interceptorContext = + InterceptorContext.builder() + .request(NoopTestRequest.builder().build()) + .httpRequest(ValidSdkObjects.sdkHttpFullRequest().build()); + + if (clientType == ClientType.ASYNC) { + interceptorContext.asyncRequestBody(ASYNC_REQUEST_BODY); + } else { + interceptorContext.requestBody(REQUEST_BODY); + } + + RequestExecutionContext ctx = createRequestExecutionContext(executionAttributes, interceptorContext.build(), + clientType == ClientType.SYNC ? false : true, + ExecutionContext.builder().signer(new NoOpSigner())); + return ctx; + } + } diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/HttpChecksumStageSraTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/HttpChecksumStageSraTest.java new file mode 100644 index 000000000000..e9fc44d106bb --- /dev/null +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/HttpChecksumStageSraTest.java @@ -0,0 +1,222 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.core.internal.http.pipeline.stages; + +import static org.assertj.core.api.Assertions.assertThat; +import static software.amazon.awssdk.core.HttpChecksumConstant.HEADER_FOR_TRAILER_REFERENCE; +import static software.amazon.awssdk.core.HttpChecksumConstant.SIGNING_METHOD; +import static software.amazon.awssdk.core.interceptor.SdkExecutionAttribute.RESOLVED_CHECKSUM_SPECS; +import static software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute.AUTH_SCHEMES; +import static software.amazon.awssdk.core.internal.signer.SigningMethod.UNSIGNED_PAYLOAD; +import static software.amazon.awssdk.http.Header.CONTENT_LENGTH; +import static software.amazon.awssdk.http.Header.CONTENT_MD5; + +import java.util.HashMap; +import java.util.stream.Stream; +import org.junit.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import software.amazon.awssdk.checksums.DefaultChecksumAlgorithm; +import software.amazon.awssdk.core.ClientType; +import software.amazon.awssdk.core.async.AsyncRequestBody; +import software.amazon.awssdk.core.checksums.ChecksumSpecs; +import software.amazon.awssdk.core.http.ExecutionContext; +import software.amazon.awssdk.core.http.NoopTestRequest; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; +import software.amazon.awssdk.core.interceptor.InterceptorContext; +import software.amazon.awssdk.core.interceptor.SdkExecutionAttribute; +import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute; +import software.amazon.awssdk.core.interceptor.trait.HttpChecksumRequired; +import software.amazon.awssdk.core.internal.http.RequestExecutionContext; +import software.amazon.awssdk.core.sync.RequestBody; +import software.amazon.awssdk.http.SdkHttpFullRequest; +import software.amazon.awssdk.http.auth.aws.internal.signer.util.ChecksumUtil; +import utils.ValidSdkObjects; + +public class HttpChecksumStageSraTest { + private static final String CHECKSUM_SPECS_HEADER = "x-amz-checksum-sha256"; + private static final RequestBody REQUEST_BODY = RequestBody.fromString("TestBody"); + private static final AsyncRequestBody ASYNC_REQUEST_BODY = AsyncRequestBody.fromString("TestBody"); + + public static Stream clientTypes() { + return Stream.of(ClientType.SYNC, ClientType.ASYNC); + } + + @ParameterizedTest + @MethodSource("clientTypes") + public void legacyHttpRequiredTrait_shouldUpdateResolvedChecksumSpec(ClientType clientType) throws Exception { + SdkHttpFullRequest.Builder requestBuilder = createHttpRequestBuilder(); + RequestExecutionContext ctx = legacyHttpRequiredRequestContext(); + + new HttpChecksumStage(clientType).execute(requestBuilder, ctx); + assertThat(requestBuilder.headers().get(CONTENT_MD5)).isNull(); + + ChecksumSpecs checksumSpecs = ctx.executionAttributes().getAttribute(RESOLVED_CHECKSUM_SPECS); + assertThat(checksumSpecs).isNotNull(); + assertThat(checksumSpecs.algorithmV2()).isEqualTo(DefaultChecksumAlgorithm.CRC32); + } + + @ParameterizedTest + @MethodSource("clientTypes") + public void nonStreamingRequestChecksumRequired_checksumNotProvided_shouldUpdateResolvedChecksumSpec(ClientType clientType) throws Exception { + SdkHttpFullRequest.Builder requestBuilder = createHttpRequestBuilder(); + RequestExecutionContext ctx = + flexibleChecksumRequestContext(clientType, ChecksumSpecs.builder().isRequestChecksumRequired(true), false); + + new HttpChecksumStage(clientType).execute(requestBuilder, ctx); + + assertThat(requestBuilder.headers().get(CONTENT_MD5)).isNull(); + + ChecksumSpecs checksumSpecs = ctx.executionAttributes().getAttribute(RESOLVED_CHECKSUM_SPECS); + assertThat(checksumSpecs).isNotNull(); + assertThat(checksumSpecs.algorithmV2()).isEqualTo(DefaultChecksumAlgorithm.CRC32); + } + + @ParameterizedTest + @MethodSource("clientTypes") + public void nonStreamingRequestChecksumRequired_checksumProvided_shouldNotUpdateResolvedChecksumSpec(ClientType clientType) throws Exception { + + SdkHttpFullRequest.Builder requestBuilder = createHttpRequestBuilder().putHeader("x-amz-checksum-sha256", "1234"); + RequestExecutionContext ctx = flexibleChecksumRequestContext(clientType, + ChecksumSpecs.builder().isRequestChecksumRequired(true), + false); + + ChecksumSpecs expectedChecksumSpecs = ctx.executionAttributes().getAttribute(RESOLVED_CHECKSUM_SPECS); + + new HttpChecksumStage(clientType).execute(requestBuilder, ctx); + + assertThat(requestBuilder.headers().get(CONTENT_MD5)).isNull(); + + ChecksumSpecs checksumSpecs = ctx.executionAttributes().getAttribute(RESOLVED_CHECKSUM_SPECS); + assertThat(checksumSpecs).isEqualTo(expectedChecksumSpecs); + } + + @Test + public void sync_flexibleChecksumInTrailer_shouldUpdateResolvedChecksumSpec() throws Exception { + SdkHttpFullRequest.Builder requestBuilder = createHttpRequestBuilder(); + RequestExecutionContext ctx = flexibleChecksumRequestContext(ClientType.SYNC, + ChecksumSpecs.builder().algorithmV2(DefaultChecksumAlgorithm.SHA1) + .headerName(ChecksumUtil.checksumHeaderName(DefaultChecksumAlgorithm.SHA1)), + false); + + new HttpChecksumStage(ClientType.SYNC).execute(requestBuilder, ctx); + + assertThat(requestBuilder.headers().get(CONTENT_MD5)).isNull(); + + ChecksumSpecs checksumSpecs = ctx.executionAttributes().getAttribute(RESOLVED_CHECKSUM_SPECS); + assertThat(checksumSpecs).isNotNull(); + assertThat(checksumSpecs.algorithmV2()).isEqualTo(DefaultChecksumAlgorithm.SHA1); + } + + @Test + public void async_flexibleChecksumInTrailer_addsFlexibleChecksumInTrailer() throws Exception { + SdkHttpFullRequest.Builder requestBuilder = createHttpRequestBuilder(); + boolean isStreaming = true; + RequestExecutionContext ctx = flexibleChecksumRequestContext(ClientType.ASYNC, + ChecksumSpecs.builder() + .algorithmV2(DefaultChecksumAlgorithm.SHA256) + .headerName(ChecksumUtil.checksumHeaderName(DefaultChecksumAlgorithm.SHA1)), + isStreaming); + + new HttpChecksumStage(ClientType.ASYNC).execute(requestBuilder, ctx); + + assertThat(requestBuilder.headers().get(HEADER_FOR_TRAILER_REFERENCE)).containsExactly(CHECKSUM_SPECS_HEADER); + assertThat(requestBuilder.headers().get("Content-encoding")).containsExactly("aws-chunked"); + assertThat(requestBuilder.headers().get("x-amz-content-sha256")).containsExactly("STREAMING-UNSIGNED-PAYLOAD-TRAILER"); + assertThat(requestBuilder.headers().get("x-amz-decoded-content-length")).containsExactly("8"); + assertThat(requestBuilder.headers().get(CONTENT_LENGTH)).containsExactly("86"); + + assertThat(requestBuilder.firstMatchingHeader(CONTENT_MD5)).isEmpty(); + assertThat(requestBuilder.firstMatchingHeader(CHECKSUM_SPECS_HEADER)).isEmpty(); + } + + private SdkHttpFullRequest.Builder createHttpRequestBuilder() { + return SdkHttpFullRequest.builder().contentStreamProvider(REQUEST_BODY.contentStreamProvider()); + } + + private RequestExecutionContext legacyHttpRequiredRequestContext() { + ExecutionAttributes executionAttributes = + ExecutionAttributes.builder() + .put(SdkInternalExecutionAttribute.HTTP_CHECKSUM_REQUIRED, HttpChecksumRequired.create()) + .put(SIGNING_METHOD, UNSIGNED_PAYLOAD) + .put(AUTH_SCHEMES, new HashMap<>()) + .build(); + + InterceptorContext interceptorContext = + InterceptorContext.builder() + .request(NoopTestRequest.builder().build()) + .httpRequest(ValidSdkObjects.sdkHttpFullRequest().build()) + .requestBody(REQUEST_BODY) + .build(); + + return createRequestExecutionContext(executionAttributes, interceptorContext, false); + } + + private RequestExecutionContext flexibleChecksumRequestContext(ClientType clientType, + ChecksumSpecs.Builder checksumSpecsBuilder, + boolean isStreaming) { + ChecksumSpecs checksumSpecs = checksumSpecsBuilder + .isRequestStreaming(isStreaming) + .build(); + + ExecutionAttributes executionAttributes = + ExecutionAttributes.builder() + .put(SdkExecutionAttribute.RESOLVED_CHECKSUM_SPECS, checksumSpecs) + .put(SdkExecutionAttribute.CLIENT_TYPE, clientType) + .put(SIGNING_METHOD, UNSIGNED_PAYLOAD) + .put(AUTH_SCHEMES, new HashMap<>()) + .build(); + + InterceptorContext.Builder interceptorContextBuilder = + InterceptorContext.builder() + .request(NoopTestRequest.builder().build()) + .httpRequest(ValidSdkObjects.sdkHttpFullRequest().build()) + .requestBody(REQUEST_BODY); + + + if (isStreaming) { + switch (clientType) { + case ASYNC: + interceptorContextBuilder.asyncRequestBody(ASYNC_REQUEST_BODY); + break; + case SYNC: + interceptorContextBuilder.requestBody(REQUEST_BODY); + break; + default: + throw new UnsupportedOperationException("Unsupported client type" + clientType.toString()); + } + + } + + return createRequestExecutionContext(executionAttributes, interceptorContextBuilder.build(), isStreaming); + } + + private RequestExecutionContext createRequestExecutionContext(ExecutionAttributes executionAttributes, + InterceptorContext interceptorContext, + boolean isAsyncStreaming) { + ExecutionContext executionContext = ExecutionContext.builder() + .executionAttributes(executionAttributes) + .interceptorContext(interceptorContext) + .build(); + RequestExecutionContext.Builder builder = RequestExecutionContext.builder() + .executionContext(executionContext) + .originalRequest(NoopTestRequest.builder().build()); + if (isAsyncStreaming) { + builder.requestProvider(ASYNC_REQUEST_BODY); + } + return builder.build(); + } +} diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/RetryableStageAdaptiveModeTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/RetryableStageAdaptiveModeTest.java deleted file mode 100644 index 9c04be10aa36..000000000000 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/http/pipeline/stages/RetryableStageAdaptiveModeTest.java +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -package software.amazon.awssdk.core.internal.http.pipeline.stages; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyDouble; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import software.amazon.awssdk.core.Response; -import software.amazon.awssdk.core.client.config.SdkClientConfiguration; -import software.amazon.awssdk.core.client.config.SdkClientOption; -import software.amazon.awssdk.core.exception.SdkClientException; -import software.amazon.awssdk.core.exception.SdkException; -import software.amazon.awssdk.core.exception.SdkServiceException; -import software.amazon.awssdk.core.http.ExecutionContext; -import software.amazon.awssdk.core.http.NoopTestRequest; -import software.amazon.awssdk.core.interceptor.ExecutionAttributes; -import software.amazon.awssdk.core.internal.http.HttpClientDependencies; -import software.amazon.awssdk.core.internal.http.RequestExecutionContext; -import software.amazon.awssdk.core.internal.http.pipeline.RequestPipeline; -import software.amazon.awssdk.core.internal.retry.RateLimitingTokenBucket; -import software.amazon.awssdk.core.retry.RetryMode; -import software.amazon.awssdk.core.retry.RetryPolicy; -import software.amazon.awssdk.http.HttpStatusCode; -import software.amazon.awssdk.http.SdkHttpFullRequest; -import software.amazon.awssdk.http.SdkHttpMethod; -import software.amazon.awssdk.metrics.NoOpMetricCollector; - -public class RetryableStageAdaptiveModeTest { - private RateLimitingTokenBucket tokenBucket; - - private RequestPipeline> mockChildPipeline; - - private RetryableStage retryableStage; - - @BeforeEach - public void setup() throws Exception { - tokenBucket = spy(RateLimitingTokenBucket.class); - mockChildPipeline = mock(RequestPipeline.class); - } - - @Test - public void execute_acquiresToken() throws Exception { - retryableStage = createStage(false); - mockChildResponse(createSuccessResponse()); - retryableStage.execute(createHttpRequest(), createExecutionContext()); - - verify(tokenBucket).acquire(1.0, false); - } - - @Test - public void execute_fastFailEnabled_propagatesSettingToBucket() throws Exception { - retryableStage = createStage(true); - mockChildResponse(createSuccessResponse()); - retryableStage.execute(createHttpRequest(), createExecutionContext()); - - verify(tokenBucket).acquire(1.0, true); - } - - @Test - public void execute_retryModeStandard_doesNotAcquireToken() throws Exception { - RetryPolicy retryPolicy = RetryPolicy.builder(RetryMode.STANDARD).build(); - mockChildResponse(createSuccessResponse()); - retryableStage = createStage(retryPolicy); - retryableStage.execute(createHttpRequest(), createExecutionContext()); - - verifyNoMoreInteractions(tokenBucket); - } - - @Test - public void execute_retryModeLegacy_doesNotAcquireToken() throws Exception { - RetryPolicy retryPolicy = RetryPolicy.builder(RetryMode.LEGACY).build(); - mockChildResponse(createSuccessResponse()); - retryableStage = createStage(retryPolicy); - retryableStage.execute(createHttpRequest(), createExecutionContext()); - - verifyNoMoreInteractions(tokenBucket); - } - - @Test - public void execute_acquireReturnsFalse_throws() { - when(tokenBucket.acquire(anyDouble(), anyBoolean())).thenReturn(false); - retryableStage = createStage(false); - - SdkHttpFullRequest httpRequest = createHttpRequest(); - RequestExecutionContext executionContext = createExecutionContext(); - assertThatThrownBy(() -> retryableStage.execute(httpRequest, executionContext)) - .isInstanceOf(SdkClientException.class) - .hasMessageContaining("Unable to acquire a send token"); - } - @Test - public void execute_responseSuccessful_updatesWithThrottlingFalse() throws Exception { - retryableStage = createStage(false); - mockChildResponse(createSuccessResponse()); - retryableStage.execute(createHttpRequest(), createExecutionContext()); - - verify(tokenBucket).updateClientSendingRate(false); - verify(tokenBucket, never()).updateClientSendingRate(true); - } - - @Test - public void execute_nonThrottlingServiceException_doesNotUpdateRate() throws Exception { - SdkServiceException exception = SdkServiceException.builder() - .statusCode(500) - .build(); - mockChildResponse(exception); - retryableStage = createStage(false); - - SdkHttpFullRequest httpRequest = createHttpRequest(); - RequestExecutionContext executionContext = createExecutionContext(); - assertThatThrownBy(() -> retryableStage.execute(httpRequest, executionContext)) - .isInstanceOf(SdkServiceException.class); - - verify(tokenBucket, never()).updateClientSendingRate(anyBoolean()); - } - - @Test - public void execute_throttlingServiceException_updatesRate() throws Exception { - SdkServiceException exception = SdkServiceException.builder() - .statusCode(HttpStatusCode.THROTTLING) - .build(); - - RetryPolicy retryPolicy = RetryPolicy.builder(RetryMode.ADAPTIVE) - .numRetries(0) - .build(); - - mockChildResponse(exception); - retryableStage = createStage(retryPolicy); - - SdkHttpFullRequest httpRequest = createHttpRequest(); - RequestExecutionContext executionContext = createExecutionContext(); - assertThatThrownBy(() -> retryableStage.execute(httpRequest, executionContext)) - .isInstanceOf(SdkServiceException.class); - - verify(tokenBucket).updateClientSendingRate(true); - verify(tokenBucket, never()).updateClientSendingRate(false); - } - - @Test - public void execute_unsuccessfulResponse_nonThrottlingError_doesNotUpdateRate() throws Exception { - retryableStage = createStage(false); - - SdkServiceException error = SdkServiceException.builder() - .statusCode(500) - .build(); - - mockChildResponse(createUnsuccessfulResponse(error)); - - SdkHttpFullRequest httpRequest = createHttpRequest(); - RequestExecutionContext executionContext = createExecutionContext(); - assertThatThrownBy(() -> retryableStage.execute(httpRequest, executionContext)) - .isInstanceOf(SdkServiceException.class); - - verify(tokenBucket, never()).updateClientSendingRate(anyBoolean()); - } - - @Test - public void execute_unsuccessfulResponse_throttlingError_updatesRate() throws Exception { - RetryPolicy retryPolicy = RetryPolicy.builder(RetryMode.ADAPTIVE) - .numRetries(0) - .build(); - - retryableStage = createStage(retryPolicy); - - SdkServiceException error = SdkServiceException.builder() - .statusCode(HttpStatusCode.THROTTLING) - .build(); - - mockChildResponse(createUnsuccessfulResponse(error)); - - SdkHttpFullRequest httpRequest = createHttpRequest(); - RequestExecutionContext executionContext = createExecutionContext(); - assertThatThrownBy(() -> retryableStage.execute(httpRequest, executionContext)) - .isInstanceOf(SdkServiceException.class); - - verify(tokenBucket).updateClientSendingRate(true); - verify(tokenBucket, never()).updateClientSendingRate(false); - } - - private RetryableStage createStage(boolean failFast) { - RetryPolicy retryPolicy = RetryPolicy.builder(RetryMode.ADAPTIVE) - .fastFailRateLimiting(failFast) - .build(); - - return createStage(retryPolicy); - } - - private RetryableStage createStage(RetryPolicy retryPolicy) { - return new RetryableStage<>(clientDependencies(retryPolicy), mockChildPipeline, tokenBucket); - } - - private Response createSuccessResponse() { - return Response.builder() - .isSuccess(true) - .build(); - } - - public Response createUnsuccessfulResponse(SdkException exception) { - return Response.builder() - .isSuccess(false) - .exception(exception) - .build(); - } - - private HttpClientDependencies clientDependencies(RetryPolicy retryPolicy) { - - SdkClientConfiguration clientConfiguration = SdkClientConfiguration.builder() - .option(SdkClientOption.RETRY_POLICY, retryPolicy) - .build(); - - return HttpClientDependencies.builder() - .clientConfiguration(clientConfiguration) - .build(); - } - - private static RequestExecutionContext createExecutionContext() { - return RequestExecutionContext.builder() - .originalRequest(NoopTestRequest.builder().build()) - .executionContext(ExecutionContext.builder() - .executionAttributes(new ExecutionAttributes()) - .metricCollector(NoOpMetricCollector.create()) - .build()) - .build(); - } - - private static SdkHttpFullRequest createHttpRequest() { - return SdkHttpFullRequest.builder() - .method(SdkHttpMethod.GET) - .protocol("https") - .host("amazon.com") - .build(); - } - - private void mockChildResponse(Response response) throws Exception { - when(mockChildPipeline.execute(any(SdkHttpFullRequest.class), any(RequestExecutionContext.class))).thenReturn(response); - } - - private void mockChildResponse(Exception error) throws Exception { - when(mockChildPipeline.execute(any(SdkHttpFullRequest.class), any(RequestExecutionContext.class))).thenThrow(error); - } -} diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/util/HttpChecksumResolverTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/util/HttpChecksumResolverTest.java index a72d69e41f64..1a580df5e556 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/util/HttpChecksumResolverTest.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/util/HttpChecksumResolverTest.java @@ -29,7 +29,7 @@ public class HttpChecksumResolverTest { - HttpChecksum CRC32_STREAMING_CHECKSUM = HttpChecksum.builder() + private static final HttpChecksum CRC32_STREAMING_CHECKSUM = HttpChecksum.builder() .requestChecksumRequired(true) .responseAlgorithms("crc32c", "crc32") .requestAlgorithm("crc32") diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/util/HttpChecksumUtilsTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/util/HttpChecksumUtilsTest.java new file mode 100644 index 000000000000..31b00d68e64f --- /dev/null +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/util/HttpChecksumUtilsTest.java @@ -0,0 +1,151 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.core.internal.util; + +import static org.assertj.core.api.Assertions.assertThat; +import static software.amazon.awssdk.core.HttpChecksumConstant.HEADER_FOR_TRAILER_REFERENCE; + +import java.util.List; +import java.util.Optional; +import java.util.stream.Stream; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import software.amazon.awssdk.checksums.DefaultChecksumAlgorithm; +import software.amazon.awssdk.core.RequestOverrideConfiguration; +import software.amazon.awssdk.core.SdkField; +import software.amazon.awssdk.core.SdkRequest; +import software.amazon.awssdk.core.checksums.ChecksumSpecs; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; +import software.amazon.awssdk.core.interceptor.SdkExecutionAttribute; +import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute; +import software.amazon.awssdk.core.interceptor.trait.HttpChecksumRequired; +import software.amazon.awssdk.core.sync.RequestBody; +import software.amazon.awssdk.http.SdkHttpFullRequest; +import software.amazon.awssdk.utils.Pair; + +public class HttpChecksumUtilsTest { + + + public static Stream httpChecksumCalculationParams() { + + return Stream.of(Arguments.of(false, null, RequestChecksumCalculation.WHEN_SUPPORTED, null, false, + "noChecksumTrait_shouldReturnFalse"), + + Arguments.of(true, null, RequestChecksumCalculation.WHEN_REQUIRED, null, true, + "hasLegacyHttpChecksumRequired_checksumWhenRequired_shouldReturnTrue"), + + Arguments.of(true, null, RequestChecksumCalculation.WHEN_SUPPORTED, null, true, + "hasLegacyHttpChecksumRequired_checksumWhenSupported_shouldReturnTrue"), + + Arguments.of(false, ChecksumSpecs.builder().isRequestChecksumRequired(true).build(), + RequestChecksumCalculation.WHEN_SUPPORTED, null, true, + "hasFlexibleHttpChecksumRequired_checksumWhenSupported_shouldReturnTrue"), + + Arguments.of(false, ChecksumSpecs.builder().isRequestChecksumRequired(true).build(), + RequestChecksumCalculation.WHEN_REQUIRED, null, true, + "hasFlexibleHttpChecksumRequired_checksumWhenRequired_shouldReturnTrue"), + + Arguments.of(false, ChecksumSpecs.builder().build(), + RequestChecksumCalculation.WHEN_SUPPORTED, null, + true, + "hasFlexibleChecksumTraitWithNoAlgorithm_checksumWhenSupported_shouldReturnTrue"), + + Arguments.of(false, ChecksumSpecs.builder().algorithmV2(DefaultChecksumAlgorithm.SHA1).build(), + RequestChecksumCalculation.WHEN_REQUIRED, null, + true, + "hasFlexibleChecksumTraitWithAlgorithm_checksumWhenRequired_shouldReturnTrue"), + + Arguments.of(false, ChecksumSpecs.builder().algorithmV2(DefaultChecksumAlgorithm.SHA1).build(), + RequestChecksumCalculation.WHEN_SUPPORTED, null, + true, + "hasFlexibleChecksumTraitWithAlgorithm_checksumWhenSupported_shouldReturnTrue"), + + Arguments.of(false, ChecksumSpecs.builder().build(), + RequestChecksumCalculation.WHEN_REQUIRED, null, + false, + "hasFlexibleChecksumTraitWithNoAlgorithm_checksumWhenRequired_shouldReturnFalse"), + + Arguments.of(true, null, + RequestChecksumCalculation.WHEN_SUPPORTED, Pair.of("x-amz-checksum-crc32", "somevalue"), + false, + "knownChecksumHeaderPresent_checksumWhenSupported_shouldReturnFalse"), + + Arguments.of(true, null, + RequestChecksumCalculation.WHEN_SUPPORTED, Pair.of("x-amz-checksum-foobar", "somevalue"), + false, + "randomHeaderWithChecksumPrefixPresent_checksumWhenSupported_shouldReturnFalse"), + + Arguments.of(true, null, + RequestChecksumCalculation.WHEN_SUPPORTED, Pair.of("test-x-amz-checksum-crc32", + "somevalue"), + true, + "randomHeaderContainingChecksumPrefixPresent_checksumWhenSupported_shouldReturnTrue"), + + Arguments.of(true, null, + RequestChecksumCalculation.WHEN_REQUIRED, Pair.of("x-amz-checksum-crc32", "somevalue"), + false, + "checksumHeaderPresent_checksumWhenRequired_shouldReturnFalse"), + + Arguments.of(true, null, + RequestChecksumCalculation.WHEN_REQUIRED, Pair.of("x-amz-checksum-foobar", "somevalue"), + false, + "randomHeaderWithChecksumPrefixPresent_checksumWhenRequired_shouldReturnFalse"), + + Arguments.of(false, ChecksumSpecs.builder().isRequestStreaming(true).build(), + RequestChecksumCalculation.WHEN_SUPPORTED, Pair.of(HEADER_FOR_TRAILER_REFERENCE, "x-amz-checksum-crc32"), + false, + "checksumTrailerPresent_checksumWhenSupported_shouldReturnFalse"), + + Arguments.of(false, ChecksumSpecs.builder().isRequestStreaming(true).build(), + RequestChecksumCalculation.WHEN_REQUIRED, Pair.of(HEADER_FOR_TRAILER_REFERENCE, "x-amz-checksum" + + "-crc32"), + false, + "checksumTrailerPresent_checksumWhenRequired_shouldReturnFalse") + ); + } + + @ParameterizedTest(name = "{index} {5}") + @MethodSource("httpChecksumCalculationParams") + void isHttpChecksumCalculationNeeded(boolean hasLegacyHttpChecksumTrait, + ChecksumSpecs checksumSpecs, + RequestChecksumCalculation requestChecksumCalculation, + Pair additionalHeader, + boolean expectedValue, + String description) { + + SdkHttpFullRequest.Builder httpRequestBuilder = createHttpRequestBuilder(); + if (additionalHeader != null) { + httpRequestBuilder.putHeader(additionalHeader.left(), additionalHeader.right()); + } + + ExecutionAttributes.Builder executionAttributes = + ExecutionAttributes.builder() + .put(SdkExecutionAttribute.RESOLVED_CHECKSUM_SPECS, checksumSpecs) + .put(SdkInternalExecutionAttribute.REQUEST_CHECKSUM_CALCULATION, requestChecksumCalculation); + + if (hasLegacyHttpChecksumTrait) { + executionAttributes.put(SdkInternalExecutionAttribute.HTTP_CHECKSUM_REQUIRED, HttpChecksumRequired.create()); + } + + assertThat(HttpChecksumUtils.isHttpChecksumCalculationNeeded(httpRequestBuilder, executionAttributes.build())).isEqualTo(expectedValue); + } + + private SdkHttpFullRequest.Builder createHttpRequestBuilder() { + return SdkHttpFullRequest.builder().contentStreamProvider(RequestBody.fromString("test").contentStreamProvider()); + } +} diff --git a/core/sdk-core/src/test/java/software/amazon/awssdk/core/io/ChecksumValidatingInputStreamTest.java b/core/sdk-core/src/test/java/software/amazon/awssdk/core/io/ChecksumValidatingInputStreamTest.java index 7bf3dd0ab7d8..2d3efecfa9c1 100644 --- a/core/sdk-core/src/test/java/software/amazon/awssdk/core/io/ChecksumValidatingInputStreamTest.java +++ b/core/sdk-core/src/test/java/software/amazon/awssdk/core/io/ChecksumValidatingInputStreamTest.java @@ -2,8 +2,9 @@ import org.assertj.core.api.Assertions; import org.junit.Test; +import software.amazon.awssdk.checksums.DefaultChecksumAlgorithm; +import software.amazon.awssdk.checksums.SdkChecksum; import software.amazon.awssdk.core.checksums.Algorithm; -import software.amazon.awssdk.core.checksums.SdkChecksum; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.core.internal.io.ChecksumValidatingInputStream; @@ -17,7 +18,7 @@ public class ChecksumValidatingInputStreamTest { public void validCheckSumMatch() throws IOException { String initialString = "Hello world"; InputStream targetStream = new ByteArrayInputStream(initialString.getBytes()); - SdkChecksum sdkChecksum = SdkChecksum.forAlgorithm(Algorithm.SHA256); + SdkChecksum sdkChecksum = SdkChecksum.forAlgorithm(DefaultChecksumAlgorithm.SHA256); ChecksumValidatingInputStream checksumValidatingInputStream = new ChecksumValidatingInputStream(targetStream, sdkChecksum, "ZOyIygCyaOW6GjVnihtTFtIS9PNmskdyMlNKiuyjfzw="); @@ -29,7 +30,7 @@ public void validCheckSumMatch() throws IOException { public void validCheckSumMismatch() { String initialString = "Hello world"; InputStream targetStream = new ByteArrayInputStream(initialString.getBytes()); - SdkChecksum sdkChecksum = SdkChecksum.forAlgorithm(Algorithm.SHA256); + SdkChecksum sdkChecksum = SdkChecksum.forAlgorithm(DefaultChecksumAlgorithm.SHA256); ChecksumValidatingInputStream checksumValidatingInputStream = new ChecksumValidatingInputStream(targetStream, sdkChecksum, "ZOyIygCyaOW6GjVnihtTFtIS9PNmskdyMlNKiuyjfz1="); diff --git a/http-client-spi/pom.xml b/http-client-spi/pom.xml index e81c5bd367cc..2fb88be28bb8 100644 --- a/http-client-spi/pom.xml +++ b/http-client-spi/pom.xml @@ -22,7 +22,7 @@ aws-sdk-java-pom software.amazon.awssdk - 2.29.52 + 2.30.0 http-client-spi AWS Java SDK :: HTTP Client Interface diff --git a/http-client-spi/src/main/java/software/amazon/awssdk/http/DefaultSdkHttpFullRequest.java b/http-client-spi/src/main/java/software/amazon/awssdk/http/DefaultSdkHttpFullRequest.java index d038b5462911..6008fa638501 100644 --- a/http-client-spi/src/main/java/software/amazon/awssdk/http/DefaultSdkHttpFullRequest.java +++ b/http-client-spi/src/main/java/software/amazon/awssdk/http/DefaultSdkHttpFullRequest.java @@ -26,6 +26,7 @@ import java.util.Optional; import java.util.function.BiConsumer; import java.util.function.Consumer; +import java.util.function.Predicate; import software.amazon.awssdk.annotations.Immutable; import software.amazon.awssdk.annotations.SdkInternalApi; import software.amazon.awssdk.internal.http.LowCopyListMap; @@ -440,6 +441,17 @@ public void forEachRawQueryParameter(BiConsumer consumer.accept(k, unmodifiableList(v))); } + @Override + public boolean anyMatchingHeader(Predicate predicate) { + for (String headerKey : headers.forInternalRead().keySet()) { + if (predicate.test(headerKey)) { + return true; + } + } + + return false; + } + @Override public int numHeaders() { return headers.forInternalRead().size(); diff --git a/http-client-spi/src/main/java/software/amazon/awssdk/http/SdkHttpHeaders.java b/http-client-spi/src/main/java/software/amazon/awssdk/http/SdkHttpHeaders.java index 790d833807b0..3ac1f0a7791a 100644 --- a/http-client-spi/src/main/java/software/amazon/awssdk/http/SdkHttpHeaders.java +++ b/http-client-spi/src/main/java/software/amazon/awssdk/http/SdkHttpHeaders.java @@ -20,6 +20,7 @@ import java.util.Map; import java.util.Optional; import java.util.function.BiConsumer; +import java.util.function.Predicate; import java.util.stream.Collectors; import software.amazon.awssdk.annotations.Immutable; import software.amazon.awssdk.annotations.SdkPublicApi; @@ -57,6 +58,16 @@ default Optional firstMatchingHeader(String header) { return SdkHttpUtils.firstMatchingHeader(headers(), header); } + /** + * Returns whether any header key matches the provided predicate. + * + * @param predicate the predicate to apply to all header keys + * @return true if any header key matches the provided predicate, otherwise {@code false} + */ + default boolean anyMatchingHeader(Predicate predicate) { + return headers().keySet().stream().anyMatch(predicate); + } + default Optional firstMatchingHeader(Collection headersToFind) { return SdkHttpUtils.firstMatchingHeaderFromCollection(headers(), headersToFind); } diff --git a/http-clients/apache-client/pom.xml b/http-clients/apache-client/pom.xml index 664e2ccd6173..128f56e09da2 100644 --- a/http-clients/apache-client/pom.xml +++ b/http-clients/apache-client/pom.xml @@ -21,7 +21,7 @@ http-clients software.amazon.awssdk - 2.29.52 + 2.30.0 apache-client diff --git a/http-clients/aws-crt-client/pom.xml b/http-clients/aws-crt-client/pom.xml index 2cf82c7ca4fa..daafc20e679f 100644 --- a/http-clients/aws-crt-client/pom.xml +++ b/http-clients/aws-crt-client/pom.xml @@ -21,7 +21,7 @@ http-clients software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 diff --git a/http-clients/netty-nio-client/pom.xml b/http-clients/netty-nio-client/pom.xml index d23d344f3093..ea3f6016dce3 100644 --- a/http-clients/netty-nio-client/pom.xml +++ b/http-clients/netty-nio-client/pom.xml @@ -20,7 +20,7 @@ http-clients software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 diff --git a/http-clients/pom.xml b/http-clients/pom.xml index f2ac96071655..6e7889745b83 100644 --- a/http-clients/pom.xml +++ b/http-clients/pom.xml @@ -21,7 +21,7 @@ aws-sdk-java-pom software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 diff --git a/http-clients/url-connection-client/pom.xml b/http-clients/url-connection-client/pom.xml index 800ac53de610..e549ee63395b 100644 --- a/http-clients/url-connection-client/pom.xml +++ b/http-clients/url-connection-client/pom.xml @@ -20,7 +20,7 @@ http-clients software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 diff --git a/http-clients/url-connection-client/src/it/java/software/amazon/awssdk/http/urlconnection/S3WithUrlHttpClientIntegrationTest.java b/http-clients/url-connection-client/src/it/java/software/amazon/awssdk/http/urlconnection/S3WithUrlHttpClientIntegrationTest.java index 194c09e3b33b..c0ed9d162971 100644 --- a/http-clients/url-connection-client/src/it/java/software/amazon/awssdk/http/urlconnection/S3WithUrlHttpClientIntegrationTest.java +++ b/http-clients/url-connection-client/src/it/java/software/amazon/awssdk/http/urlconnection/S3WithUrlHttpClientIntegrationTest.java @@ -53,8 +53,8 @@ public class S3WithUrlHttpClientIntegrationTest { private static final String KEY = "key"; private static final Region REGION = Region.US_WEST_2; private static final CapturingInterceptor capturingInterceptor = new CapturingInterceptor(); - private static final String SIGNED_PAYLOAD_HEADER_VALUE = "STREAMING-AWS4-HMAC-SHA256-PAYLOAD"; - private static final String UNSIGNED_PAYLOAD_HEADER_VALUE = "UNSIGNED-PAYLOAD"; + private static final String SIGNED_PAYLOAD_HEADER_VALUE = "STREAMING-AWS4-HMAC-SHA256-PAYLOAD-TRAILER"; + private static final String UNSIGNED_PAYLOAD_HEADER_VALUE = "STREAMING-UNSIGNED-PAYLOAD-TRAILER"; private static S3Client s3; private static S3Client s3Http; diff --git a/metric-publishers/cloudwatch-metric-publisher/pom.xml b/metric-publishers/cloudwatch-metric-publisher/pom.xml index 016799dfa3da..bf732436f0b6 100644 --- a/metric-publishers/cloudwatch-metric-publisher/pom.xml +++ b/metric-publishers/cloudwatch-metric-publisher/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk metric-publishers - 2.29.52 + 2.30.0 cloudwatch-metric-publisher diff --git a/metric-publishers/pom.xml b/metric-publishers/pom.xml index c61304f6680a..0c00d802babc 100644 --- a/metric-publishers/pom.xml +++ b/metric-publishers/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk aws-sdk-java-pom - 2.29.52 + 2.30.0 metric-publishers diff --git a/pom.xml b/pom.xml index 9bc801686ade..010e850fe059 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ 4.0.0 software.amazon.awssdk aws-sdk-java-pom - 2.29.52 + 2.30.0 pom AWS Java SDK :: Parent The Amazon Web Services SDK for Java provides Java APIs @@ -100,7 +100,7 @@ ${project.version} - 2.29.51 + 2.29.52 2.15.2 2.15.2 2.13.2 @@ -124,7 +124,7 @@ 2.2.21 1.17.1 1.37 - 0.33.3 + 0.33.6 5.10.0 @@ -667,7 +667,7 @@ s3-event-notifications - s3 + s3 s3-control sqs rds @@ -680,6 +680,8 @@ software.amazon.awssdk.regions.* software.amazon.awssdk.utils.JavaSystemSetting + + software.amazon.awssdk.eventnotifications.s3.model.S3EventNotification true diff --git a/release-scripts/pom.xml b/release-scripts/pom.xml index ad731dd1b865..fffea8879bca 100644 --- a/release-scripts/pom.xml +++ b/release-scripts/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk aws-sdk-java-pom - 2.29.52 + 2.30.0 ../pom.xml release-scripts diff --git a/services-custom/dynamodb-enhanced/pom.xml b/services-custom/dynamodb-enhanced/pom.xml index 42136c68ea4b..1be0e68062e8 100644 --- a/services-custom/dynamodb-enhanced/pom.xml +++ b/services-custom/dynamodb-enhanced/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services-custom - 2.29.52 + 2.30.0 dynamodb-enhanced AWS Java SDK :: DynamoDB :: Enhanced Client diff --git a/services-custom/iam-policy-builder/pom.xml b/services-custom/iam-policy-builder/pom.xml index 9b04f3c812a3..a24d9214dae0 100644 --- a/services-custom/iam-policy-builder/pom.xml +++ b/services-custom/iam-policy-builder/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk aws-sdk-java-pom - 2.29.52 + 2.30.0 ../../pom.xml iam-policy-builder diff --git a/services-custom/pom.xml b/services-custom/pom.xml index e0d062a5b9c3..999e55430e05 100644 --- a/services-custom/pom.xml +++ b/services-custom/pom.xml @@ -19,7 +19,7 @@ software.amazon.awssdk aws-sdk-java-pom - 2.29.52 + 2.30.0 services-custom AWS Java SDK :: Custom Services diff --git a/services-custom/s3-event-notifications/pom.xml b/services-custom/s3-event-notifications/pom.xml index fa4b944b51d8..d555527ce5cd 100644 --- a/services-custom/s3-event-notifications/pom.xml +++ b/services-custom/s3-event-notifications/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk aws-sdk-java-pom - 2.29.52 + 2.30.0 ../../pom.xml s3-event-notifications diff --git a/services-custom/s3-event-notifications/src/main/java/software/amazon/awssdk/eventnotifications/s3/model/S3EventNotification.java b/services-custom/s3-event-notifications/src/main/java/software/amazon/awssdk/eventnotifications/s3/model/S3EventNotification.java index d3e94e92c2ca..aaf506e2cb16 100644 --- a/services-custom/s3-event-notifications/src/main/java/software/amazon/awssdk/eventnotifications/s3/model/S3EventNotification.java +++ b/services-custom/s3-event-notifications/src/main/java/software/amazon/awssdk/eventnotifications/s3/model/S3EventNotification.java @@ -73,7 +73,7 @@ public static S3EventNotification fromJson(byte[] json) { * @param json the notification message in json format * @return an instance of notification message S3EventNotification */ - public S3EventNotification fromJson(InputStream json) { + public static S3EventNotification fromJson(InputStream json) { return S3EventNotificationReader.create().read(json); } diff --git a/services-custom/s3-event-notifications/src/test/java/software/amazon/awssdk/eventnotifications/s3/model/S3EventNotificationReaderTest.java b/services-custom/s3-event-notifications/src/test/java/software/amazon/awssdk/eventnotifications/s3/model/S3EventNotificationReaderTest.java index ff369943bc1f..ef9d2c89154a 100644 --- a/services-custom/s3-event-notifications/src/test/java/software/amazon/awssdk/eventnotifications/s3/model/S3EventNotificationReaderTest.java +++ b/services-custom/s3-event-notifications/src/test/java/software/amazon/awssdk/eventnotifications/s3/model/S3EventNotificationReaderTest.java @@ -18,6 +18,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import java.io.ByteArrayInputStream; import java.time.Instant; import java.util.Arrays; import java.util.Collections; @@ -454,4 +455,128 @@ void malformedJson_throwsException() { String json = "{\"Records\":[], \"toto\"}"; assertThatThrownBy(() -> S3EventNotification.fromJson(json)).hasCauseInstanceOf(JsonParseException.class); } + + @Test + void fromJsonInputStream_handlesCorrectly() { + String eventJson = "{ " + + " \"Records\":[ " + + " { " + + " \"eventVersion\":\"2.1\"," + + " \"eventSource\":\"aws:s3\"," + + " \"awsRegion\":\"us-west-2\"," + + " \"eventTime\":\"1970-01-01T00:00:00.000Z\"," + + " \"eventName\":\"ObjectCreated:Put\"," + + " \"userIdentity\":{ " + + " \"principalId\":\"AIDAJDPLRKLG7UEXAMPLE\"" + + " }," + + " \"requestParameters\":{ " + + " \"sourceIPAddress\":\"127.0.0.1\"" + + " }," + + " \"responseElements\":{ " + + " \"x-amz-request-id\":\"C3D13FE58DE4C810\"," + + " \"x-amz-id-2\":\"FMyUVURIY8/IgAtTv8xRjskZQpcIZ9KG4V5Wp6S7S/JRWeUWerMUE5JgHvANOjpD\"" + + " }," + + " \"s3\":{ " + + " \"s3SchemaVersion\":\"1.0\"," + + " \"configurationId\":\"testConfigRule\"," + + " \"bucket\":{ " + + " \"name\":\"mybucket\"," + + " \"ownerIdentity\":{ " + + " \"principalId\":\"A3NL1KOZZKExample\"" + + " }," + + " \"arn\":\"arn:aws:s3:::mybucket\"" + + " }," + + " \"object\":{ " + + " \"key\":\"HappyFace.jpg\"," + + " \"size\":1024," + + " \"eTag\":\"d41d8cd98f00b204e9800998ecf8427e\"," + + " \"versionId\":\"096fKKXTRTtl3on89fVO.nfljtsv6qko\"," + + " \"sequencer\":\"0055AED6DCD90281E5\"" + + " }" + + " }" + + " }" + + " ]" + + "}"; + + S3EventNotification event = S3EventNotification.fromJson(new ByteArrayInputStream(eventJson.getBytes())); + + assertThat(event.getRecords()).hasSize(1); + + // verify constructors + S3EventNotification expected = new S3EventNotification( + Collections.singletonList(new S3EventNotificationRecord( + "us-west-2", + "ObjectCreated:Put", + "aws:s3", + "1970-01-01T00:00:00.000Z", + "2.1", + new RequestParameters("127.0.0.1"), + new ResponseElements( + "FMyUVURIY8/IgAtTv8xRjskZQpcIZ9KG4V5Wp6S7S/JRWeUWerMUE5JgHvANOjpD", "C3D13FE58DE4C810"), + new S3( + "testConfigRule", + new S3Bucket( + "mybucket", + new UserIdentity("A3NL1KOZZKExample"), + "arn:aws:s3:::mybucket"), + new S3Object( + "HappyFace.jpg", + 1024L, + "d41d8cd98f00b204e9800998ecf8427e", + "096fKKXTRTtl3on89fVO.nfljtsv6qko", + "0055AED6DCD90281E5"), + "1.0" + ), + new UserIdentity("AIDAJDPLRKLG7UEXAMPLE") + )) + ); + assertThat(event).isEqualTo(expected); + + // verify getters + S3EventNotificationRecord rec = event.getRecords().get(0); + assertThat(rec).isNotNull(); + assertThat(rec.getAwsRegion()).isEqualTo("us-west-2"); + assertThat(rec.getEventName()).isEqualTo("ObjectCreated:Put"); + assertThat(rec.getEventTime()).isEqualTo(Instant.parse("1970-01-01T00:00:00.000Z")); + assertThat(rec.getEventVersion()).isEqualTo("2.1"); + + UserIdentity userIdentity = rec.getUserIdentity(); + assertThat(userIdentity).isNotNull(); + assertThat(userIdentity.getPrincipalId()).isEqualTo("AIDAJDPLRKLG7UEXAMPLE"); + + RequestParameters requestParameters = rec.getRequestParameters(); + assertThat(requestParameters).isNotNull(); + assertThat(requestParameters.getSourceIpAddress()).isEqualTo("127.0.0.1"); + + ResponseElements responseElements = rec.getResponseElements(); + assertThat(responseElements).isNotNull(); + assertThat(responseElements.getXAmzRequestId()).isEqualTo("C3D13FE58DE4C810"); + assertThat(responseElements.getXAmzId2()) + .isEqualTo("FMyUVURIY8/IgAtTv8xRjskZQpcIZ9KG4V5Wp6S7S/JRWeUWerMUE5JgHvANOjpD"); + + S3 s3 = rec.getS3(); + assertThat(s3).isNotNull(); + assertThat(s3.getS3SchemaVersion()).isEqualTo("1.0"); + assertThat(s3.getConfigurationId()).isEqualTo("testConfigRule"); + S3Bucket s3Bucket = s3.getBucket(); + assertThat(s3Bucket).isNotNull(); + assertThat(s3Bucket.getName()).isEqualTo("mybucket"); + assertThat(s3Bucket.getArn()).isEqualTo("arn:aws:s3:::mybucket"); + UserIdentity ownerIdentity = s3Bucket.getOwnerIdentity(); + assertThat(ownerIdentity).isNotNull(); + assertThat(ownerIdentity.getPrincipalId()).isEqualTo("A3NL1KOZZKExample"); + S3Object s3Object = s3.getObject(); + assertThat(s3Object).isNotNull(); + assertThat(s3Object.getKey()).isEqualTo("HappyFace.jpg"); + assertThat(s3Object.getETag()).isEqualTo("d41d8cd98f00b204e9800998ecf8427e"); + assertThat(s3Object.getSizeAsLong()).isEqualTo(1024L); + assertThat(s3Object.getVersionId()).isEqualTo("096fKKXTRTtl3on89fVO.nfljtsv6qko"); + assertThat(s3Object.getSequencer()).isEqualTo("0055AED6DCD90281E5"); + + assertThat(rec.getGlacierEventData()).isNull(); + assertThat(rec.getIntelligentTieringEventData()).isNull(); + assertThat(rec.getLifecycleEventData()).isNull(); + assertThat(rec.getReplicationEventData()).isNull(); + + } } diff --git a/services-custom/s3-transfer-manager/pom.xml b/services-custom/s3-transfer-manager/pom.xml index 4be85db87ea5..2bcad57a03ab 100644 --- a/services-custom/s3-transfer-manager/pom.xml +++ b/services-custom/s3-transfer-manager/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk aws-sdk-java-pom - 2.29.52 + 2.30.0 ../../pom.xml s3-transfer-manager diff --git a/services-custom/s3-transfer-manager/src/it/java/software/amazon/awssdk/transfer/s3/S3TransferManagerUploadPauseResumeIntegrationTest.java b/services-custom/s3-transfer-manager/src/it/java/software/amazon/awssdk/transfer/s3/S3TransferManagerUploadPauseResumeIntegrationTest.java index 1a49e5c618a4..f8e51246fa66 100644 --- a/services-custom/s3-transfer-manager/src/it/java/software/amazon/awssdk/transfer/s3/S3TransferManagerUploadPauseResumeIntegrationTest.java +++ b/services-custom/s3-transfer-manager/src/it/java/software/amazon/awssdk/transfer/s3/S3TransferManagerUploadPauseResumeIntegrationTest.java @@ -35,7 +35,6 @@ import software.amazon.awssdk.core.waiters.AsyncWaiter; import software.amazon.awssdk.core.waiters.Waiter; import software.amazon.awssdk.core.waiters.WaiterAcceptor; -import software.amazon.awssdk.services.s3.S3AsyncClient; import software.amazon.awssdk.services.s3.model.ListMultipartUploadsResponse; import software.amazon.awssdk.services.s3.model.ListPartsResponse; import software.amazon.awssdk.services.s3.model.NoSuchUploadException; diff --git a/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/DefaultFileUploadWireMockTest.java b/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/DefaultFileUploadWireMockTest.java index 79f487ea4d64..b6c562746380 100644 --- a/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/DefaultFileUploadWireMockTest.java +++ b/services-custom/s3-transfer-manager/src/test/java/software/amazon/awssdk/transfer/s3/internal/DefaultFileUploadWireMockTest.java @@ -123,12 +123,12 @@ void connectionFaultDuringUpload_shouldSaveStateOfUpload() { stubCreateMpuSuccessfulResponse(); - wireMock.stubFor(put(urlPathMatching("/bucket/key?partNumber=1&uploadId=uploadId")) + wireMock.stubFor(put(urlEqualTo("/bucket/key?partNumber=1&uploadId=uploadId")) .willReturn(aResponse() .withStatus(200) .withBody("1\"etag1\""))); - wireMock.stubFor(put(urlPathMatching("/bucket/key?partNumber=2&uploadId=uploadId")) + wireMock.stubFor(put(urlEqualTo("/bucket/key?partNumber=2&uploadId=uploadId")) .willReturn(aResponse() .withFault(Fault.CONNECTION_RESET_BY_PEER))); @@ -136,7 +136,8 @@ void connectionFaultDuringUpload_shouldSaveStateOfUpload() { FileUpload fileUpload = null; try { - tm.uploadFile(request); + fileUpload = tm.uploadFile(request); + fileUpload.completionFuture().join(); } catch (Exception e) { assertThat(e).isInstanceOf(CompletionException.class); ResumableFileUpload resumableFileUpload = fileUpload.pause(); diff --git a/services/accessanalyzer/pom.xml b/services/accessanalyzer/pom.xml index 205018e24252..91fcce27b883 100644 --- a/services/accessanalyzer/pom.xml +++ b/services/accessanalyzer/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 accessanalyzer AWS Java SDK :: Services :: AccessAnalyzer diff --git a/services/account/pom.xml b/services/account/pom.xml index fc78f5218d63..31b63e6d104a 100644 --- a/services/account/pom.xml +++ b/services/account/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 account AWS Java SDK :: Services :: Account diff --git a/services/acm/pom.xml b/services/acm/pom.xml index 81d3241a40d3..0cd785af68fd 100644 --- a/services/acm/pom.xml +++ b/services/acm/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 acm AWS Java SDK :: Services :: AWS Certificate Manager diff --git a/services/acmpca/pom.xml b/services/acmpca/pom.xml index 946011235397..0b5acebe5558 100644 --- a/services/acmpca/pom.xml +++ b/services/acmpca/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 acmpca AWS Java SDK :: Services :: ACM PCA diff --git a/services/amp/pom.xml b/services/amp/pom.xml index 47a9b5b97fae..874647c73d2b 100644 --- a/services/amp/pom.xml +++ b/services/amp/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 amp AWS Java SDK :: Services :: Amp diff --git a/services/amplify/pom.xml b/services/amplify/pom.xml index 226ee807910d..d05354d0e97f 100644 --- a/services/amplify/pom.xml +++ b/services/amplify/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 amplify AWS Java SDK :: Services :: Amplify diff --git a/services/amplifybackend/pom.xml b/services/amplifybackend/pom.xml index 68c70004e46d..43d8f1137db7 100644 --- a/services/amplifybackend/pom.xml +++ b/services/amplifybackend/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 amplifybackend AWS Java SDK :: Services :: Amplify Backend diff --git a/services/amplifyuibuilder/pom.xml b/services/amplifyuibuilder/pom.xml index f6a0bc4a7356..a1b45e7a1567 100644 --- a/services/amplifyuibuilder/pom.xml +++ b/services/amplifyuibuilder/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 amplifyuibuilder AWS Java SDK :: Services :: Amplify UI Builder diff --git a/services/apigateway/pom.xml b/services/apigateway/pom.xml index dddcba1658ba..0a16ba181ecf 100644 --- a/services/apigateway/pom.xml +++ b/services/apigateway/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 apigateway AWS Java SDK :: Services :: Amazon API Gateway diff --git a/services/apigateway/src/main/resources/codegen-resources/service-2.json b/services/apigateway/src/main/resources/codegen-resources/service-2.json index 2d551032fd4f..2602d85be713 100644 --- a/services/apigateway/src/main/resources/codegen-resources/service-2.json +++ b/services/apigateway/src/main/resources/codegen-resources/service-2.json @@ -2626,7 +2626,7 @@ }, "domainNameId":{ "shape":"String", - "documentation":"

    The identifier for the domain name resource. Supported only for private custom domain names.

    ", + "documentation":"

    The identifier for the domain name resource. Required for private custom domain names.

    ", "location":"querystring", "locationName":"domainNameId" }, @@ -4474,7 +4474,7 @@ }, "domainNameId":{ "shape":"String", - "documentation":"

    The identifier for the domain name resource. Supported only for private custom domain names.

    ", + "documentation":"

    The identifier for the domain name resource. Required for private custom domain names.

    ", "location":"querystring", "locationName":"domainNameId" } diff --git a/services/apigatewaymanagementapi/pom.xml b/services/apigatewaymanagementapi/pom.xml index 3c05064dbab2..653823778513 100644 --- a/services/apigatewaymanagementapi/pom.xml +++ b/services/apigatewaymanagementapi/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 apigatewaymanagementapi AWS Java SDK :: Services :: ApiGatewayManagementApi diff --git a/services/apigatewayv2/pom.xml b/services/apigatewayv2/pom.xml index 6d0ca9a52168..2a0fa615ad01 100644 --- a/services/apigatewayv2/pom.xml +++ b/services/apigatewayv2/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 apigatewayv2 AWS Java SDK :: Services :: ApiGatewayV2 diff --git a/services/appconfig/pom.xml b/services/appconfig/pom.xml index 9acaddc6f549..579997685c8f 100644 --- a/services/appconfig/pom.xml +++ b/services/appconfig/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 appconfig AWS Java SDK :: Services :: AppConfig diff --git a/services/appconfigdata/pom.xml b/services/appconfigdata/pom.xml index a2d2a24cea39..d6278185bde9 100644 --- a/services/appconfigdata/pom.xml +++ b/services/appconfigdata/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 appconfigdata AWS Java SDK :: Services :: App Config Data diff --git a/services/appfabric/pom.xml b/services/appfabric/pom.xml index f2fa769e613a..3b274c7a0d9b 100644 --- a/services/appfabric/pom.xml +++ b/services/appfabric/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 appfabric AWS Java SDK :: Services :: App Fabric diff --git a/services/appflow/pom.xml b/services/appflow/pom.xml index a975334e9a1e..ac90184ca104 100644 --- a/services/appflow/pom.xml +++ b/services/appflow/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 appflow AWS Java SDK :: Services :: Appflow diff --git a/services/appintegrations/pom.xml b/services/appintegrations/pom.xml index 773dd1f1d8b3..faeefee5ad23 100644 --- a/services/appintegrations/pom.xml +++ b/services/appintegrations/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 appintegrations AWS Java SDK :: Services :: App Integrations diff --git a/services/applicationautoscaling/pom.xml b/services/applicationautoscaling/pom.xml index 2cc0397adef7..38ec46c5a955 100644 --- a/services/applicationautoscaling/pom.xml +++ b/services/applicationautoscaling/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 applicationautoscaling AWS Java SDK :: Services :: AWS Application Auto Scaling diff --git a/services/applicationcostprofiler/pom.xml b/services/applicationcostprofiler/pom.xml index 4925a08afe67..9fa50ba68cf1 100644 --- a/services/applicationcostprofiler/pom.xml +++ b/services/applicationcostprofiler/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 applicationcostprofiler AWS Java SDK :: Services :: Application Cost Profiler diff --git a/services/applicationdiscovery/pom.xml b/services/applicationdiscovery/pom.xml index 0379ae0051a6..d36598b71a5b 100644 --- a/services/applicationdiscovery/pom.xml +++ b/services/applicationdiscovery/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 applicationdiscovery AWS Java SDK :: Services :: AWS Application Discovery Service diff --git a/services/applicationinsights/pom.xml b/services/applicationinsights/pom.xml index 6009b381dd44..554ad148bb44 100644 --- a/services/applicationinsights/pom.xml +++ b/services/applicationinsights/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 applicationinsights AWS Java SDK :: Services :: Application Insights diff --git a/services/applicationsignals/pom.xml b/services/applicationsignals/pom.xml index 3fb4bc5fbe6f..69b25d271825 100644 --- a/services/applicationsignals/pom.xml +++ b/services/applicationsignals/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 applicationsignals AWS Java SDK :: Services :: Application Signals diff --git a/services/appmesh/pom.xml b/services/appmesh/pom.xml index 9191a6a87e16..e80ea2d631d2 100644 --- a/services/appmesh/pom.xml +++ b/services/appmesh/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 appmesh AWS Java SDK :: Services :: App Mesh diff --git a/services/apprunner/pom.xml b/services/apprunner/pom.xml index bb6fa58806a6..e057ad15765e 100644 --- a/services/apprunner/pom.xml +++ b/services/apprunner/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 apprunner AWS Java SDK :: Services :: App Runner diff --git a/services/appstream/pom.xml b/services/appstream/pom.xml index 04bafc2ede6f..6d1c9bbcbbb8 100644 --- a/services/appstream/pom.xml +++ b/services/appstream/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 appstream AWS Java SDK :: Services :: Amazon AppStream diff --git a/services/appsync/pom.xml b/services/appsync/pom.xml index 871f708b4468..4d958b6b4925 100644 --- a/services/appsync/pom.xml +++ b/services/appsync/pom.xml @@ -21,7 +21,7 @@ services software.amazon.awssdk - 2.29.52 + 2.30.0 appsync diff --git a/services/apptest/pom.xml b/services/apptest/pom.xml index 606aae063d34..29394aa6784e 100644 --- a/services/apptest/pom.xml +++ b/services/apptest/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 apptest AWS Java SDK :: Services :: App Test diff --git a/services/arczonalshift/pom.xml b/services/arczonalshift/pom.xml index 04538ab9720e..c15f80b26176 100644 --- a/services/arczonalshift/pom.xml +++ b/services/arczonalshift/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 arczonalshift AWS Java SDK :: Services :: ARC Zonal Shift diff --git a/services/artifact/pom.xml b/services/artifact/pom.xml index 5a779599cf9b..9bc53aa491bd 100644 --- a/services/artifact/pom.xml +++ b/services/artifact/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 artifact AWS Java SDK :: Services :: Artifact diff --git a/services/athena/pom.xml b/services/athena/pom.xml index 0969d9d82975..bccb73be8baf 100644 --- a/services/athena/pom.xml +++ b/services/athena/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 athena AWS Java SDK :: Services :: Amazon Athena diff --git a/services/auditmanager/pom.xml b/services/auditmanager/pom.xml index 354236453455..dee7df8a28d9 100644 --- a/services/auditmanager/pom.xml +++ b/services/auditmanager/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 auditmanager AWS Java SDK :: Services :: Audit Manager diff --git a/services/autoscaling/pom.xml b/services/autoscaling/pom.xml index 6db31e9fba5c..9859d7146ecc 100644 --- a/services/autoscaling/pom.xml +++ b/services/autoscaling/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 autoscaling AWS Java SDK :: Services :: Auto Scaling diff --git a/services/autoscalingplans/pom.xml b/services/autoscalingplans/pom.xml index 1a6a5566cdbf..235f7e6340c1 100644 --- a/services/autoscalingplans/pom.xml +++ b/services/autoscalingplans/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 autoscalingplans AWS Java SDK :: Services :: Auto Scaling Plans diff --git a/services/b2bi/pom.xml b/services/b2bi/pom.xml index 659b675fac67..997bf3d62abd 100644 --- a/services/b2bi/pom.xml +++ b/services/b2bi/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 b2bi AWS Java SDK :: Services :: B2 Bi diff --git a/services/backup/pom.xml b/services/backup/pom.xml index 143e4f3589f5..371439de1c36 100644 --- a/services/backup/pom.xml +++ b/services/backup/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 backup AWS Java SDK :: Services :: Backup diff --git a/services/backupgateway/pom.xml b/services/backupgateway/pom.xml index e76c4c01d228..0c7cf7eef720 100644 --- a/services/backupgateway/pom.xml +++ b/services/backupgateway/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 backupgateway AWS Java SDK :: Services :: Backup Gateway diff --git a/services/backupsearch/pom.xml b/services/backupsearch/pom.xml index ba2958a049fd..f4963b2a62b8 100644 --- a/services/backupsearch/pom.xml +++ b/services/backupsearch/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 backupsearch AWS Java SDK :: Services :: Backup Search diff --git a/services/batch/pom.xml b/services/batch/pom.xml index 8e0dbd85830a..4bde81da4803 100644 --- a/services/batch/pom.xml +++ b/services/batch/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 batch AWS Java SDK :: Services :: AWS Batch diff --git a/services/bcmdataexports/pom.xml b/services/bcmdataexports/pom.xml index ca1eddca3c90..0015a90c9b9d 100644 --- a/services/bcmdataexports/pom.xml +++ b/services/bcmdataexports/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 bcmdataexports AWS Java SDK :: Services :: BCM Data Exports diff --git a/services/bcmpricingcalculator/pom.xml b/services/bcmpricingcalculator/pom.xml index e5434adb2037..91583b4d88b4 100644 --- a/services/bcmpricingcalculator/pom.xml +++ b/services/bcmpricingcalculator/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 bcmpricingcalculator AWS Java SDK :: Services :: BCM Pricing Calculator diff --git a/services/bedrock/pom.xml b/services/bedrock/pom.xml index f51d9cbe310b..69f04fb7b9b1 100644 --- a/services/bedrock/pom.xml +++ b/services/bedrock/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 bedrock AWS Java SDK :: Services :: Bedrock diff --git a/services/bedrockagent/pom.xml b/services/bedrockagent/pom.xml index 2dfbdc65537a..32bc831741ae 100644 --- a/services/bedrockagent/pom.xml +++ b/services/bedrockagent/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 bedrockagent AWS Java SDK :: Services :: Bedrock Agent diff --git a/services/bedrockagentruntime/pom.xml b/services/bedrockagentruntime/pom.xml index 9c8f7abfcd28..5c33e8fe5f94 100644 --- a/services/bedrockagentruntime/pom.xml +++ b/services/bedrockagentruntime/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 bedrockagentruntime AWS Java SDK :: Services :: Bedrock Agent Runtime diff --git a/services/bedrockagentruntime/src/main/resources/codegen-resources/service-2.json b/services/bedrockagentruntime/src/main/resources/codegen-resources/service-2.json index 36c06b21b65d..5f1192615eab 100644 --- a/services/bedrockagentruntime/src/main/resources/codegen-resources/service-2.json +++ b/services/bedrockagentruntime/src/main/resources/codegen-resources/service-2.json @@ -102,7 +102,7 @@ {"shape":"AccessDeniedException"}, {"shape":"ServiceQuotaExceededException"} ], - "documentation":"

    The CLI doesn't support streaming operations in Amazon Bedrock, including InvokeAgent.

    Sends a prompt for the agent to process and respond to. Note the following fields for the request:

    • To continue the same conversation with an agent, use the same sessionId value in the request.

    • To activate trace enablement, turn enableTrace to true. Trace enablement helps you follow the agent's reasoning process that led it to the information it processed, the actions it took, and the final result it yielded. For more information, see Trace enablement.

    • To stream agent responses, make sure that only orchestration prompt is enabled. Agent streaming is not supported for the following steps:

      • Pre-processing

      • Post-processing

      • Agent with 1 Knowledge base and User Input not enabled

    • End a conversation by setting endSession to true.

    • In the sessionState object, you can include attributes for the session or prompt or, if you configured an action group to return control, results from invocation of the action group.

    The response is returned in the bytes field of the chunk object.

    • The attribution object contains citations for parts of the response.

    • If you set enableTrace to true in the request, you can trace the agent's steps and reasoning process that led it to the response.

    • If the action predicted was configured to return control, the response returns parameters for the action, elicited from the user, in the returnControl field.

    • Errors are also surfaced in the response.

    " + "documentation":"

    Sends a prompt for the agent to process and respond to. Note the following fields for the request:

    • To continue the same conversation with an agent, use the same sessionId value in the request.

    • To activate trace enablement, turn enableTrace to true. Trace enablement helps you follow the agent's reasoning process that led it to the information it processed, the actions it took, and the final result it yielded. For more information, see Trace enablement.

    • To stream agent responses, make sure that only orchestration prompt is enabled. Agent streaming is not supported for the following steps:

      • Pre-processing

      • Post-processing

      • Agent with 1 Knowledge base and User Input not enabled

    • End a conversation by setting endSession to true.

    • In the sessionState object, you can include attributes for the session or prompt or, if you configured an action group to return control, results from invocation of the action group.

    The response contains both chunk and trace attributes.

    The final response is returned in the bytes field of the chunk object. The InvokeAgent returns one chunk for the entire interaction.

    • The attribution object contains citations for parts of the response.

    • If you set enableTrace to true in the request, you can trace the agent's steps and reasoning process that led it to the response.

    • If the action predicted was configured to return control, the response returns parameters for the action, elicited from the user, in the returnControl field.

    • Errors are also surfaced in the response.

    " }, "InvokeFlow":{ "name":"InvokeFlow", @@ -146,7 +146,7 @@ {"shape":"AccessDeniedException"}, {"shape":"ServiceQuotaExceededException"} ], - "documentation":"

    Invokes an inline Amazon Bedrock agent using the configurations you provide with the request.

    • Specify the following fields for security purposes.

      • (Optional) customerEncryptionKeyArn – The Amazon Resource Name (ARN) of a KMS key to encrypt the creation of the agent.

      • (Optional) idleSessionTTLinSeconds – Specify the number of seconds for which the agent should maintain session information. After this time expires, the subsequent InvokeInlineAgent request begins a new session.

    • To override the default prompt behavior for agent orchestration and to use advanced prompts, include a promptOverrideConfiguration object. For more information, see Advanced prompts.

    • The agent instructions will not be honored if your agent has only one knowledge base, uses default prompts, has no action group, and user input is disabled.

    The CLI doesn't support streaming operations in Amazon Bedrock, including InvokeInlineAgent.

    " + "documentation":"

    Invokes an inline Amazon Bedrock agent using the configurations you provide with the request.

    • Specify the following fields for security purposes.

      • (Optional) customerEncryptionKeyArn – The Amazon Resource Name (ARN) of a KMS key to encrypt the creation of the agent.

      • (Optional) idleSessionTTLinSeconds – Specify the number of seconds for which the agent should maintain session information. After this time expires, the subsequent InvokeInlineAgent request begins a new session.

    • To override the default prompt behavior for agent orchestration and to use advanced prompts, include a promptOverrideConfiguration object. For more information, see Advanced prompts.

    • The agent instructions will not be honored if your agent has only one knowledge base, uses default prompts, has no action group, and user input is disabled.

    " }, "OptimizePrompt":{ "name":"OptimizePrompt", @@ -2903,6 +2903,10 @@ "documentation":"

    The unique identifier of the session. Use the same value across requests to continue the same conversation.

    ", "location":"uri", "locationName":"sessionId" + }, + "streamingConfigurations":{ + "shape":"StreamingConfigurations", + "documentation":"

    Specifies the configurations for streaming.

    To use agent streaming, you need permissions to perform the bedrock:InvokeModelWithResponseStream action.

    " } } }, diff --git a/services/bedrockdataautomation/pom.xml b/services/bedrockdataautomation/pom.xml index d8c4f85b1b65..cd4262062ac0 100644 --- a/services/bedrockdataautomation/pom.xml +++ b/services/bedrockdataautomation/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 bedrockdataautomation AWS Java SDK :: Services :: Bedrock Data Automation diff --git a/services/bedrockdataautomationruntime/pom.xml b/services/bedrockdataautomationruntime/pom.xml index 6a52e3d2a75f..84ecc4d7bf68 100644 --- a/services/bedrockdataautomationruntime/pom.xml +++ b/services/bedrockdataautomationruntime/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 bedrockdataautomationruntime AWS Java SDK :: Services :: Bedrock Data Automation Runtime diff --git a/services/bedrockruntime/pom.xml b/services/bedrockruntime/pom.xml index b2e4b7f5c11e..4bd3c2a89897 100644 --- a/services/bedrockruntime/pom.xml +++ b/services/bedrockruntime/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 bedrockruntime AWS Java SDK :: Services :: Bedrock Runtime diff --git a/services/billing/pom.xml b/services/billing/pom.xml index 217f01d05822..26c7dfffaed5 100644 --- a/services/billing/pom.xml +++ b/services/billing/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 billing AWS Java SDK :: Services :: Billing diff --git a/services/billingconductor/pom.xml b/services/billingconductor/pom.xml index d2486d26f112..7784781ee923 100644 --- a/services/billingconductor/pom.xml +++ b/services/billingconductor/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 billingconductor AWS Java SDK :: Services :: Billingconductor diff --git a/services/braket/pom.xml b/services/braket/pom.xml index 6fef25efac0b..5877a8ff7971 100644 --- a/services/braket/pom.xml +++ b/services/braket/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 braket AWS Java SDK :: Services :: Braket diff --git a/services/budgets/pom.xml b/services/budgets/pom.xml index eb88a84b7092..a0c4770e527f 100644 --- a/services/budgets/pom.xml +++ b/services/budgets/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 budgets AWS Java SDK :: Services :: AWS Budgets diff --git a/services/chatbot/pom.xml b/services/chatbot/pom.xml index 2e68cc61d4c9..aec6edd394c7 100644 --- a/services/chatbot/pom.xml +++ b/services/chatbot/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 chatbot AWS Java SDK :: Services :: Chatbot diff --git a/services/chime/pom.xml b/services/chime/pom.xml index d0f010ea73be..08703cccf716 100644 --- a/services/chime/pom.xml +++ b/services/chime/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 chime AWS Java SDK :: Services :: Chime diff --git a/services/chimesdkidentity/pom.xml b/services/chimesdkidentity/pom.xml index eb59e65ea816..f5da08089d20 100644 --- a/services/chimesdkidentity/pom.xml +++ b/services/chimesdkidentity/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 chimesdkidentity AWS Java SDK :: Services :: Chime SDK Identity diff --git a/services/chimesdkmediapipelines/pom.xml b/services/chimesdkmediapipelines/pom.xml index d1f9ee3b211c..1ebe70974821 100644 --- a/services/chimesdkmediapipelines/pom.xml +++ b/services/chimesdkmediapipelines/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 chimesdkmediapipelines AWS Java SDK :: Services :: Chime SDK Media Pipelines diff --git a/services/chimesdkmeetings/pom.xml b/services/chimesdkmeetings/pom.xml index 27226e7c4456..f4c22fae308c 100644 --- a/services/chimesdkmeetings/pom.xml +++ b/services/chimesdkmeetings/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 chimesdkmeetings AWS Java SDK :: Services :: Chime SDK Meetings diff --git a/services/chimesdkmessaging/pom.xml b/services/chimesdkmessaging/pom.xml index 0b6fe95441c0..57186a4d36bb 100644 --- a/services/chimesdkmessaging/pom.xml +++ b/services/chimesdkmessaging/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 chimesdkmessaging AWS Java SDK :: Services :: Chime SDK Messaging diff --git a/services/chimesdkvoice/pom.xml b/services/chimesdkvoice/pom.xml index 8bb4d1ea9c0e..cedc624147e0 100644 --- a/services/chimesdkvoice/pom.xml +++ b/services/chimesdkvoice/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 chimesdkvoice AWS Java SDK :: Services :: Chime SDK Voice diff --git a/services/cleanrooms/pom.xml b/services/cleanrooms/pom.xml index f8a909f5bffa..2dbf51017fef 100644 --- a/services/cleanrooms/pom.xml +++ b/services/cleanrooms/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 cleanrooms AWS Java SDK :: Services :: Clean Rooms diff --git a/services/cleanroomsml/pom.xml b/services/cleanroomsml/pom.xml index ae4bd2c559e5..c4497a55acec 100644 --- a/services/cleanroomsml/pom.xml +++ b/services/cleanroomsml/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 cleanroomsml AWS Java SDK :: Services :: Clean Rooms ML diff --git a/services/cloud9/pom.xml b/services/cloud9/pom.xml index 692013e84f26..995e33a8107d 100644 --- a/services/cloud9/pom.xml +++ b/services/cloud9/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 cloud9 diff --git a/services/cloudcontrol/pom.xml b/services/cloudcontrol/pom.xml index 6284d9e1642a..78d9807b3a41 100644 --- a/services/cloudcontrol/pom.xml +++ b/services/cloudcontrol/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 cloudcontrol AWS Java SDK :: Services :: Cloud Control diff --git a/services/clouddirectory/pom.xml b/services/clouddirectory/pom.xml index 7a81da927407..d745e3f7210a 100644 --- a/services/clouddirectory/pom.xml +++ b/services/clouddirectory/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 clouddirectory AWS Java SDK :: Services :: Amazon CloudDirectory diff --git a/services/cloudformation/pom.xml b/services/cloudformation/pom.xml index aad43da62d08..7fddd6d49259 100644 --- a/services/cloudformation/pom.xml +++ b/services/cloudformation/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 cloudformation AWS Java SDK :: Services :: AWS CloudFormation diff --git a/services/cloudfront/pom.xml b/services/cloudfront/pom.xml index 0357dc36a4ae..7c8eb700d6cc 100644 --- a/services/cloudfront/pom.xml +++ b/services/cloudfront/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 cloudfront AWS Java SDK :: Services :: Amazon CloudFront diff --git a/services/cloudfrontkeyvaluestore/pom.xml b/services/cloudfrontkeyvaluestore/pom.xml index 73e49726eaac..60aab7d783c2 100644 --- a/services/cloudfrontkeyvaluestore/pom.xml +++ b/services/cloudfrontkeyvaluestore/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 cloudfrontkeyvaluestore AWS Java SDK :: Services :: Cloud Front Key Value Store diff --git a/services/cloudhsm/pom.xml b/services/cloudhsm/pom.xml index c5e2b2fb0138..ad4e28dc4c1d 100644 --- a/services/cloudhsm/pom.xml +++ b/services/cloudhsm/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 cloudhsm AWS Java SDK :: Services :: AWS CloudHSM diff --git a/services/cloudhsmv2/pom.xml b/services/cloudhsmv2/pom.xml index 557af0ce27f9..a053bfa07921 100644 --- a/services/cloudhsmv2/pom.xml +++ b/services/cloudhsmv2/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 cloudhsmv2 diff --git a/services/cloudsearch/pom.xml b/services/cloudsearch/pom.xml index 2060b79579a6..c858bffdd057 100644 --- a/services/cloudsearch/pom.xml +++ b/services/cloudsearch/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 cloudsearch AWS Java SDK :: Services :: Amazon CloudSearch diff --git a/services/cloudsearchdomain/pom.xml b/services/cloudsearchdomain/pom.xml index 81ccf29abad0..8e75d2cbe7a9 100644 --- a/services/cloudsearchdomain/pom.xml +++ b/services/cloudsearchdomain/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 cloudsearchdomain AWS Java SDK :: Services :: Amazon CloudSearch Domain diff --git a/services/cloudtrail/pom.xml b/services/cloudtrail/pom.xml index 15aff0abd9ca..ce242f65d381 100644 --- a/services/cloudtrail/pom.xml +++ b/services/cloudtrail/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 cloudtrail AWS Java SDK :: Services :: AWS CloudTrail diff --git a/services/cloudtraildata/pom.xml b/services/cloudtraildata/pom.xml index 3262cfbdb142..f2751d965205 100644 --- a/services/cloudtraildata/pom.xml +++ b/services/cloudtraildata/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 cloudtraildata AWS Java SDK :: Services :: Cloud Trail Data diff --git a/services/cloudwatch/pom.xml b/services/cloudwatch/pom.xml index 0bc808b90df9..847d61d6289b 100644 --- a/services/cloudwatch/pom.xml +++ b/services/cloudwatch/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 cloudwatch AWS Java SDK :: Services :: Amazon CloudWatch diff --git a/services/cloudwatchevents/pom.xml b/services/cloudwatchevents/pom.xml index 287313205e0d..77e10d05a141 100644 --- a/services/cloudwatchevents/pom.xml +++ b/services/cloudwatchevents/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 cloudwatchevents AWS Java SDK :: Services :: Amazon CloudWatch Events diff --git a/services/cloudwatchlogs/pom.xml b/services/cloudwatchlogs/pom.xml index cae0ddca9a59..0f9c4ffbb0bf 100644 --- a/services/cloudwatchlogs/pom.xml +++ b/services/cloudwatchlogs/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 cloudwatchlogs AWS Java SDK :: Services :: Amazon CloudWatch Logs diff --git a/services/codeartifact/pom.xml b/services/codeartifact/pom.xml index 3cb0cf4ac7ec..20fd9ffe93a9 100644 --- a/services/codeartifact/pom.xml +++ b/services/codeartifact/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 codeartifact AWS Java SDK :: Services :: Codeartifact diff --git a/services/codebuild/pom.xml b/services/codebuild/pom.xml index 321e417e81a2..bf347ce73825 100644 --- a/services/codebuild/pom.xml +++ b/services/codebuild/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 codebuild AWS Java SDK :: Services :: AWS Code Build diff --git a/services/codecatalyst/pom.xml b/services/codecatalyst/pom.xml index 35b2fef2ed70..52648f7bb478 100644 --- a/services/codecatalyst/pom.xml +++ b/services/codecatalyst/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 codecatalyst AWS Java SDK :: Services :: Code Catalyst diff --git a/services/codecommit/pom.xml b/services/codecommit/pom.xml index 0c63003dcce8..b25c37ef2348 100644 --- a/services/codecommit/pom.xml +++ b/services/codecommit/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 codecommit AWS Java SDK :: Services :: AWS CodeCommit diff --git a/services/codeconnections/pom.xml b/services/codeconnections/pom.xml index 83feba22a11f..65127f0c87c7 100644 --- a/services/codeconnections/pom.xml +++ b/services/codeconnections/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 codeconnections AWS Java SDK :: Services :: Code Connections diff --git a/services/codedeploy/pom.xml b/services/codedeploy/pom.xml index d2d097d71115..c351c6681730 100644 --- a/services/codedeploy/pom.xml +++ b/services/codedeploy/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 codedeploy AWS Java SDK :: Services :: AWS CodeDeploy diff --git a/services/codeguruprofiler/pom.xml b/services/codeguruprofiler/pom.xml index b594a5d83607..4db0a99ee30b 100644 --- a/services/codeguruprofiler/pom.xml +++ b/services/codeguruprofiler/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 codeguruprofiler AWS Java SDK :: Services :: CodeGuruProfiler diff --git a/services/codegurureviewer/pom.xml b/services/codegurureviewer/pom.xml index a8d685c35593..f2acb8897af6 100644 --- a/services/codegurureviewer/pom.xml +++ b/services/codegurureviewer/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 codegurureviewer AWS Java SDK :: Services :: CodeGuru Reviewer diff --git a/services/codegurusecurity/pom.xml b/services/codegurusecurity/pom.xml index 2306706f52ad..16a9ae16c1f9 100644 --- a/services/codegurusecurity/pom.xml +++ b/services/codegurusecurity/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 codegurusecurity AWS Java SDK :: Services :: Code Guru Security diff --git a/services/codepipeline/pom.xml b/services/codepipeline/pom.xml index f8cac3729f92..bd798f0d6c1a 100644 --- a/services/codepipeline/pom.xml +++ b/services/codepipeline/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 codepipeline AWS Java SDK :: Services :: AWS CodePipeline diff --git a/services/codestarconnections/pom.xml b/services/codestarconnections/pom.xml index a3b30d5da4d7..361f98cd48f8 100644 --- a/services/codestarconnections/pom.xml +++ b/services/codestarconnections/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 codestarconnections AWS Java SDK :: Services :: CodeStar connections diff --git a/services/codestarnotifications/pom.xml b/services/codestarnotifications/pom.xml index 734197ca8d51..b0ca94ea347d 100644 --- a/services/codestarnotifications/pom.xml +++ b/services/codestarnotifications/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 codestarnotifications AWS Java SDK :: Services :: Codestar Notifications diff --git a/services/cognitoidentity/pom.xml b/services/cognitoidentity/pom.xml index acbf404cc134..a87d2a940ad0 100644 --- a/services/cognitoidentity/pom.xml +++ b/services/cognitoidentity/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 cognitoidentity AWS Java SDK :: Services :: Amazon Cognito Identity diff --git a/services/cognitoidentity/src/main/resources/codegen-resources/endpoint-rule-set.json b/services/cognitoidentity/src/main/resources/codegen-resources/endpoint-rule-set.json index 348fc5c4bb07..96572525e550 100644 --- a/services/cognitoidentity/src/main/resources/codegen-resources/endpoint-rule-set.json +++ b/services/cognitoidentity/src/main/resources/codegen-resources/endpoint-rule-set.json @@ -166,6 +166,82 @@ } ], "rules": [ + { + "conditions": [ + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-east-1" + ] + } + ], + "endpoint": { + "url": "https://cognito-identity-fips.us-east-1.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [ + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-east-2" + ] + } + ], + "endpoint": { + "url": "https://cognito-identity-fips.us-east-2.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [ + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-west-1" + ] + } + ], + "endpoint": { + "url": "https://cognito-identity-fips.us-west-1.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, + { + "conditions": [ + { + "fn": "stringEquals", + "argv": [ + { + "ref": "Region" + }, + "us-west-2" + ] + } + ], + "endpoint": { + "url": "https://cognito-identity-fips.us-west-2.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, { "conditions": [], "endpoint": { @@ -270,6 +346,31 @@ } ], "rules": [ + { + "conditions": [ + { + "fn": "stringEquals", + "argv": [ + "aws", + { + "fn": "getAttr", + "argv": [ + { + "ref": "PartitionResult" + }, + "name" + ] + } + ] + } + ], + "endpoint": { + "url": "https://cognito-identity.{Region}.amazonaws.com", + "properties": {}, + "headers": {} + }, + "type": "endpoint" + }, { "conditions": [], "endpoint": { diff --git a/services/cognitoidentity/src/main/resources/codegen-resources/endpoint-tests.json b/services/cognitoidentity/src/main/resources/codegen-resources/endpoint-tests.json index cfc617981e47..506b46098bbe 100644 --- a/services/cognitoidentity/src/main/resources/codegen-resources/endpoint-tests.json +++ b/services/cognitoidentity/src/main/resources/codegen-resources/endpoint-tests.json @@ -1,237 +1,159 @@ { "testCases": [ { - "documentation": "For region ap-northeast-1 with FIPS disabled and DualStack disabled", - "expect": { - "endpoint": { - "url": "https://cognito-identity.ap-northeast-1.amazonaws.com" - } - }, - "params": { - "Region": "ap-northeast-1", - "UseFIPS": false, - "UseDualStack": false - } - }, - { - "documentation": "For region ap-northeast-2 with FIPS disabled and DualStack disabled", - "expect": { - "endpoint": { - "url": "https://cognito-identity.ap-northeast-2.amazonaws.com" - } - }, - "params": { - "Region": "ap-northeast-2", - "UseFIPS": false, - "UseDualStack": false - } - }, - { - "documentation": "For region ap-south-1 with FIPS disabled and DualStack disabled", - "expect": { - "endpoint": { - "url": "https://cognito-identity.ap-south-1.amazonaws.com" - } - }, - "params": { - "Region": "ap-south-1", - "UseFIPS": false, - "UseDualStack": false - } - }, - { - "documentation": "For region ap-southeast-1 with FIPS disabled and DualStack disabled", - "expect": { - "endpoint": { - "url": "https://cognito-identity.ap-southeast-1.amazonaws.com" - } - }, - "params": { - "Region": "ap-southeast-1", - "UseFIPS": false, - "UseDualStack": false - } - }, - { - "documentation": "For region ap-southeast-2 with FIPS disabled and DualStack disabled", - "expect": { - "endpoint": { - "url": "https://cognito-identity.ap-southeast-2.amazonaws.com" - } - }, - "params": { - "Region": "ap-southeast-2", - "UseFIPS": false, - "UseDualStack": false - } - }, - { - "documentation": "For region ca-central-1 with FIPS disabled and DualStack disabled", + "documentation": "For region us-east-1 with FIPS disabled and DualStack disabled", "expect": { "endpoint": { - "url": "https://cognito-identity.ca-central-1.amazonaws.com" + "url": "https://cognito-identity.us-east-1.amazonaws.com" } }, "params": { - "Region": "ca-central-1", + "Region": "us-east-1", "UseFIPS": false, "UseDualStack": false } }, { - "documentation": "For region eu-central-1 with FIPS disabled and DualStack disabled", + "documentation": "For region us-east-1 with FIPS enabled and DualStack disabled", "expect": { "endpoint": { - "url": "https://cognito-identity.eu-central-1.amazonaws.com" + "url": "https://cognito-identity-fips.us-east-1.amazonaws.com" } }, "params": { - "Region": "eu-central-1", - "UseFIPS": false, + "Region": "us-east-1", + "UseFIPS": true, "UseDualStack": false } }, { - "documentation": "For region eu-north-1 with FIPS disabled and DualStack disabled", + "documentation": "For region us-east-1 with FIPS disabled and DualStack enabled", "expect": { "endpoint": { - "url": "https://cognito-identity.eu-north-1.amazonaws.com" + "url": "https://cognito-identity.us-east-1.amazonaws.com" } }, "params": { - "Region": "eu-north-1", + "Region": "us-east-1", "UseFIPS": false, - "UseDualStack": false + "UseDualStack": true } }, { - "documentation": "For region eu-west-1 with FIPS disabled and DualStack disabled", + "documentation": "For region us-east-1 with FIPS enabled and DualStack enabled", "expect": { "endpoint": { - "url": "https://cognito-identity.eu-west-1.amazonaws.com" + "url": "https://cognito-identity-fips.us-east-1.amazonaws.com" } }, "params": { - "Region": "eu-west-1", - "UseFIPS": false, - "UseDualStack": false + "Region": "us-east-1", + "UseFIPS": true, + "UseDualStack": true } }, { - "documentation": "For region eu-west-2 with FIPS disabled and DualStack disabled", + "documentation": "For region us-east-2 with FIPS disabled and DualStack disabled", "expect": { "endpoint": { - "url": "https://cognito-identity.eu-west-2.amazonaws.com" + "url": "https://cognito-identity.us-east-2.amazonaws.com" } }, "params": { - "Region": "eu-west-2", + "Region": "us-east-2", "UseFIPS": false, "UseDualStack": false } }, { - "documentation": "For region eu-west-3 with FIPS disabled and DualStack disabled", + "documentation": "For region us-east-2 with FIPS enabled and DualStack disabled", "expect": { "endpoint": { - "url": "https://cognito-identity.eu-west-3.amazonaws.com" + "url": "https://cognito-identity-fips.us-east-2.amazonaws.com" } }, "params": { - "Region": "eu-west-3", - "UseFIPS": false, + "Region": "us-east-2", + "UseFIPS": true, "UseDualStack": false } }, { - "documentation": "For region me-south-1 with FIPS disabled and DualStack disabled", + "documentation": "For region us-east-2 with FIPS disabled and DualStack enabled", "expect": { "endpoint": { - "url": "https://cognito-identity.me-south-1.amazonaws.com" + "url": "https://cognito-identity.us-east-2.amazonaws.com" } }, "params": { - "Region": "me-south-1", + "Region": "us-east-2", "UseFIPS": false, - "UseDualStack": false + "UseDualStack": true } }, { - "documentation": "For region sa-east-1 with FIPS disabled and DualStack disabled", + "documentation": "For region us-east-2 with FIPS enabled and DualStack enabled", "expect": { "endpoint": { - "url": "https://cognito-identity.sa-east-1.amazonaws.com" + "url": "https://cognito-identity-fips.us-east-2.amazonaws.com" } }, "params": { - "Region": "sa-east-1", - "UseFIPS": false, - "UseDualStack": false + "Region": "us-east-2", + "UseFIPS": true, + "UseDualStack": true } }, { - "documentation": "For region us-east-1 with FIPS disabled and DualStack disabled", + "documentation": "For region us-west-1 with FIPS disabled and DualStack disabled", "expect": { "endpoint": { - "url": "https://cognito-identity.us-east-1.amazonaws.com" + "url": "https://cognito-identity.us-west-1.amazonaws.com" } }, "params": { - "Region": "us-east-1", + "Region": "us-west-1", "UseFIPS": false, "UseDualStack": false } }, { - "documentation": "For region us-east-1 with FIPS enabled and DualStack disabled", + "documentation": "For region us-west-1 with FIPS enabled and DualStack disabled", "expect": { "endpoint": { - "url": "https://cognito-identity-fips.us-east-1.amazonaws.com" + "url": "https://cognito-identity-fips.us-west-1.amazonaws.com" } }, "params": { - "Region": "us-east-1", + "Region": "us-west-1", "UseFIPS": true, "UseDualStack": false } }, { - "documentation": "For region us-east-2 with FIPS disabled and DualStack disabled", + "documentation": "For region us-west-1 with FIPS disabled and DualStack enabled", "expect": { "endpoint": { - "url": "https://cognito-identity.us-east-2.amazonaws.com" + "url": "https://cognito-identity.us-west-1.amazonaws.com" } }, "params": { - "Region": "us-east-2", + "Region": "us-west-1", "UseFIPS": false, - "UseDualStack": false - } - }, - { - "documentation": "For region us-east-2 with FIPS enabled and DualStack disabled", - "expect": { - "endpoint": { - "url": "https://cognito-identity-fips.us-east-2.amazonaws.com" - } - }, - "params": { - "Region": "us-east-2", - "UseFIPS": true, - "UseDualStack": false + "UseDualStack": true } }, { - "documentation": "For region us-west-1 with FIPS disabled and DualStack disabled", + "documentation": "For region us-west-1 with FIPS enabled and DualStack enabled", "expect": { "endpoint": { - "url": "https://cognito-identity.us-west-1.amazonaws.com" + "url": "https://cognito-identity-fips.us-west-1.amazonaws.com" } }, "params": { "Region": "us-west-1", - "UseFIPS": false, - "UseDualStack": false + "UseFIPS": true, + "UseDualStack": true } }, { @@ -261,28 +183,28 @@ } }, { - "documentation": "For region us-east-1 with FIPS enabled and DualStack enabled", + "documentation": "For region us-west-2 with FIPS disabled and DualStack enabled", "expect": { "endpoint": { - "url": "https://cognito-identity-fips.us-east-1.api.aws" + "url": "https://cognito-identity.us-west-2.amazonaws.com" } }, "params": { - "Region": "us-east-1", - "UseFIPS": true, + "Region": "us-west-2", + "UseFIPS": false, "UseDualStack": true } }, { - "documentation": "For region us-east-1 with FIPS disabled and DualStack enabled", + "documentation": "For region us-west-2 with FIPS enabled and DualStack enabled", "expect": { "endpoint": { - "url": "https://cognito-identity.us-east-1.api.aws" + "url": "https://cognito-identity-fips.us-west-2.amazonaws.com" } }, "params": { - "Region": "us-east-1", - "UseFIPS": false, + "Region": "us-west-2", + "UseFIPS": true, "UseDualStack": true } }, diff --git a/services/cognitoidentityprovider/pom.xml b/services/cognitoidentityprovider/pom.xml index e0e4c93c1d99..60fc98fc1c97 100644 --- a/services/cognitoidentityprovider/pom.xml +++ b/services/cognitoidentityprovider/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 cognitoidentityprovider AWS Java SDK :: Services :: Amazon Cognito Identity Provider Service diff --git a/services/cognitosync/pom.xml b/services/cognitosync/pom.xml index 2980c5b85a04..23c0ec9670b7 100644 --- a/services/cognitosync/pom.xml +++ b/services/cognitosync/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 cognitosync AWS Java SDK :: Services :: Amazon Cognito Sync diff --git a/services/comprehend/pom.xml b/services/comprehend/pom.xml index d45df0682d04..e0eb8e544b06 100644 --- a/services/comprehend/pom.xml +++ b/services/comprehend/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 comprehend diff --git a/services/comprehendmedical/pom.xml b/services/comprehendmedical/pom.xml index a5fe71c2e1cb..6ccaf527771d 100644 --- a/services/comprehendmedical/pom.xml +++ b/services/comprehendmedical/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 comprehendmedical AWS Java SDK :: Services :: ComprehendMedical diff --git a/services/computeoptimizer/pom.xml b/services/computeoptimizer/pom.xml index 9f5a88a6f6a8..cf28f4e00a3f 100644 --- a/services/computeoptimizer/pom.xml +++ b/services/computeoptimizer/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 computeoptimizer AWS Java SDK :: Services :: Compute Optimizer diff --git a/services/config/pom.xml b/services/config/pom.xml index 88ea58e2c38b..45b8eeff4913 100644 --- a/services/config/pom.xml +++ b/services/config/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 config AWS Java SDK :: Services :: AWS Config diff --git a/services/connect/pom.xml b/services/connect/pom.xml index d803f92e8571..3c39c6733816 100644 --- a/services/connect/pom.xml +++ b/services/connect/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 connect AWS Java SDK :: Services :: Connect diff --git a/services/connectcampaigns/pom.xml b/services/connectcampaigns/pom.xml index 96e92e8cc9ae..378a7c7193f6 100644 --- a/services/connectcampaigns/pom.xml +++ b/services/connectcampaigns/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 connectcampaigns AWS Java SDK :: Services :: Connect Campaigns diff --git a/services/connectcampaignsv2/pom.xml b/services/connectcampaignsv2/pom.xml index bdb3c5f619e5..19dd3215b3f9 100644 --- a/services/connectcampaignsv2/pom.xml +++ b/services/connectcampaignsv2/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 connectcampaignsv2 AWS Java SDK :: Services :: Connect Campaigns V2 diff --git a/services/connectcases/pom.xml b/services/connectcases/pom.xml index 0eeb0c00e12f..01a44843955b 100644 --- a/services/connectcases/pom.xml +++ b/services/connectcases/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 connectcases AWS Java SDK :: Services :: Connect Cases diff --git a/services/connectcontactlens/pom.xml b/services/connectcontactlens/pom.xml index 75339a7d677a..a2b0fa7ae053 100644 --- a/services/connectcontactlens/pom.xml +++ b/services/connectcontactlens/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 connectcontactlens AWS Java SDK :: Services :: Connect Contact Lens diff --git a/services/connectparticipant/pom.xml b/services/connectparticipant/pom.xml index 3e3701c6eb4e..d9cd86aabec2 100644 --- a/services/connectparticipant/pom.xml +++ b/services/connectparticipant/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 connectparticipant AWS Java SDK :: Services :: ConnectParticipant diff --git a/services/controlcatalog/pom.xml b/services/controlcatalog/pom.xml index de4aa65f05ab..e66f36526e28 100644 --- a/services/controlcatalog/pom.xml +++ b/services/controlcatalog/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 controlcatalog AWS Java SDK :: Services :: Control Catalog diff --git a/services/controltower/pom.xml b/services/controltower/pom.xml index 208e08a6ac5a..55c9e2d9136c 100644 --- a/services/controltower/pom.xml +++ b/services/controltower/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 controltower AWS Java SDK :: Services :: Control Tower diff --git a/services/costandusagereport/pom.xml b/services/costandusagereport/pom.xml index 241b60a907e1..8500d0f041ad 100644 --- a/services/costandusagereport/pom.xml +++ b/services/costandusagereport/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 costandusagereport AWS Java SDK :: Services :: AWS Cost and Usage Report diff --git a/services/costexplorer/pom.xml b/services/costexplorer/pom.xml index 5b73111101cc..78ea193550d3 100644 --- a/services/costexplorer/pom.xml +++ b/services/costexplorer/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 costexplorer diff --git a/services/costoptimizationhub/pom.xml b/services/costoptimizationhub/pom.xml index 06fa422bfad7..cc17073fbf0d 100644 --- a/services/costoptimizationhub/pom.xml +++ b/services/costoptimizationhub/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 costoptimizationhub AWS Java SDK :: Services :: Cost Optimization Hub diff --git a/services/customerprofiles/pom.xml b/services/customerprofiles/pom.xml index bb376c0b5a8e..ed9410c595d7 100644 --- a/services/customerprofiles/pom.xml +++ b/services/customerprofiles/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 customerprofiles AWS Java SDK :: Services :: Customer Profiles diff --git a/services/databasemigration/pom.xml b/services/databasemigration/pom.xml index 08b0b2cace24..3df65d29c07a 100644 --- a/services/databasemigration/pom.xml +++ b/services/databasemigration/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 databasemigration AWS Java SDK :: Services :: AWS Database Migration Service diff --git a/services/databrew/pom.xml b/services/databrew/pom.xml index fc952cc59d68..31ffbd491e7a 100644 --- a/services/databrew/pom.xml +++ b/services/databrew/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 databrew AWS Java SDK :: Services :: Data Brew diff --git a/services/dataexchange/pom.xml b/services/dataexchange/pom.xml index 3d365f45779f..a0772d1c0dc8 100644 --- a/services/dataexchange/pom.xml +++ b/services/dataexchange/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 dataexchange AWS Java SDK :: Services :: DataExchange diff --git a/services/datapipeline/pom.xml b/services/datapipeline/pom.xml index 6052f8db6d0c..3754d79b7201 100644 --- a/services/datapipeline/pom.xml +++ b/services/datapipeline/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 datapipeline AWS Java SDK :: Services :: AWS Data Pipeline diff --git a/services/datasync/pom.xml b/services/datasync/pom.xml index 58b7fce7c311..19f3b6f5c762 100644 --- a/services/datasync/pom.xml +++ b/services/datasync/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 datasync AWS Java SDK :: Services :: DataSync diff --git a/services/datazone/pom.xml b/services/datazone/pom.xml index 70bc78c54a02..8ef719cad4ad 100644 --- a/services/datazone/pom.xml +++ b/services/datazone/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 datazone AWS Java SDK :: Services :: Data Zone diff --git a/services/dax/pom.xml b/services/dax/pom.xml index f8751646dddd..6f146695b1bc 100644 --- a/services/dax/pom.xml +++ b/services/dax/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 dax AWS Java SDK :: Services :: Amazon DynamoDB Accelerator (DAX) diff --git a/services/deadline/pom.xml b/services/deadline/pom.xml index 34c776eee608..5e4281506bf9 100644 --- a/services/deadline/pom.xml +++ b/services/deadline/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 deadline AWS Java SDK :: Services :: Deadline diff --git a/services/detective/pom.xml b/services/detective/pom.xml index f7b5624e4ee1..ffd3adde6787 100644 --- a/services/detective/pom.xml +++ b/services/detective/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 detective AWS Java SDK :: Services :: Detective diff --git a/services/devicefarm/pom.xml b/services/devicefarm/pom.xml index e19170c51d6a..a2163837d0c9 100644 --- a/services/devicefarm/pom.xml +++ b/services/devicefarm/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 devicefarm AWS Java SDK :: Services :: AWS Device Farm diff --git a/services/devopsguru/pom.xml b/services/devopsguru/pom.xml index c385ebace636..52e2dd49cf95 100644 --- a/services/devopsguru/pom.xml +++ b/services/devopsguru/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 devopsguru AWS Java SDK :: Services :: Dev Ops Guru diff --git a/services/directconnect/pom.xml b/services/directconnect/pom.xml index 1c13edacf4c2..ae23a4c02c21 100644 --- a/services/directconnect/pom.xml +++ b/services/directconnect/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 directconnect AWS Java SDK :: Services :: AWS Direct Connect diff --git a/services/directory/pom.xml b/services/directory/pom.xml index 12c6501d372e..68d619bdb0a1 100644 --- a/services/directory/pom.xml +++ b/services/directory/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 directory AWS Java SDK :: Services :: AWS Directory Service diff --git a/services/directoryservicedata/pom.xml b/services/directoryservicedata/pom.xml index bf00a0e12cb5..3a6de22a3faa 100644 --- a/services/directoryservicedata/pom.xml +++ b/services/directoryservicedata/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 directoryservicedata AWS Java SDK :: Services :: Directory Service Data diff --git a/services/dlm/pom.xml b/services/dlm/pom.xml index 6f8e684d308e..51ecb9fb11b9 100644 --- a/services/dlm/pom.xml +++ b/services/dlm/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 dlm AWS Java SDK :: Services :: DLM diff --git a/services/docdb/pom.xml b/services/docdb/pom.xml index 798a52de9959..bec14195ff3e 100644 --- a/services/docdb/pom.xml +++ b/services/docdb/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 docdb AWS Java SDK :: Services :: DocDB diff --git a/services/docdbelastic/pom.xml b/services/docdbelastic/pom.xml index 802311ffaa31..dafa6c93d5eb 100644 --- a/services/docdbelastic/pom.xml +++ b/services/docdbelastic/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 docdbelastic AWS Java SDK :: Services :: Doc DB Elastic diff --git a/services/drs/pom.xml b/services/drs/pom.xml index 7543239f662f..aaea5983cf12 100644 --- a/services/drs/pom.xml +++ b/services/drs/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 drs AWS Java SDK :: Services :: Drs diff --git a/services/dsql/pom.xml b/services/dsql/pom.xml index 510ecf095e95..b408c4040c17 100644 --- a/services/dsql/pom.xml +++ b/services/dsql/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 dsql AWS Java SDK :: Services :: DSQL diff --git a/services/dynamodb/pom.xml b/services/dynamodb/pom.xml index a681443fc78f..6435126c0685 100644 --- a/services/dynamodb/pom.xml +++ b/services/dynamodb/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 dynamodb AWS Java SDK :: Services :: Amazon DynamoDB diff --git a/services/ebs/pom.xml b/services/ebs/pom.xml index 2dde054ed7e9..776280be9d85 100644 --- a/services/ebs/pom.xml +++ b/services/ebs/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 ebs AWS Java SDK :: Services :: EBS diff --git a/services/ec2/pom.xml b/services/ec2/pom.xml index d77a701083a5..eb3fd94a0865 100644 --- a/services/ec2/pom.xml +++ b/services/ec2/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 ec2 AWS Java SDK :: Services :: Amazon EC2 diff --git a/services/ec2instanceconnect/pom.xml b/services/ec2instanceconnect/pom.xml index 1003dcbcf967..5cce36bd327d 100644 --- a/services/ec2instanceconnect/pom.xml +++ b/services/ec2instanceconnect/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 ec2instanceconnect AWS Java SDK :: Services :: EC2 Instance Connect diff --git a/services/ecr/pom.xml b/services/ecr/pom.xml index 40cb8fe1c990..87f748ef8171 100644 --- a/services/ecr/pom.xml +++ b/services/ecr/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 ecr AWS Java SDK :: Services :: Amazon EC2 Container Registry diff --git a/services/ecrpublic/pom.xml b/services/ecrpublic/pom.xml index 2082ba5a3b3e..d7f313039653 100644 --- a/services/ecrpublic/pom.xml +++ b/services/ecrpublic/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 ecrpublic AWS Java SDK :: Services :: ECR PUBLIC diff --git a/services/ecs/pom.xml b/services/ecs/pom.xml index e42758d10213..370fa8580429 100644 --- a/services/ecs/pom.xml +++ b/services/ecs/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 ecs AWS Java SDK :: Services :: Amazon EC2 Container Service diff --git a/services/efs/pom.xml b/services/efs/pom.xml index ba0c3fe55474..6a57b9a846a2 100644 --- a/services/efs/pom.xml +++ b/services/efs/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 efs AWS Java SDK :: Services :: Amazon Elastic File System diff --git a/services/eks/pom.xml b/services/eks/pom.xml index d9d39cb3cd9b..98ae54cf82d8 100644 --- a/services/eks/pom.xml +++ b/services/eks/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 eks AWS Java SDK :: Services :: EKS diff --git a/services/eksauth/pom.xml b/services/eksauth/pom.xml index 56f65ea1bf78..5127fc155ec2 100644 --- a/services/eksauth/pom.xml +++ b/services/eksauth/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 eksauth AWS Java SDK :: Services :: EKS Auth diff --git a/services/elasticache/pom.xml b/services/elasticache/pom.xml index 784de61742c7..a0c3947ac7c5 100644 --- a/services/elasticache/pom.xml +++ b/services/elasticache/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 elasticache AWS Java SDK :: Services :: Amazon ElastiCache diff --git a/services/elasticbeanstalk/pom.xml b/services/elasticbeanstalk/pom.xml index 461b9eb377ab..604686a6b0c5 100644 --- a/services/elasticbeanstalk/pom.xml +++ b/services/elasticbeanstalk/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 elasticbeanstalk AWS Java SDK :: Services :: AWS Elastic Beanstalk diff --git a/services/elasticinference/pom.xml b/services/elasticinference/pom.xml index 863895164431..9a6c9b2225f7 100644 --- a/services/elasticinference/pom.xml +++ b/services/elasticinference/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 elasticinference AWS Java SDK :: Services :: Elastic Inference diff --git a/services/elasticloadbalancing/pom.xml b/services/elasticloadbalancing/pom.xml index feda15001e86..592c7206c2e8 100644 --- a/services/elasticloadbalancing/pom.xml +++ b/services/elasticloadbalancing/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 elasticloadbalancing AWS Java SDK :: Services :: Elastic Load Balancing diff --git a/services/elasticloadbalancingv2/pom.xml b/services/elasticloadbalancingv2/pom.xml index 049596c89f69..1117db0f148b 100644 --- a/services/elasticloadbalancingv2/pom.xml +++ b/services/elasticloadbalancingv2/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 elasticloadbalancingv2 AWS Java SDK :: Services :: Elastic Load Balancing V2 diff --git a/services/elasticsearch/pom.xml b/services/elasticsearch/pom.xml index ad09f42bdf0e..7de5245cd15a 100644 --- a/services/elasticsearch/pom.xml +++ b/services/elasticsearch/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 elasticsearch AWS Java SDK :: Services :: Amazon Elasticsearch Service diff --git a/services/elastictranscoder/pom.xml b/services/elastictranscoder/pom.xml index c1fac0e9c717..328a512cd7ca 100644 --- a/services/elastictranscoder/pom.xml +++ b/services/elastictranscoder/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 elastictranscoder AWS Java SDK :: Services :: Amazon Elastic Transcoder diff --git a/services/emr/pom.xml b/services/emr/pom.xml index f5495befd678..fe4fe79c24a2 100644 --- a/services/emr/pom.xml +++ b/services/emr/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 emr AWS Java SDK :: Services :: Amazon EMR diff --git a/services/emrcontainers/pom.xml b/services/emrcontainers/pom.xml index 2e7ff04732a3..8ade9b27dab9 100644 --- a/services/emrcontainers/pom.xml +++ b/services/emrcontainers/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 emrcontainers AWS Java SDK :: Services :: EMR Containers diff --git a/services/emrserverless/pom.xml b/services/emrserverless/pom.xml index 9afd3711c639..551399291ab0 100644 --- a/services/emrserverless/pom.xml +++ b/services/emrserverless/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 emrserverless AWS Java SDK :: Services :: EMR Serverless diff --git a/services/entityresolution/pom.xml b/services/entityresolution/pom.xml index 05dcbc193163..389041c13fee 100644 --- a/services/entityresolution/pom.xml +++ b/services/entityresolution/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 entityresolution AWS Java SDK :: Services :: Entity Resolution diff --git a/services/eventbridge/pom.xml b/services/eventbridge/pom.xml index 21227eea093a..3a5944f12710 100644 --- a/services/eventbridge/pom.xml +++ b/services/eventbridge/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 eventbridge AWS Java SDK :: Services :: EventBridge diff --git a/services/evidently/pom.xml b/services/evidently/pom.xml index bcd49b77bd76..8ddc0aac1bf6 100644 --- a/services/evidently/pom.xml +++ b/services/evidently/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 evidently AWS Java SDK :: Services :: Evidently diff --git a/services/finspace/pom.xml b/services/finspace/pom.xml index f39271eaa0e7..4b2475ff6bc1 100644 --- a/services/finspace/pom.xml +++ b/services/finspace/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 finspace AWS Java SDK :: Services :: Finspace diff --git a/services/finspacedata/pom.xml b/services/finspacedata/pom.xml index 48a280eb9c01..dbb0b9c43fdb 100644 --- a/services/finspacedata/pom.xml +++ b/services/finspacedata/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 finspacedata AWS Java SDK :: Services :: Finspace Data diff --git a/services/firehose/pom.xml b/services/firehose/pom.xml index 3c213c1d90a5..23e0a3019151 100644 --- a/services/firehose/pom.xml +++ b/services/firehose/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 firehose AWS Java SDK :: Services :: Amazon Kinesis Firehose diff --git a/services/fis/pom.xml b/services/fis/pom.xml index 6ed3560ef9a2..822d2485ada6 100644 --- a/services/fis/pom.xml +++ b/services/fis/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 fis AWS Java SDK :: Services :: Fis diff --git a/services/fms/pom.xml b/services/fms/pom.xml index 308819f3ae2f..7b1c44882b0c 100644 --- a/services/fms/pom.xml +++ b/services/fms/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 fms AWS Java SDK :: Services :: FMS diff --git a/services/forecast/pom.xml b/services/forecast/pom.xml index 649f8e7cd2b6..813931bb1107 100644 --- a/services/forecast/pom.xml +++ b/services/forecast/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 forecast AWS Java SDK :: Services :: Forecast diff --git a/services/forecastquery/pom.xml b/services/forecastquery/pom.xml index 674cc94266cb..66b81fa0dafc 100644 --- a/services/forecastquery/pom.xml +++ b/services/forecastquery/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 forecastquery AWS Java SDK :: Services :: Forecastquery diff --git a/services/frauddetector/pom.xml b/services/frauddetector/pom.xml index 8e0d99a88b8d..fdd10c9dc7e6 100644 --- a/services/frauddetector/pom.xml +++ b/services/frauddetector/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 frauddetector AWS Java SDK :: Services :: FraudDetector diff --git a/services/freetier/pom.xml b/services/freetier/pom.xml index 8dfb18e00d81..42667c0cc652 100644 --- a/services/freetier/pom.xml +++ b/services/freetier/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 freetier AWS Java SDK :: Services :: Free Tier diff --git a/services/fsx/pom.xml b/services/fsx/pom.xml index 7ffb291aa708..39c69b2b1f24 100644 --- a/services/fsx/pom.xml +++ b/services/fsx/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 fsx AWS Java SDK :: Services :: FSx diff --git a/services/gamelift/pom.xml b/services/gamelift/pom.xml index b1f1b88ec521..6f1ce7950271 100644 --- a/services/gamelift/pom.xml +++ b/services/gamelift/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 gamelift AWS Java SDK :: Services :: AWS GameLift diff --git a/services/geomaps/pom.xml b/services/geomaps/pom.xml index 7e7da84ad340..47e0c14369cb 100644 --- a/services/geomaps/pom.xml +++ b/services/geomaps/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 geomaps AWS Java SDK :: Services :: Geo Maps diff --git a/services/geoplaces/pom.xml b/services/geoplaces/pom.xml index fa30675fcc32..4ceec23499f7 100644 --- a/services/geoplaces/pom.xml +++ b/services/geoplaces/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 geoplaces AWS Java SDK :: Services :: Geo Places diff --git a/services/georoutes/pom.xml b/services/georoutes/pom.xml index 3cd25fa943b3..03c9b2494649 100644 --- a/services/georoutes/pom.xml +++ b/services/georoutes/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 georoutes AWS Java SDK :: Services :: Geo Routes diff --git a/services/glacier/pom.xml b/services/glacier/pom.xml index 2827768d9f19..d431a18a9a0d 100644 --- a/services/glacier/pom.xml +++ b/services/glacier/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 glacier AWS Java SDK :: Services :: Amazon Glacier diff --git a/services/globalaccelerator/pom.xml b/services/globalaccelerator/pom.xml index 7b2ef646df76..ca4a2243885e 100644 --- a/services/globalaccelerator/pom.xml +++ b/services/globalaccelerator/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 globalaccelerator AWS Java SDK :: Services :: Global Accelerator diff --git a/services/glue/pom.xml b/services/glue/pom.xml index b63acf8df8fe..0f14d9828bca 100644 --- a/services/glue/pom.xml +++ b/services/glue/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 glue diff --git a/services/grafana/pom.xml b/services/grafana/pom.xml index 09bd3ee0c13b..c2816dd8958f 100644 --- a/services/grafana/pom.xml +++ b/services/grafana/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 grafana AWS Java SDK :: Services :: Grafana diff --git a/services/greengrass/pom.xml b/services/greengrass/pom.xml index d5bb2c1305a8..055c65bba820 100644 --- a/services/greengrass/pom.xml +++ b/services/greengrass/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 greengrass AWS Java SDK :: Services :: AWS Greengrass diff --git a/services/greengrassv2/pom.xml b/services/greengrassv2/pom.xml index 6443ecd9e50a..e15f29af2cc9 100644 --- a/services/greengrassv2/pom.xml +++ b/services/greengrassv2/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 greengrassv2 AWS Java SDK :: Services :: Greengrass V2 diff --git a/services/groundstation/pom.xml b/services/groundstation/pom.xml index 25cac711e885..fa0e96df5d6f 100644 --- a/services/groundstation/pom.xml +++ b/services/groundstation/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 groundstation AWS Java SDK :: Services :: GroundStation diff --git a/services/guardduty/pom.xml b/services/guardduty/pom.xml index 77127fc9f3bb..0d2a13752b7e 100644 --- a/services/guardduty/pom.xml +++ b/services/guardduty/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 guardduty diff --git a/services/health/pom.xml b/services/health/pom.xml index cc62f2367c8d..09eafa3a83bc 100644 --- a/services/health/pom.xml +++ b/services/health/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 health AWS Java SDK :: Services :: AWS Health APIs and Notifications diff --git a/services/healthlake/pom.xml b/services/healthlake/pom.xml index 7b37842cf3cd..55305f9ed7d2 100644 --- a/services/healthlake/pom.xml +++ b/services/healthlake/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 healthlake AWS Java SDK :: Services :: Health Lake diff --git a/services/iam/pom.xml b/services/iam/pom.xml index 4891cab1c714..63002420d2cc 100644 --- a/services/iam/pom.xml +++ b/services/iam/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 iam AWS Java SDK :: Services :: AWS IAM diff --git a/services/identitystore/pom.xml b/services/identitystore/pom.xml index 8c8ee5e78327..f149f9718c76 100644 --- a/services/identitystore/pom.xml +++ b/services/identitystore/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 identitystore AWS Java SDK :: Services :: Identitystore diff --git a/services/imagebuilder/pom.xml b/services/imagebuilder/pom.xml index 53b50d6e9d8e..843029da72c0 100644 --- a/services/imagebuilder/pom.xml +++ b/services/imagebuilder/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 imagebuilder AWS Java SDK :: Services :: Imagebuilder diff --git a/services/inspector/pom.xml b/services/inspector/pom.xml index a0b016649706..6361e36f42ce 100644 --- a/services/inspector/pom.xml +++ b/services/inspector/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 inspector AWS Java SDK :: Services :: Amazon Inspector Service diff --git a/services/inspector2/pom.xml b/services/inspector2/pom.xml index 54ca2710e89f..b3e83d6b6f55 100644 --- a/services/inspector2/pom.xml +++ b/services/inspector2/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 inspector2 AWS Java SDK :: Services :: Inspector2 diff --git a/services/inspectorscan/pom.xml b/services/inspectorscan/pom.xml index bb4f11ea92b0..1abf423dd227 100644 --- a/services/inspectorscan/pom.xml +++ b/services/inspectorscan/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 inspectorscan AWS Java SDK :: Services :: Inspector Scan diff --git a/services/internetmonitor/pom.xml b/services/internetmonitor/pom.xml index 07da0a1b9afe..be355508fc56 100644 --- a/services/internetmonitor/pom.xml +++ b/services/internetmonitor/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 internetmonitor AWS Java SDK :: Services :: Internet Monitor diff --git a/services/invoicing/pom.xml b/services/invoicing/pom.xml index 1974e3aa4b3d..018c64f6182e 100644 --- a/services/invoicing/pom.xml +++ b/services/invoicing/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 invoicing AWS Java SDK :: Services :: Invoicing diff --git a/services/iot/pom.xml b/services/iot/pom.xml index f372220fe63f..a2e4566e0775 100644 --- a/services/iot/pom.xml +++ b/services/iot/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 iot AWS Java SDK :: Services :: AWS IoT diff --git a/services/iotanalytics/pom.xml b/services/iotanalytics/pom.xml index 93b409c18d66..2296f6d29fd8 100644 --- a/services/iotanalytics/pom.xml +++ b/services/iotanalytics/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 iotanalytics AWS Java SDK :: Services :: IoTAnalytics diff --git a/services/iotdataplane/pom.xml b/services/iotdataplane/pom.xml index 120f63589ed9..425e638d8411 100644 --- a/services/iotdataplane/pom.xml +++ b/services/iotdataplane/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 iotdataplane AWS Java SDK :: Services :: AWS IoT Data Plane diff --git a/services/iotdeviceadvisor/pom.xml b/services/iotdeviceadvisor/pom.xml index c3b8cf66dc13..bbc99869f811 100644 --- a/services/iotdeviceadvisor/pom.xml +++ b/services/iotdeviceadvisor/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 iotdeviceadvisor AWS Java SDK :: Services :: Iot Device Advisor diff --git a/services/iotevents/pom.xml b/services/iotevents/pom.xml index 29a01e451f76..f92c383bfafa 100644 --- a/services/iotevents/pom.xml +++ b/services/iotevents/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 iotevents AWS Java SDK :: Services :: IoT Events diff --git a/services/ioteventsdata/pom.xml b/services/ioteventsdata/pom.xml index 4f152670121a..c2ac025b87e7 100644 --- a/services/ioteventsdata/pom.xml +++ b/services/ioteventsdata/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 ioteventsdata AWS Java SDK :: Services :: IoT Events Data diff --git a/services/iotfleethub/pom.xml b/services/iotfleethub/pom.xml index 3be31eb08815..ffbf8bbe0eb0 100644 --- a/services/iotfleethub/pom.xml +++ b/services/iotfleethub/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 iotfleethub AWS Java SDK :: Services :: Io T Fleet Hub diff --git a/services/iotfleetwise/pom.xml b/services/iotfleetwise/pom.xml index c39baad325b0..8df6da1ad416 100644 --- a/services/iotfleetwise/pom.xml +++ b/services/iotfleetwise/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 iotfleetwise AWS Java SDK :: Services :: Io T Fleet Wise diff --git a/services/iotjobsdataplane/pom.xml b/services/iotjobsdataplane/pom.xml index aaf208efafb7..b9f167a584eb 100644 --- a/services/iotjobsdataplane/pom.xml +++ b/services/iotjobsdataplane/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 iotjobsdataplane AWS Java SDK :: Services :: IoT Jobs Data Plane diff --git a/services/iotsecuretunneling/pom.xml b/services/iotsecuretunneling/pom.xml index 5ef4a2cca1c2..7afefbf4eec2 100644 --- a/services/iotsecuretunneling/pom.xml +++ b/services/iotsecuretunneling/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 iotsecuretunneling AWS Java SDK :: Services :: IoTSecureTunneling diff --git a/services/iotsitewise/pom.xml b/services/iotsitewise/pom.xml index c9466f27a532..73f6cb8fed4a 100644 --- a/services/iotsitewise/pom.xml +++ b/services/iotsitewise/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 iotsitewise AWS Java SDK :: Services :: Io T Site Wise diff --git a/services/iotthingsgraph/pom.xml b/services/iotthingsgraph/pom.xml index 443a093aa759..e13ce0ee8269 100644 --- a/services/iotthingsgraph/pom.xml +++ b/services/iotthingsgraph/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 iotthingsgraph AWS Java SDK :: Services :: IoTThingsGraph diff --git a/services/iottwinmaker/pom.xml b/services/iottwinmaker/pom.xml index 16cb25d93317..563b313287a1 100644 --- a/services/iottwinmaker/pom.xml +++ b/services/iottwinmaker/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 iottwinmaker AWS Java SDK :: Services :: Io T Twin Maker diff --git a/services/iotwireless/pom.xml b/services/iotwireless/pom.xml index 2945f2b3342c..dcd17f684d23 100644 --- a/services/iotwireless/pom.xml +++ b/services/iotwireless/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 iotwireless AWS Java SDK :: Services :: IoT Wireless diff --git a/services/ivs/pom.xml b/services/ivs/pom.xml index fe464d0c4393..67dcdbd21d08 100644 --- a/services/ivs/pom.xml +++ b/services/ivs/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 ivs AWS Java SDK :: Services :: Ivs diff --git a/services/ivschat/pom.xml b/services/ivschat/pom.xml index afc9477f4747..4b5ff479074b 100644 --- a/services/ivschat/pom.xml +++ b/services/ivschat/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 ivschat AWS Java SDK :: Services :: Ivschat diff --git a/services/ivsrealtime/pom.xml b/services/ivsrealtime/pom.xml index 5f78576db2dc..548e5f9ffdb7 100644 --- a/services/ivsrealtime/pom.xml +++ b/services/ivsrealtime/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 ivsrealtime AWS Java SDK :: Services :: IVS Real Time diff --git a/services/kafka/pom.xml b/services/kafka/pom.xml index 7e4a9922e984..b09ad83a459e 100644 --- a/services/kafka/pom.xml +++ b/services/kafka/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 kafka AWS Java SDK :: Services :: Kafka diff --git a/services/kafkaconnect/pom.xml b/services/kafkaconnect/pom.xml index 046ac32fec4f..f3ee8faf2e58 100644 --- a/services/kafkaconnect/pom.xml +++ b/services/kafkaconnect/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 kafkaconnect AWS Java SDK :: Services :: Kafka Connect diff --git a/services/kendra/pom.xml b/services/kendra/pom.xml index ddf68af95835..1631c0fb2f1a 100644 --- a/services/kendra/pom.xml +++ b/services/kendra/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 kendra AWS Java SDK :: Services :: Kendra diff --git a/services/kendraranking/pom.xml b/services/kendraranking/pom.xml index 6222512a4a96..2390eaf113bd 100644 --- a/services/kendraranking/pom.xml +++ b/services/kendraranking/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 kendraranking AWS Java SDK :: Services :: Kendra Ranking diff --git a/services/keyspaces/pom.xml b/services/keyspaces/pom.xml index d81cd54049db..f27fc6467985 100644 --- a/services/keyspaces/pom.xml +++ b/services/keyspaces/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 keyspaces AWS Java SDK :: Services :: Keyspaces diff --git a/services/kinesis/pom.xml b/services/kinesis/pom.xml index 372f07250937..9b823736b0fc 100644 --- a/services/kinesis/pom.xml +++ b/services/kinesis/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 kinesis AWS Java SDK :: Services :: Amazon Kinesis diff --git a/services/kinesisanalytics/pom.xml b/services/kinesisanalytics/pom.xml index 6406dc59d7c4..884d9c100cba 100644 --- a/services/kinesisanalytics/pom.xml +++ b/services/kinesisanalytics/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 kinesisanalytics AWS Java SDK :: Services :: Amazon Kinesis Analytics diff --git a/services/kinesisanalyticsv2/pom.xml b/services/kinesisanalyticsv2/pom.xml index ffdfc8a45d81..1ba216d8d82b 100644 --- a/services/kinesisanalyticsv2/pom.xml +++ b/services/kinesisanalyticsv2/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 kinesisanalyticsv2 AWS Java SDK :: Services :: Kinesis Analytics V2 diff --git a/services/kinesisvideo/pom.xml b/services/kinesisvideo/pom.xml index c819271ee644..83f93f475fdf 100644 --- a/services/kinesisvideo/pom.xml +++ b/services/kinesisvideo/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 kinesisvideo diff --git a/services/kinesisvideoarchivedmedia/pom.xml b/services/kinesisvideoarchivedmedia/pom.xml index f716be3b8205..e562e5127cbd 100644 --- a/services/kinesisvideoarchivedmedia/pom.xml +++ b/services/kinesisvideoarchivedmedia/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 kinesisvideoarchivedmedia AWS Java SDK :: Services :: Kinesis Video Archived Media diff --git a/services/kinesisvideomedia/pom.xml b/services/kinesisvideomedia/pom.xml index a3697bff6540..225973f9f91c 100644 --- a/services/kinesisvideomedia/pom.xml +++ b/services/kinesisvideomedia/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 kinesisvideomedia AWS Java SDK :: Services :: Kinesis Video Media diff --git a/services/kinesisvideosignaling/pom.xml b/services/kinesisvideosignaling/pom.xml index 28c6422d0f06..6241befb2de7 100644 --- a/services/kinesisvideosignaling/pom.xml +++ b/services/kinesisvideosignaling/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 kinesisvideosignaling AWS Java SDK :: Services :: Kinesis Video Signaling diff --git a/services/kinesisvideowebrtcstorage/pom.xml b/services/kinesisvideowebrtcstorage/pom.xml index f22359a58395..b64c49afe2bb 100644 --- a/services/kinesisvideowebrtcstorage/pom.xml +++ b/services/kinesisvideowebrtcstorage/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 kinesisvideowebrtcstorage AWS Java SDK :: Services :: Kinesis Video Web RTC Storage diff --git a/services/kms/pom.xml b/services/kms/pom.xml index c32fb61bc960..8e21568df600 100644 --- a/services/kms/pom.xml +++ b/services/kms/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 kms AWS Java SDK :: Services :: AWS KMS diff --git a/services/lakeformation/pom.xml b/services/lakeformation/pom.xml index 3264ea24bccc..b2eb622641eb 100644 --- a/services/lakeformation/pom.xml +++ b/services/lakeformation/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 lakeformation AWS Java SDK :: Services :: LakeFormation diff --git a/services/lambda/pom.xml b/services/lambda/pom.xml index 740dbe8a97ef..efd538fd767d 100644 --- a/services/lambda/pom.xml +++ b/services/lambda/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 lambda AWS Java SDK :: Services :: AWS Lambda diff --git a/services/launchwizard/pom.xml b/services/launchwizard/pom.xml index 8e9acac7bc64..0285ab7baaee 100644 --- a/services/launchwizard/pom.xml +++ b/services/launchwizard/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 launchwizard AWS Java SDK :: Services :: Launch Wizard diff --git a/services/lexmodelbuilding/pom.xml b/services/lexmodelbuilding/pom.xml index 591b158c2ab9..06bbb9bd2344 100644 --- a/services/lexmodelbuilding/pom.xml +++ b/services/lexmodelbuilding/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 lexmodelbuilding AWS Java SDK :: Services :: Amazon Lex Model Building diff --git a/services/lexmodelsv2/pom.xml b/services/lexmodelsv2/pom.xml index 4185c581b8ec..2480ba832eb6 100644 --- a/services/lexmodelsv2/pom.xml +++ b/services/lexmodelsv2/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 lexmodelsv2 AWS Java SDK :: Services :: Lex Models V2 diff --git a/services/lexruntime/pom.xml b/services/lexruntime/pom.xml index e523cefda273..50bedca9fa30 100644 --- a/services/lexruntime/pom.xml +++ b/services/lexruntime/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 lexruntime AWS Java SDK :: Services :: Amazon Lex Runtime diff --git a/services/lexruntimev2/pom.xml b/services/lexruntimev2/pom.xml index 7541ed9f4585..059b5d23338d 100644 --- a/services/lexruntimev2/pom.xml +++ b/services/lexruntimev2/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 lexruntimev2 AWS Java SDK :: Services :: Lex Runtime V2 diff --git a/services/licensemanager/pom.xml b/services/licensemanager/pom.xml index ca90457c2d24..ed9424b0ee5c 100644 --- a/services/licensemanager/pom.xml +++ b/services/licensemanager/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 licensemanager AWS Java SDK :: Services :: License Manager diff --git a/services/licensemanagerlinuxsubscriptions/pom.xml b/services/licensemanagerlinuxsubscriptions/pom.xml index 33a444c0541e..348aaed69791 100644 --- a/services/licensemanagerlinuxsubscriptions/pom.xml +++ b/services/licensemanagerlinuxsubscriptions/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 licensemanagerlinuxsubscriptions AWS Java SDK :: Services :: License Manager Linux Subscriptions diff --git a/services/licensemanagerusersubscriptions/pom.xml b/services/licensemanagerusersubscriptions/pom.xml index 7b110e33bbfa..dc4f297e1920 100644 --- a/services/licensemanagerusersubscriptions/pom.xml +++ b/services/licensemanagerusersubscriptions/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 licensemanagerusersubscriptions AWS Java SDK :: Services :: License Manager User Subscriptions diff --git a/services/lightsail/pom.xml b/services/lightsail/pom.xml index 045e6fa7819a..4d7c1b641efa 100644 --- a/services/lightsail/pom.xml +++ b/services/lightsail/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 lightsail AWS Java SDK :: Services :: Amazon Lightsail diff --git a/services/location/pom.xml b/services/location/pom.xml index eceb35049885..25462a1616ff 100644 --- a/services/location/pom.xml +++ b/services/location/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 location AWS Java SDK :: Services :: Location diff --git a/services/lookoutequipment/pom.xml b/services/lookoutequipment/pom.xml index 2591614eab8a..6af6f6e3fcd6 100644 --- a/services/lookoutequipment/pom.xml +++ b/services/lookoutequipment/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 lookoutequipment AWS Java SDK :: Services :: Lookout Equipment diff --git a/services/lookoutmetrics/pom.xml b/services/lookoutmetrics/pom.xml index a854ea019ee5..bb37b89f88e7 100644 --- a/services/lookoutmetrics/pom.xml +++ b/services/lookoutmetrics/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 lookoutmetrics AWS Java SDK :: Services :: Lookout Metrics diff --git a/services/lookoutvision/pom.xml b/services/lookoutvision/pom.xml index 98e33e625487..e7a80031a7b9 100644 --- a/services/lookoutvision/pom.xml +++ b/services/lookoutvision/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 lookoutvision AWS Java SDK :: Services :: Lookout Vision diff --git a/services/m2/pom.xml b/services/m2/pom.xml index 4f58a153714c..15244fe935b7 100644 --- a/services/m2/pom.xml +++ b/services/m2/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 m2 AWS Java SDK :: Services :: M2 diff --git a/services/machinelearning/pom.xml b/services/machinelearning/pom.xml index 4d1ff6d07919..30ff5ac31a25 100644 --- a/services/machinelearning/pom.xml +++ b/services/machinelearning/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 machinelearning AWS Java SDK :: Services :: Amazon Machine Learning diff --git a/services/macie2/pom.xml b/services/macie2/pom.xml index 7a5581b136f5..8de64c62f545 100644 --- a/services/macie2/pom.xml +++ b/services/macie2/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 macie2 AWS Java SDK :: Services :: Macie2 diff --git a/services/mailmanager/pom.xml b/services/mailmanager/pom.xml index 65bd91af657c..ded3ddc3e012 100644 --- a/services/mailmanager/pom.xml +++ b/services/mailmanager/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 mailmanager AWS Java SDK :: Services :: Mail Manager diff --git a/services/managedblockchain/pom.xml b/services/managedblockchain/pom.xml index ee764bab04a0..ea85358ddb9a 100644 --- a/services/managedblockchain/pom.xml +++ b/services/managedblockchain/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 managedblockchain AWS Java SDK :: Services :: ManagedBlockchain diff --git a/services/managedblockchainquery/pom.xml b/services/managedblockchainquery/pom.xml index 7212930a3e93..c60725581ef2 100644 --- a/services/managedblockchainquery/pom.xml +++ b/services/managedblockchainquery/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 managedblockchainquery AWS Java SDK :: Services :: Managed Blockchain Query diff --git a/services/marketplaceagreement/pom.xml b/services/marketplaceagreement/pom.xml index b69cdea48545..791f400c5018 100644 --- a/services/marketplaceagreement/pom.xml +++ b/services/marketplaceagreement/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 marketplaceagreement AWS Java SDK :: Services :: Marketplace Agreement diff --git a/services/marketplacecatalog/pom.xml b/services/marketplacecatalog/pom.xml index 5ffe47b8cc54..d56c45f12ff9 100644 --- a/services/marketplacecatalog/pom.xml +++ b/services/marketplacecatalog/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 marketplacecatalog AWS Java SDK :: Services :: Marketplace Catalog diff --git a/services/marketplacecommerceanalytics/pom.xml b/services/marketplacecommerceanalytics/pom.xml index a2d242389e80..61b04e6dbe4f 100644 --- a/services/marketplacecommerceanalytics/pom.xml +++ b/services/marketplacecommerceanalytics/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 marketplacecommerceanalytics AWS Java SDK :: Services :: AWS Marketplace Commerce Analytics diff --git a/services/marketplacedeployment/pom.xml b/services/marketplacedeployment/pom.xml index ddcfad23fc29..a36f94995543 100644 --- a/services/marketplacedeployment/pom.xml +++ b/services/marketplacedeployment/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 marketplacedeployment AWS Java SDK :: Services :: Marketplace Deployment diff --git a/services/marketplaceentitlement/pom.xml b/services/marketplaceentitlement/pom.xml index 4491ab0ec61c..d2286fb74313 100644 --- a/services/marketplaceentitlement/pom.xml +++ b/services/marketplaceentitlement/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 marketplaceentitlement AWS Java SDK :: Services :: AWS Marketplace Entitlement diff --git a/services/marketplacemetering/pom.xml b/services/marketplacemetering/pom.xml index 71916e5d89bf..9b58c10278df 100644 --- a/services/marketplacemetering/pom.xml +++ b/services/marketplacemetering/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 marketplacemetering AWS Java SDK :: Services :: AWS Marketplace Metering Service diff --git a/services/marketplacereporting/pom.xml b/services/marketplacereporting/pom.xml index c881c0d257b0..60dacea7c71e 100644 --- a/services/marketplacereporting/pom.xml +++ b/services/marketplacereporting/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 marketplacereporting AWS Java SDK :: Services :: Marketplace Reporting diff --git a/services/mediaconnect/pom.xml b/services/mediaconnect/pom.xml index 0e80f53e0649..a4910a4a14ac 100644 --- a/services/mediaconnect/pom.xml +++ b/services/mediaconnect/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 mediaconnect AWS Java SDK :: Services :: MediaConnect diff --git a/services/mediaconvert/pom.xml b/services/mediaconvert/pom.xml index 2cf00a6b5a13..4938f73c98ff 100644 --- a/services/mediaconvert/pom.xml +++ b/services/mediaconvert/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 mediaconvert diff --git a/services/medialive/pom.xml b/services/medialive/pom.xml index a6fa4e8123ed..d7668f27a97f 100644 --- a/services/medialive/pom.xml +++ b/services/medialive/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 medialive diff --git a/services/mediapackage/pom.xml b/services/mediapackage/pom.xml index 459813020917..29788c7f6d47 100644 --- a/services/mediapackage/pom.xml +++ b/services/mediapackage/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 mediapackage diff --git a/services/mediapackagev2/pom.xml b/services/mediapackagev2/pom.xml index f18a0249cefc..8a2f549b92b2 100644 --- a/services/mediapackagev2/pom.xml +++ b/services/mediapackagev2/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 mediapackagev2 AWS Java SDK :: Services :: Media Package V2 diff --git a/services/mediapackagevod/pom.xml b/services/mediapackagevod/pom.xml index e53a6ea418b7..d6a8f729808a 100644 --- a/services/mediapackagevod/pom.xml +++ b/services/mediapackagevod/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 mediapackagevod AWS Java SDK :: Services :: MediaPackage Vod diff --git a/services/mediastore/pom.xml b/services/mediastore/pom.xml index e9509fb4ad24..884ee99d362b 100644 --- a/services/mediastore/pom.xml +++ b/services/mediastore/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 mediastore diff --git a/services/mediastoredata/pom.xml b/services/mediastoredata/pom.xml index fc0970655852..79eff99a3529 100644 --- a/services/mediastoredata/pom.xml +++ b/services/mediastoredata/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 mediastoredata diff --git a/services/mediatailor/pom.xml b/services/mediatailor/pom.xml index 6009dda29ed5..71bf00ec114e 100644 --- a/services/mediatailor/pom.xml +++ b/services/mediatailor/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 mediatailor AWS Java SDK :: Services :: MediaTailor diff --git a/services/medicalimaging/pom.xml b/services/medicalimaging/pom.xml index 3d866c6f50e2..0b20ae59fba9 100644 --- a/services/medicalimaging/pom.xml +++ b/services/medicalimaging/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 medicalimaging AWS Java SDK :: Services :: Medical Imaging diff --git a/services/memorydb/pom.xml b/services/memorydb/pom.xml index a661144ed974..323b432c5541 100644 --- a/services/memorydb/pom.xml +++ b/services/memorydb/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 memorydb AWS Java SDK :: Services :: Memory DB diff --git a/services/mgn/pom.xml b/services/mgn/pom.xml index 6a23a0733ee1..ee1d8f543888 100644 --- a/services/mgn/pom.xml +++ b/services/mgn/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 mgn AWS Java SDK :: Services :: Mgn diff --git a/services/migrationhub/pom.xml b/services/migrationhub/pom.xml index 4808d7f65f79..e621b4095e8a 100644 --- a/services/migrationhub/pom.xml +++ b/services/migrationhub/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 migrationhub diff --git a/services/migrationhubconfig/pom.xml b/services/migrationhubconfig/pom.xml index f29fb8f3f5d1..de693865a5b6 100644 --- a/services/migrationhubconfig/pom.xml +++ b/services/migrationhubconfig/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 migrationhubconfig AWS Java SDK :: Services :: MigrationHub Config diff --git a/services/migrationhuborchestrator/pom.xml b/services/migrationhuborchestrator/pom.xml index 26f7d898cdf6..070c318c4846 100644 --- a/services/migrationhuborchestrator/pom.xml +++ b/services/migrationhuborchestrator/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 migrationhuborchestrator AWS Java SDK :: Services :: Migration Hub Orchestrator diff --git a/services/migrationhubrefactorspaces/pom.xml b/services/migrationhubrefactorspaces/pom.xml index b222a0156431..010fc57d8f13 100644 --- a/services/migrationhubrefactorspaces/pom.xml +++ b/services/migrationhubrefactorspaces/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 migrationhubrefactorspaces AWS Java SDK :: Services :: Migration Hub Refactor Spaces diff --git a/services/migrationhubstrategy/pom.xml b/services/migrationhubstrategy/pom.xml index 67a4ff5ac10e..8993d28328a5 100644 --- a/services/migrationhubstrategy/pom.xml +++ b/services/migrationhubstrategy/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 migrationhubstrategy AWS Java SDK :: Services :: Migration Hub Strategy diff --git a/services/mq/pom.xml b/services/mq/pom.xml index 6d256b1532b5..f4135c08d39b 100644 --- a/services/mq/pom.xml +++ b/services/mq/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 mq diff --git a/services/mturk/pom.xml b/services/mturk/pom.xml index 9bbbb96f6692..c211858f0247 100644 --- a/services/mturk/pom.xml +++ b/services/mturk/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 mturk AWS Java SDK :: Services :: Amazon Mechanical Turk Requester diff --git a/services/mwaa/pom.xml b/services/mwaa/pom.xml index 025074002b3f..ea7f3c2b5c9a 100644 --- a/services/mwaa/pom.xml +++ b/services/mwaa/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 mwaa AWS Java SDK :: Services :: MWAA diff --git a/services/neptune/pom.xml b/services/neptune/pom.xml index 37f73d4b572f..11daf489a917 100644 --- a/services/neptune/pom.xml +++ b/services/neptune/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 neptune AWS Java SDK :: Services :: Neptune diff --git a/services/neptunedata/pom.xml b/services/neptunedata/pom.xml index 2d008b8270be..789c8d1342fc 100644 --- a/services/neptunedata/pom.xml +++ b/services/neptunedata/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 neptunedata AWS Java SDK :: Services :: Neptunedata diff --git a/services/neptunegraph/pom.xml b/services/neptunegraph/pom.xml index 0e30a2d4a2e0..1c828cbaa126 100644 --- a/services/neptunegraph/pom.xml +++ b/services/neptunegraph/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 neptunegraph AWS Java SDK :: Services :: Neptune Graph diff --git a/services/networkfirewall/pom.xml b/services/networkfirewall/pom.xml index 0ffc731ed9cc..d92fac56def7 100644 --- a/services/networkfirewall/pom.xml +++ b/services/networkfirewall/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 networkfirewall AWS Java SDK :: Services :: Network Firewall diff --git a/services/networkflowmonitor/pom.xml b/services/networkflowmonitor/pom.xml index f076681b7b1a..69a3d3f43329 100644 --- a/services/networkflowmonitor/pom.xml +++ b/services/networkflowmonitor/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 networkflowmonitor AWS Java SDK :: Services :: Network Flow Monitor diff --git a/services/networkmanager/pom.xml b/services/networkmanager/pom.xml index eeb081355718..bd0d7c763498 100644 --- a/services/networkmanager/pom.xml +++ b/services/networkmanager/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 networkmanager AWS Java SDK :: Services :: NetworkManager diff --git a/services/networkmonitor/pom.xml b/services/networkmonitor/pom.xml index 92c4ee48e81d..a5fa9db36113 100644 --- a/services/networkmonitor/pom.xml +++ b/services/networkmonitor/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 networkmonitor AWS Java SDK :: Services :: Network Monitor diff --git a/services/notifications/pom.xml b/services/notifications/pom.xml index 8be7bec85ebd..927b23490672 100644 --- a/services/notifications/pom.xml +++ b/services/notifications/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 notifications AWS Java SDK :: Services :: Notifications diff --git a/services/notificationscontacts/pom.xml b/services/notificationscontacts/pom.xml index 952462fad5c6..f27dd682d0e1 100644 --- a/services/notificationscontacts/pom.xml +++ b/services/notificationscontacts/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 notificationscontacts AWS Java SDK :: Services :: Notifications Contacts diff --git a/services/oam/pom.xml b/services/oam/pom.xml index afc96853b11c..93c3a9de2aea 100644 --- a/services/oam/pom.xml +++ b/services/oam/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 oam AWS Java SDK :: Services :: OAM diff --git a/services/observabilityadmin/pom.xml b/services/observabilityadmin/pom.xml index 3389141e9356..11c377907591 100644 --- a/services/observabilityadmin/pom.xml +++ b/services/observabilityadmin/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 observabilityadmin AWS Java SDK :: Services :: Observability Admin diff --git a/services/omics/pom.xml b/services/omics/pom.xml index d6c62f21f9a6..fbad5c8d08f3 100644 --- a/services/omics/pom.xml +++ b/services/omics/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 omics AWS Java SDK :: Services :: Omics diff --git a/services/opensearch/pom.xml b/services/opensearch/pom.xml index f33fbd78cf08..602ba876b7f9 100644 --- a/services/opensearch/pom.xml +++ b/services/opensearch/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 opensearch AWS Java SDK :: Services :: Open Search diff --git a/services/opensearchserverless/pom.xml b/services/opensearchserverless/pom.xml index b65333ed249c..9b5ab49b8ef5 100644 --- a/services/opensearchserverless/pom.xml +++ b/services/opensearchserverless/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 opensearchserverless AWS Java SDK :: Services :: Open Search Serverless diff --git a/services/opsworks/pom.xml b/services/opsworks/pom.xml index 19351aac0e00..ea532eea7b59 100644 --- a/services/opsworks/pom.xml +++ b/services/opsworks/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 opsworks AWS Java SDK :: Services :: AWS OpsWorks diff --git a/services/opsworkscm/pom.xml b/services/opsworkscm/pom.xml index c7571d2481ef..39c6570a9e4b 100644 --- a/services/opsworkscm/pom.xml +++ b/services/opsworkscm/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 opsworkscm AWS Java SDK :: Services :: AWS OpsWorks for Chef Automate diff --git a/services/organizations/pom.xml b/services/organizations/pom.xml index cbe28696b3bb..7817270ed0c6 100644 --- a/services/organizations/pom.xml +++ b/services/organizations/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 organizations AWS Java SDK :: Services :: AWS Organizations diff --git a/services/osis/pom.xml b/services/osis/pom.xml index 531dd1601fef..abe7d730ef88 100644 --- a/services/osis/pom.xml +++ b/services/osis/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 osis AWS Java SDK :: Services :: OSIS diff --git a/services/outposts/pom.xml b/services/outposts/pom.xml index ad522ae4a1eb..3d033066b103 100644 --- a/services/outposts/pom.xml +++ b/services/outposts/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 outposts AWS Java SDK :: Services :: Outposts diff --git a/services/panorama/pom.xml b/services/panorama/pom.xml index 3881da7560d4..807c7c10894c 100644 --- a/services/panorama/pom.xml +++ b/services/panorama/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 panorama AWS Java SDK :: Services :: Panorama diff --git a/services/partnercentralselling/pom.xml b/services/partnercentralselling/pom.xml index cf0ff9c74a27..5ea0522982e8 100644 --- a/services/partnercentralselling/pom.xml +++ b/services/partnercentralselling/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 partnercentralselling AWS Java SDK :: Services :: Partner Central Selling diff --git a/services/partnercentralselling/src/main/resources/codegen-resources/service-2.json b/services/partnercentralselling/src/main/resources/codegen-resources/service-2.json index 5f6f7dfe23cf..02f9b793bdef 100644 --- a/services/partnercentralselling/src/main/resources/codegen-resources/service-2.json +++ b/services/partnercentralselling/src/main/resources/codegen-resources/service-2.json @@ -24,12 +24,13 @@ "input":{"shape":"AcceptEngagementInvitationRequest"}, "errors":[ {"shape":"ThrottlingException"}, + {"shape":"ConflictException"}, {"shape":"AccessDeniedException"}, {"shape":"InternalServerException"}, {"shape":"ValidationException"}, {"shape":"ResourceNotFoundException"} ], - "documentation":"

    Use the AcceptEngagementInvitation action to accept an engagement invitation shared by AWS. Accepting the invitation indicates your willingness to participate in the engagement, granting you access to all engagement-related data.

    " + "documentation":"

    Use the AcceptEngagementInvitation action to accept an engagement invitation shared by AWS. Accepting the invitation indicates your willingness to participate in the engagement, granting you access to all engagement-related data.

    " }, "AssignOpportunity":{ "name":"AssignOpportunity", @@ -79,7 +80,7 @@ {"shape":"ServiceQuotaExceededException"}, {"shape":"ResourceNotFoundException"} ], - "documentation":"

    The CreateEngagement action allows you to create an Engagement, which serves as a collaborative space between different parties such as AWS Partners and AWS Sellers. This action automatically adds the caller's AWS account as an active member of the newly created Engagement.

    ", + "documentation":"

    The CreateEngagement action allows you to create an Engagement, which serves as a collaborative space between different parties such as AWS Partners and AWS Sellers. This action automatically adds the caller's AWS account as an active member of the newly created Engagement.

    ", "idempotent":true }, "CreateEngagementInvitation":{ @@ -117,7 +118,7 @@ {"shape":"ValidationException"}, {"shape":"ResourceNotFoundException"} ], - "documentation":"

    Creates an Opportunity record in Partner Central. Use this operation to create a potential business opportunity for submission to Amazon Web Services. Creating an opportunity sets Lifecycle.ReviewStatus to Pending Submission.

    To submit an opportunity, follow these steps:

    1. To create the opportunity, use CreateOpportunity.

    2. To associate a solution with the opportunity, use AssociateOpportunity.

    3. To submit the opportunity, use StartEngagementFromOpportunityTask.

    After submission, you can't edit the opportunity until the review is complete. But opportunities in the Pending Submission state must have complete details. You can update the opportunity while it's in the Pending Submission state.

    There's a set of mandatory fields to create opportunities, but consider providing optional fields to enrich the opportunity record.

    ", + "documentation":"

    Creates an Opportunity record in Partner Central. Use this operation to create a potential business opportunity for submission to Amazon Web Services. Creating an opportunity sets Lifecycle.ReviewStatus to Pending Submission.

    To submit an opportunity, follow these steps:

    1. To create the opportunity, use CreateOpportunity.

    2. To associate a solution with the opportunity, use AssociateOpportunity.

    3. To start the engagement with AWS, use StartEngagementFromOpportunity.

    After submission, you can't edit the opportunity until the review is complete. But opportunities in the Pending Submission state must have complete details. You can update the opportunity while it's in the Pending Submission state.

    There's a set of mandatory fields to create opportunities, but consider providing optional fields to enrich the opportunity record.

    ", "idempotent":true }, "CreateResourceSnapshot":{ @@ -155,7 +156,7 @@ {"shape":"ServiceQuotaExceededException"}, {"shape":"ResourceNotFoundException"} ], - "documentation":"

    Use this action to create a job to generate a snapshot of the specified resource within an engagement. It initiates an asynchronous process to create a resource snapshot. The job creates a new snapshot only if the resource state has changed, adhering to the same access control and immutability rules as direct snapshot creation.

    ", + "documentation":"

    Use this action to create a job to generate a snapshot of the specified resource within an engagement. It initiates an asynchronous process to create a resource snapshot. The job creates a new snapshot only if the resource state has changed, adhering to the same access control and immutability rules as direct snapshot creation.

    ", "idempotent":true }, "DeleteResourceSnapshotJob":{ @@ -167,6 +168,7 @@ "input":{"shape":"DeleteResourceSnapshotJobRequest"}, "errors":[ {"shape":"ThrottlingException"}, + {"shape":"ConflictException"}, {"shape":"AccessDeniedException"}, {"shape":"ValidationException"}, {"shape":"ResourceNotFoundException"} @@ -221,7 +223,7 @@ {"shape":"ValidationException"}, {"shape":"ResourceNotFoundException"} ], - "documentation":"

    Use this action to retrieve the engagement record for a given EngagementIdentifier.

    " + "documentation":"

    Use this action to retrieve the engagement record for a given EngagementIdentifier.

    " }, "GetEngagementInvitation":{ "name":"GetEngagementInvitation", @@ -287,7 +289,7 @@ {"shape":"ValidationException"}, {"shape":"ResourceNotFoundException"} ], - "documentation":"

    Use this action to retrieves information about a specific resource snapshot job.

    " + "documentation":"

    Use this action to retrieves information about a specific resource snapshot job.

    " }, "GetSellingSystemSettings":{ "name":"GetSellingSystemSettings", @@ -368,7 +370,7 @@ {"shape":"ValidationException"}, {"shape":"ResourceNotFoundException"} ], - "documentation":"

    Retrieves the details of member partners in an engagement. This operation can only be invoked by members of the engagement. The ListEngagementMembers operation allows you to fetch information about the members of a specific engagement. This action is restricted to members of the engagement being queried.

    " + "documentation":"

    Retrieves the details of member partners in an Engagement. This operation can only be invoked by members of the Engagement. The ListEngagementMembers operation allows you to fetch information about the members of a specific Engagement. This action is restricted to members of the Engagement being queried.

    " }, "ListEngagementResourceAssociations":{ "name":"ListEngagementResourceAssociations", @@ -384,7 +386,7 @@ {"shape":"ValidationException"}, {"shape":"ResourceNotFoundException"} ], - "documentation":"

    Lists the associations between resources and engagements where the caller is a member and has at least one snapshot in the engagement.

    " + "documentation":"

    Lists the associations between resources and engagements where the caller is a member and has at least one snapshot in the engagement.

    " }, "ListEngagements":{ "name":"ListEngagements", @@ -400,7 +402,7 @@ {"shape":"ValidationException"}, {"shape":"ResourceNotFoundException"} ], - "documentation":"

    This action allows users to retrieve a list of engagement records from Partner Central. This action can be used to manage and track various engagements across different stages of the partner selling process.

    " + "documentation":"

    This action allows users to retrieve a list of Engagement records from Partner Central. This action can be used to manage and track various engagements across different stages of the partner selling process.

    " }, "ListOpportunities":{ "name":"ListOpportunities", @@ -430,7 +432,8 @@ "errors":[ {"shape":"ThrottlingException"}, {"shape":"AccessDeniedException"}, - {"shape":"ValidationException"} + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"} ], "documentation":"

    Lists resource snapshot jobs owned by the customer. This operation supports various filtering scenarios, including listing all jobs owned by the caller, jobs for a specific engagement, jobs with a specific status, or any combination of these filters.

    " }, @@ -448,7 +451,7 @@ {"shape":"ValidationException"}, {"shape":"ResourceNotFoundException"} ], - "documentation":"

    Retrieves a list of resource view snapshots based on specified criteria.

    " + "documentation":"

    Retrieves a list of resource view snapshots based on specified criteria. This operation supports various use cases, including:

    • Fetching all snapshots associated with an engagement.

    • Retrieving snapshots of a specific resource type within an engagement.

    • Obtaining snapshots for a particular resource using a specified template.

    • Accessing the latest snapshot of a resource within an engagement.

    • Filtering snapshots by resource owner.

    " }, "ListSolutions":{ "name":"ListSolutions", @@ -466,6 +469,23 @@ ], "documentation":"

    Retrieves a list of Partner Solutions that the partner registered on Partner Central. This API is used to generate a list of solutions that an end user selects from for association with an opportunity.

    " }, + "ListTagsForResource":{ + "name":"ListTagsForResource", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ListTagsForResourceRequest"}, + "output":{"shape":"ListTagsForResourceResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"} + ], + "documentation":"

    Returns a list of tags for a resource.

    " + }, "PutSellingSystemSettings":{ "name":"PutSellingSystemSettings", "http":{ @@ -492,6 +512,7 @@ "input":{"shape":"RejectEngagementInvitationRequest"}, "errors":[ {"shape":"ThrottlingException"}, + {"shape":"ConflictException"}, {"shape":"AccessDeniedException"}, {"shape":"InternalServerException"}, {"shape":"ValidationException"}, @@ -550,7 +571,7 @@ {"shape":"ValidationException"}, {"shape":"ResourceNotFoundException"} ], - "documentation":"

    Starts a resource snapshot job that has been previously created.

    ", + "documentation":"

    Starts a resource snapshot job that has been previously created.

    ", "idempotent":true }, "StopResourceSnapshotJob":{ @@ -566,7 +587,7 @@ {"shape":"ValidationException"}, {"shape":"ResourceNotFoundException"} ], - "documentation":"

    Stops a resource snapshot job. The job must be started prior to being stopped.

    ", + "documentation":"

    Stops a resource snapshot job. The job must be started prior to being stopped.

    ", "idempotent":true }, "SubmitOpportunity":{ @@ -583,7 +604,45 @@ {"shape":"ValidationException"}, {"shape":"ResourceNotFoundException"} ], - "documentation":"

    Use this action to submit an opportunity that was previously created by partner for AWS review. After you perform this action, the opportunity becomes non-editable until it is reviewed by AWS and has LifeCycle.ReviewStatus as either Approved or Action Required.

    " + "documentation":"

    Use this action to submit an Opportunity that was previously created by partner for AWS review. After you perform this action, the Opportunity becomes non-editable until it is reviewed by AWS and has LifeCycle.ReviewStatus as either Approved or Action Required.

    " + }, + "TagResource":{ + "name":"TagResource", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"TagResourceRequest"}, + "output":{"shape":"TagResourceResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ConflictException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"} + ], + "documentation":"

    Assigns one or more tags (key-value pairs) to the specified resource.

    ", + "idempotent":true + }, + "UntagResource":{ + "name":"UntagResource", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"UntagResourceRequest"}, + "output":{"shape":"UntagResourceResponse"}, + "errors":[ + {"shape":"ThrottlingException"}, + {"shape":"ConflictException"}, + {"shape":"AccessDeniedException"}, + {"shape":"InternalServerException"}, + {"shape":"ValidationException"}, + {"shape":"ResourceNotFoundException"} + ], + "documentation":"

    Removes a tag or tags from a resource.

    ", + "idempotent":true }, "UpdateOpportunity":{ "name":"UpdateOpportunity", @@ -614,7 +673,7 @@ "members":{ "Catalog":{ "shape":"CatalogIdentifier", - "documentation":"

    The CatalogType parameter specifies the catalog associated with the engagement invitation. Accepted values are AWS and Sandbox, which determine the environment in which the engagement invitation is managed.

    " + "documentation":"

    The CatalogType parameter specifies the catalog associated with the engagement invitation. Accepted values are AWS and Sandbox, which determine the environment in which the engagement invitation is managed.

    " }, "Identifier":{ "shape":"EngagementInvitationArnOrIdentifier", @@ -1624,24 +1683,24 @@ "members":{ "Catalog":{ "shape":"CatalogIdentifier", - "documentation":"

    The CreateEngagementRequest$Catalog parameter specifies the catalog related to the engagement. Accepted values are AWS and Sandbox, which determine the environment in which the engagement is managed.

    " + "documentation":"

    The CreateEngagementRequest$Catalog parameter specifies the catalog related to the engagement. Accepted values are AWS and Sandbox, which determine the environment in which the engagement is managed.

    " }, "ClientToken":{ "shape":"CreateEngagementRequestClientTokenString", - "documentation":"

    The CreateEngagementRequest$ClientToken parameter specifies a unique, case-sensitive identifier to ensure that the request is handled exactly once. The value must not exceed sixty-four alphanumeric characters.

    ", + "documentation":"

    The CreateEngagementRequest$ClientToken parameter specifies a unique, case-sensitive identifier to ensure that the request is handled exactly once. The value must not exceed sixty-four alphanumeric characters.

    ", "idempotencyToken":true }, "Contexts":{ "shape":"EngagementContexts", - "documentation":"

    The Contexts field is a required array of objects, with a maximum of 5 contexts allowed, specifying detailed information about customer projects associated with the Engagement. Each context object contains a Type field indicating the context type, which must be CustomerProject in this version, and a Payload field containing the CustomerProject details. The CustomerProject object is composed of two main components: Customer and Project. The Customer object includes information such as CompanyName, WebsiteUrl, Industry, and CountryCode, providing essential details about the customer. The Project object contains Title, BusinessProblem, and TargetCompletionDate, offering insights into the specific project associated with the customer. This structure allows comprehensive context to be included within the Engagement, facilitating effective collaboration between parties by providing relevant customer and project information.

    " + "documentation":"

    The Contexts field is a required array of objects, with a maximum of 5 contexts allowed, specifying detailed information about customer projects associated with the Engagement. Each context object contains a Type field indicating the context type, which must be CustomerProject in this version, and a Payload field containing the CustomerProject details. The CustomerProject object is composed of two main components: Customer and Project. The Customer object includes information such as CompanyName, WebsiteUrl, Industry, and CountryCode, providing essential details about the customer. The Project object contains Title, BusinessProblem, and TargetCompletionDate, offering insights into the specific project associated with the customer. This structure allows comprehensive context to be included within the Engagement, facilitating effective collaboration between parties by providing relevant customer and project information.

    " }, "Description":{ "shape":"EngagementDescription", - "documentation":"

    Provides a description of the Engagement.

    " + "documentation":"

    Provides a description of the Engagement.

    " }, "Title":{ "shape":"EngagementTitle", - "documentation":"

    Specifies the title of the Engagement.

    " + "documentation":"

    Specifies the title of the Engagement.

    " } } }, @@ -1654,11 +1713,11 @@ "members":{ "Arn":{ "shape":"EngagementArn", - "documentation":"

    The Amazon Resource Name (ARN) that identifies the engagement.

    " + "documentation":"

    The Amazon Resource Name (ARN) that identifies the engagement.

    " }, "Id":{ "shape":"EngagementIdentifier", - "documentation":"

    Unique identifier assigned to the newly created engagement.

    " + "documentation":"

    Unique identifier assigned to the newly created engagement.

    " } } }, @@ -1712,7 +1771,7 @@ }, "PrimaryNeedsFromAws":{ "shape":"PrimaryNeedsFromAws", - "documentation":"

    Identifies the type of support the partner needs from Amazon Web Services.

    Valid values:

    • Cosell—Architectural Validation: Confirmation from Amazon Web Services that the partner's proposed solution architecture is aligned with Amazon Web Services best practices and poses minimal architectural risks.

    • Cosell—Business Presentation: Request Amazon Web Services seller's participation in a joint customer presentation.

    • Cosell—Competitive Information: Access to Amazon Web Services competitive resources and support for the partner's proposed solution.

    • Cosell—Pricing Assistance: Connect with an Amazon Web Services seller for support situations where a partner may be receiving an upfront discount on a service (for example: EDP deals).

    • Cosell—Technical Consultation: Connect with an Amazon Web Services Solutions Architect to address the partner's questions about the proposed solution.

    • Cosell—Total Cost of Ownership Evaluation: Assistance with quoting different cost savings of proposed solutions on Amazon Web Services versus on-premises or a traditional hosting environment.

    • Cosell—Deal Support: Request Amazon Web Services seller's support to progress the opportunity (for example: joint customer call, strategic positioning).

    • Cosell—Support for Public Tender/RFx: Opportunity related to the public sector where the partner needs Amazon Web Services RFx support.

    • Do Not Need Support from AWS Sales Rep: Indicates that a partner doesn't need support from an Amazon Web Services sales representative, and the partner solely manages the opportunity. It's possible to request coselling support on these opportunities at any stage during their lifecycles. This is also known as a for-visibility-only (FVO) opportunity.

    " + "documentation":"

    Identifies the type of support the partner needs from Amazon Web Services.

    Valid values:

    • Cosell—Architectural Validation: Confirmation from Amazon Web Services that the partner's proposed solution architecture is aligned with Amazon Web Services best practices and poses minimal architectural risks.

    • Cosell—Business Presentation: Request Amazon Web Services seller's participation in a joint customer presentation.

    • Cosell—Competitive Information: Access to Amazon Web Services competitive resources and support for the partner's proposed solution.

    • Cosell—Pricing Assistance: Connect with an Amazon Web Services seller for support situations where a partner may be receiving an upfront discount on a service (for example: EDP deals).

    • Cosell—Technical Consultation: Connect with an Amazon Web Services Solutions Architect to address the partner's questions about the proposed solution.

    • Cosell—Total Cost of Ownership Evaluation: Assistance with quoting different cost savings of proposed solutions on Amazon Web Services versus on-premises or a traditional hosting environment.

    • Cosell—Deal Support: Request Amazon Web Services seller's support to progress the opportunity (for example: joint customer call, strategic positioning).

    • Cosell—Support for Public Tender/RFx: Opportunity related to the public sector where the partner needs Amazon Web Services RFx support.

    " }, "Project":{ "shape":"Project", @@ -1764,28 +1823,32 @@ "members":{ "Catalog":{ "shape":"CatalogIdentifier", - "documentation":"

    Specifies the catalog in which to create the snapshot job. Valid values are AWS and Sandbox.

    " + "documentation":"

    Specifies the catalog in which to create the snapshot job. Valid values are AWS and Sandbox.

    " }, "ClientToken":{ "shape":"CreateResourceSnapshotJobRequestClientTokenString", - "documentation":"

    Specifies a unique, client-generated UUID to ensure that the request is handled exactly once. This token helps prevent duplicate snapshot job creations.

    ", + "documentation":"

    A client-generated UUID used for idempotency check. The token helps prevent duplicate job creations.

    ", "idempotencyToken":true }, "EngagementIdentifier":{ "shape":"EngagementIdentifier", - "documentation":"

    Specifies the identifier of the engagement associated with the resource to be snapshotted.

    " + "documentation":"

    Specifies the identifier of the engagement associated with the resource to be snapshotted.

    " }, "ResourceIdentifier":{ "shape":"ResourceIdentifier", - "documentation":"

    Specifies the identifier of the specific resource to be snapshotted. The format depends on the ResourceType.

    " + "documentation":"

    Specifies the identifier of the specific resource to be snapshotted. The format depends on the ResourceType.

    " }, "ResourceSnapshotTemplateIdentifier":{ "shape":"ResourceTemplateName", - "documentation":"

    Specifies the name of the template that defines the schema for the snapshot.

    " + "documentation":"

    Specifies the name of the template that defines the schema for the snapshot.

    " }, "ResourceType":{ "shape":"ResourceType", - "documentation":"

    The type of resource for which the snapshot job is being created. Must be one of the supported resource types Opportunity.

    " + "documentation":"

    The type of resource for which the snapshot job is being created. Must be one of the supported resource types i.e. Opportunity

    " + }, + "Tags":{ + "shape":"TagList", + "documentation":"

    A list of objects specifying each tag name and value.

    " } } }, @@ -1798,11 +1861,11 @@ "members":{ "Arn":{ "shape":"ResourceSnapshotJobArn", - "documentation":"

    The Amazon Resource Name (ARN) of the created snapshot job.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the created snapshot job.

    " }, "Id":{ "shape":"ResourceSnapshotJobIdentifier", - "documentation":"

    The unique identifier for the created snapshot job.

    " + "documentation":"

    The unique identifier for the created snapshot job.

    " } } }, @@ -2059,10 +2122,10 @@ "Customer":{"shape":"EngagementCustomer"}, "Project":{ "shape":"EngagementCustomerProjectDetails", - "documentation":"

    Information about the customer project associated with the Engagement.

    " + "documentation":"

    Information about the customer project associated with the Engagement.

    " } }, - "documentation":"

    The CustomerProjects structure in Engagements offers a flexible framework for managing customer-project relationships. It supports multiple customers per Engagement and multiple projects per customer, while also allowing for customers without projects and projects without specific customers.

    All Engagement members have full visibility of customers and their associated projects, enabling the capture of relevant context even when project details are not fully defined. This structure also facilitates targeted invitations, allowing partners to focus on specific customers and their business problems when sending Engagement invitations.

    " + "documentation":"

    The CustomerProjects structure in Engagements offers a flexible framework for managing customer-project relationships. It supports multiple customers per Engagement and multiple projects per customer, while also allowing for customers without projects and projects without specific customers.

    All Engagement members have full visibility of customers and their associated projects, enabling the capture of relevant context even when project details are not fully defined. This structure also facilitates targeted invitations, allowing partners to focus on specific customers and their business problems when sending Engagement invitations.

    " }, "CustomerSummary":{ "type":"structure", @@ -2172,24 +2235,24 @@ "members":{ "Payload":{ "shape":"EngagementContextPayload", - "documentation":"

    Contains the specific details of the Engagement context. The structure of this payload varies depending on the Type field.

    " + "documentation":"

    Contains the specific details of the Engagement context. The structure of this payload varies depending on the Type field.

    " }, "Type":{ "shape":"EngagementContextType", - "documentation":"

    Specifies the type of Engagement context. Valid values are \"CustomerProject\" or \"Document\", indicating whether the context relates to a customer project or a document respectively.

    " + "documentation":"

    Specifies the type of Engagement context. Valid values are \"CustomerProject\" or \"Document\", indicating whether the context relates to a customer project or a document respectively.

    " } }, - "documentation":"

    Provides detailed context information for an Engagement. This structure allows for specifying the type of context and its associated payload.

    " + "documentation":"

    Provides detailed context information for an Engagement. This structure allows for specifying the type of context and its associated payload.

    " }, "EngagementContextPayload":{ "type":"structure", "members":{ "CustomerProject":{ "shape":"CustomerProjectsContext", - "documentation":"

    Contains detailed information about a customer project when the context type is \"CustomerProject\". This field is present only when the Type in EngagementContextDetails is set to \"CustomerProject\".

    " + "documentation":"

    Contains detailed information about a customer project when the context type is \"CustomerProject\". This field is present only when the Type in EngagementContextDetails is set to \"CustomerProject\".

    " } }, - "documentation":"

    Represents the payload of an Engagement context. The structure of this payload varies based on the context type specified in the EngagementContextDetails.

    ", + "documentation":"

    Represents the payload of an Engagement context. The structure of this payload varies based on the context type specified in the EngagementContextDetails.

    ", "union":true }, "EngagementContextType":{ @@ -2246,18 +2309,18 @@ "members":{ "BusinessProblem":{ "shape":"EngagementCustomerBusinessProblem", - "documentation":"

    A description of the business problem the project aims to solve.

    " + "documentation":"

    A description of the business problem the project aims to solve.

    " }, "TargetCompletionDate":{ "shape":"EngagementCustomerProjectDetailsTargetCompletionDateString", - "documentation":"

    The target completion date for the customer's project.

    " + "documentation":"

    The target completion date for the customer's project.

    " }, "Title":{ "shape":"EngagementCustomerProjectTitle", - "documentation":"

    The title of the project.

    " + "documentation":"

    The title of the project.

    " } }, - "documentation":"

    Provides comprehensive details about a customer project associated with an Engagement. This may include information such as project goals, timelines, and specific customer requirements.

    " + "documentation":"

    Provides comprehensive details about a customer project associated with an Engagement. This may include information such as project goals, timelines, and specific customer requirements.

    " }, "EngagementCustomerProjectDetailsTargetCompletionDateString":{ "type":"string", @@ -2387,15 +2450,15 @@ "members":{ "AccountId":{ "shape":"AwsAccount", - "documentation":"

    This is the unique identifier for the AWS account associated with the member organization. It's used for AWS-related operations and identity verification.

    " + "documentation":"

    This is the unique identifier for the AWS account associated with the member organization. It's used for AWS-related operations and identity verification.

    " }, "CompanyName":{ "shape":"MemberCompanyName", - "documentation":"

    The official name of the member's company or organization.

    " + "documentation":"

    The official name of the member's company or organization.

    " }, "WebsiteUrl":{ "shape":"String", - "documentation":"

    The URL of the member company's website. This offers a way to find more information about the member organization and serves as an additional identifier.

    " + "documentation":"

    The URL of the member company's website. This offers a way to find more information about the member organization and serves as an additional identifier.

    " } }, "documentation":"

    Engagement members are the participants in an Engagement, which is likely a collaborative project or business opportunity within the AWS partner network. Members can be different partner organizations or AWS accounts that are working together on a specific engagement.

    Each member is represented by their AWS Account ID, Company Name, and associated details. Members have a status within the Engagement (PENDING, ACCEPTED, REJECTED, or WITHDRAWN), indicating their current state of participation. Only existing members of an Engagement can view the list of other members. This implies a level of privacy and access control within the Engagement structure.

    " @@ -2409,14 +2472,14 @@ "members":{ "CompanyName":{ "shape":"MemberCompanyName", - "documentation":"

    The official name of the member's company or organization.

    " + "documentation":"

    The official name of the member's company or organization.

    " }, "WebsiteUrl":{ "shape":"String", - "documentation":"

    The URL of the member company's website. This offers a way to find more information about the member organization and serves as an additional identifier.

    " + "documentation":"

    The URL of the member company's website. This offers a way to find more information about the member organization and serves as an additional identifier.

    " } }, - "documentation":"

    The EngagementMemberSummary provides a snapshot of essential information about participants in an AWS Partner Central Engagement. This compact data structure encapsulates key details of each member, facilitating efficient collaboration and management within the Engagement.

    " + "documentation":"

    The EngagementMemberSummary provides a snapshot of essential information about participants in an AWS Partner Central Engagement. This compact data structure encapsulates key details of each member, facilitating efficient collaboration and management within the Engagement.

    " }, "EngagementMembers":{ "type":"list", @@ -2440,7 +2503,7 @@ }, "CreatedBy":{ "shape":"AwsAccount", - "documentation":"

    The AWS account ID of the entity that created the association.

    " + "documentation":"

    The AWS account ID of the entity that owns the resource. Identifies the account responsible for or having primary control over the resource.

    " }, "EngagementId":{ "shape":"EngagementIdentifier", @@ -2478,14 +2541,14 @@ "members":{ "SortBy":{ "shape":"EngagementSortName", - "documentation":"

    The field by which to sort the results.

    " + "documentation":"

    The field by which to sort the results.

    " }, "SortOrder":{ "shape":"SortOrder", - "documentation":"

    The order in which to sort the results.

    " + "documentation":"

    The order in which to sort the results.

    " } }, - "documentation":"

    Specifies the sorting parameters for listing Engagements.

    " + "documentation":"

    Specifies the sorting parameters for listing Engagements.

    " }, "EngagementSortName":{ "type":"string", @@ -2496,30 +2559,30 @@ "members":{ "Arn":{ "shape":"EngagementArn", - "documentation":"

    The Amazon Resource Name (ARN) of the created engagement.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the created Engagement.

    " }, "CreatedAt":{ "shape":"DateTime", - "documentation":"

    The date and time when the engagement was created.

    " + "documentation":"

    The date and time when the Engagement was created.

    " }, "CreatedBy":{ "shape":"AwsAccount", - "documentation":"

    The AWS account ID of the engagement creator.

    " + "documentation":"

    The AWS Account ID of the Engagement creator.

    " }, "Id":{ "shape":"EngagementIdentifier", - "documentation":"

    The unique identifier for the engagement.

    " + "documentation":"

    The unique identifier for the Engagement.

    " }, "MemberCount":{ "shape":"Integer", - "documentation":"

    The number of members in the engagement.

    " + "documentation":"

    The number of members in the Engagement.

    " }, "Title":{ "shape":"EngagementTitle", - "documentation":"

    The title of the engagement.

    " + "documentation":"

    The title of the Engagement.

    " } }, - "documentation":"

    An object that contains an Engagement's subset of fields.

    " + "documentation":"

    An object that contains an Engagement's subset of fields.

    " }, "EngagementSummaryList":{ "type":"list", @@ -2549,7 +2612,7 @@ }, "EstimationUrl":{ "shape":"WebsiteUrl", - "documentation":"

    A URL providing additional information or context about the spend estimation.

    " + "documentation":"

    A URL providing additional information or context about the spend estimation.

    " }, "Frequency":{ "shape":"PaymentFrequency", @@ -2852,11 +2915,11 @@ }, "EngagementDescription":{ "shape":"EngagementDescription", - "documentation":"

    The description of the engagement associated with this invitation.

    " + "documentation":"

    The description of the engagement associated with this invitation.

    " }, "EngagementId":{ "shape":"EngagementIdentifier", - "documentation":"

    The identifier of the engagement associated with this invitation.This ID links the invitation to its corresponding engagement.

    " + "documentation":"

    The identifier of the engagement associated with this invitation.This ID links the invitation to its corresponding engagement.

    " }, "EngagementTitle":{ "shape":"EngagementTitle", @@ -2864,7 +2927,7 @@ }, "ExistingMembers":{ "shape":"EngagementMemberSummaries", - "documentation":"

    A list of active members currently part of the Engagement. This array contains a maximum of 10 members, each represented by an object with the following properties.

    • CompanyName: The name of the member's company.

    • WebsiteUrl: The website URL of the member's company.

    " + "documentation":"

    A list of active members currently part of the Engagement. This array contains a maximum of 10 members, each represented by an object with the following properties.

    • CompanyName: The name of the member's company.

    • WebsiteUrl: The website URL of the member's company.

    " }, "ExpirationDate":{ "shape":"DateTime", @@ -2880,7 +2943,7 @@ }, "InvitationMessage":{ "shape":"InvitationMessage", - "documentation":"

    The message sent to the invited partner when the invitation was created.

    " + "documentation":"

    The message sent to the invited partner when the invitation was created.

    " }, "Payload":{ "shape":"Payload", @@ -2926,11 +2989,11 @@ "members":{ "Catalog":{ "shape":"CatalogIdentifier", - "documentation":"

    Specifies the catalog related to the engagement request. Valid values are AWS and Sandbox.

    " + "documentation":"

    Specifies the catalog related to the engagement request. Valid values are AWS and Sandbox.

    " }, "Identifier":{ "shape":"EngagementArnOrIdentifier", - "documentation":"

    Specifies the identifier of the Engagement record to retrieve.

    " + "documentation":"

    Specifies the identifier of the Engagement record to retrieve.

    " } } }, @@ -2939,35 +3002,35 @@ "members":{ "Arn":{ "shape":"EngagementArn", - "documentation":"

    The Amazon Resource Name (ARN) of the engagement retrieved.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the engagement retrieved.

    " }, "Contexts":{ "shape":"EngagementContexts", - "documentation":"

    A list of context objects associated with the engagement. Each context provides additional information related to the Engagement, such as customer projects or documents.

    " + "documentation":"

    A list of context objects associated with the engagement. Each context provides additional information related to the Engagement, such as customer projects or documents.

    " }, "CreatedAt":{ "shape":"DateTime", - "documentation":"

    The date and time when the Engagement was created, presented in ISO 8601 format (UTC). For example: \"2023-05-01T20:37:46Z\". This timestamp helps track the lifecycle of the Engagement.

    " + "documentation":"

    The date and time when the Engagement was created, presented in ISO 8601 format (UTC). For example: \"2023-05-01T20:37:46Z\". This timestamp helps track the lifecycle of the Engagement.

    " }, "CreatedBy":{ "shape":"AwsAccount", - "documentation":"

    The AWS account ID of the user who originally created the engagement. This field helps in tracking the origin of the engagement.

    " + "documentation":"

    The AWS account ID of the user who originally created the engagement. This field helps in tracking the origin of the engagement.

    " }, "Description":{ "shape":"EngagementDescription", - "documentation":"

    A more detailed description of the engagement. This provides additional context or information about the engagement's purpose or scope.

    " + "documentation":"

    A more detailed description of the engagement. This provides additional context or information about the engagement's purpose or scope.

    " }, "Id":{ "shape":"EngagementIdentifier", - "documentation":"

    The unique resource identifier of the engagement retrieved.

    " + "documentation":"

    The unique resource identifier of the engagement retrieved.

    " }, "MemberCount":{ "shape":"Integer", - "documentation":"

    Specifies the current count of members participating in the Engagement. This count includes all active members regardless of their roles or permissions within the Engagement.

    " + "documentation":"

    Specifies the current count of members participating in the Engagement. This count includes all active members regardless of their roles or permissions within the Engagement.

    " }, "Title":{ "shape":"EngagementTitle", - "documentation":"

    The title of the engagement. It provides a brief, descriptive name for the engagement that is meaningful and easily recognizable.

    " + "documentation":"

    The title of the engagement. It provides a brief, descriptive name for the engagement that is meaningful and easily recognizable.

    " } } }, @@ -3048,7 +3111,7 @@ }, "PrimaryNeedsFromAws":{ "shape":"PrimaryNeedsFromAws", - "documentation":"

    Identifies the type of support the partner needs from Amazon Web Services.

    Valid values:

    • Cosell—Architectural Validation: Confirmation from Amazon Web Services that the partner's proposed solution architecture is aligned with Amazon Web Services best practices and poses minimal architectural risks.

    • Cosell—Business Presentation: Request Amazon Web Services seller's participation in a joint customer presentation.

    • Cosell—Competitive Information: Access to Amazon Web Services competitive resources and support for the partner's proposed solution.

    • Cosell—Pricing Assistance: Connect with an Amazon Web Services seller for support situations where a partner may be receiving an upfront discount on a service (for example: EDP deals).

    • Cosell—Technical Consultation: Connect with an Amazon Web Services Solutions Architect to address the partner's questions about the proposed solution.

    • Cosell—Total Cost of Ownership Evaluation: Assistance with quoting different cost savings of proposed solutions on Amazon Web Services versus on-premises or a traditional hosting environment.

    • Cosell—Deal Support: Request Amazon Web Services seller's support to progress the opportunity (for example: joint customer call, strategic positioning).

    • Cosell—Support for Public Tender/RFx: Opportunity related to the public sector where the partner needs Amazon Web Services RFx support.

    • Do Not Need Support from Amazon Web Services Sales Rep: Indicates that a partner doesn't need support from an Amazon Web Services sales representative, and the partner solely manages the opportunity. It's possible to request coselling support on these opportunities at any stage during their lifecycle. Also known as, for-visibility-only (FVO) opportunity.

    " + "documentation":"

    Identifies the type of support the partner needs from Amazon Web Services.

    Valid values:

    • Cosell—Architectural Validation: Confirmation from Amazon Web Services that the partner's proposed solution architecture is aligned with Amazon Web Services best practices and poses minimal architectural risks.

    • Cosell—Business Presentation: Request Amazon Web Services seller's participation in a joint customer presentation.

    • Cosell—Competitive Information: Access to Amazon Web Services competitive resources and support for the partner's proposed solution.

    • Cosell—Pricing Assistance: Connect with an Amazon Web Services seller for support situations where a partner may be receiving an upfront discount on a service (for example: EDP deals).

    • Cosell—Technical Consultation: Connect with an Amazon Web Services Solutions Architect to address the partner's questions about the proposed solution.

    • Cosell—Total Cost of Ownership Evaluation: Assistance with quoting different cost savings of proposed solutions on Amazon Web Services versus on-premises or a traditional hosting environment.

    • Cosell—Deal Support: Request Amazon Web Services seller's support to progress the opportunity (for example: joint customer call, strategic positioning).

    • Cosell—Support for Public Tender/RFx: Opportunity related to the public sector where the partner needs Amazon Web Services RFx support.

    " }, "Project":{ "shape":"Project", @@ -3078,11 +3141,11 @@ "members":{ "Catalog":{ "shape":"CatalogIdentifier", - "documentation":"

    Specifies the catalog related to the request. Valid values are:

    • AWS: Retrieves the snapshot job from the production AWS environment.

    • Sandbox: Retrieves the snapshot job from a sandbox environment used for testing or development purposes.

    " + "documentation":"

    Specifies the catalog related to the request. Valid values are:

    • AWS: Retrieves the snapshot job from the production AWS environment.

    • Sandbox: Retrieves the snapshot job from a sandbox environment used for testing or development purposes.

    " }, "ResourceSnapshotJobIdentifier":{ "shape":"ResourceSnapshotJobIdentifier", - "documentation":"

    The unique identifier of the resource snapshot job to be retrieved. This identifier is crucial for pinpointing the specific job you want to query.

    " + "documentation":"

    The unique identifier of the resource snapshot job to be retrieved. This identifier is crucial for pinpointing the specific job you want to query.

    " } } }, @@ -3092,51 +3155,51 @@ "members":{ "Arn":{ "shape":"ResourceSnapshotJobArn", - "documentation":"

    he Amazon Resource Name (ARN) of the snapshot job. This globally unique identifier can be used for resource-specific operations across AWS services.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the snapshot job. This globally unique identifier can be used for resource-specific operations across AWS services.

    " }, "Catalog":{ "shape":"CatalogIdentifier", - "documentation":"

    The catalog in which the snapshot job was created. This will match the catalog specified in the request.

    " + "documentation":"

    The catalog in which the snapshot job was created. This will match the Catalog specified in the request.

    " }, "CreatedAt":{ "shape":"DateTime", - "documentation":"

    The date and time when the snapshot job was created, in ISO 8601 format (UTC). Example: \"2023-05-01T20:37:46Z\"

    " + "documentation":"

    The date and time when the snapshot job was created in ISO 8601 format (UTC). Example: \"2023-05-01T20:37:46Z\"

    " }, "EngagementId":{ "shape":"EngagementIdentifier", - "documentation":"

    The identifier of the engagement associated with this snapshot job. This links the job to a specific engagement context.

    " + "documentation":"

    The identifier of the engagement associated with this snapshot job. This links the job to a specific engagement context.

    " }, "Id":{ "shape":"ResourceSnapshotJobIdentifier", - "documentation":"

    The unique identifier of the snapshot job. This matches the ResourceSnapshotJobIdentifier provided in the request.

    " + "documentation":"

    The unique identifier of the snapshot job. This matches the ResourceSnapshotJobIdentifier provided in the request.

    " }, "LastFailure":{ "shape":"String", - "documentation":"

    If the job has encountered any failures, this field contains the error message from the most recent failure. This can be useful for troubleshooting issues with the job.

    " + "documentation":"

    If the job has encountered any failures, this field contains the error message from the most recent failure. This can be useful for troubleshooting issues with the job.

    " }, "LastSuccessfulExecutionDate":{ "shape":"DateTime", - "documentation":"

    The date and time of the last successful execution of the job, in ISO 8601 format (UTC). Example: \"2023-05-01T20:37:46Z\"

    " + "documentation":"

    The date and time of the last successful execution of the job, in ISO 8601 format (UTC). Example: \"2023-05-01T20:37:46Z\"

    " }, "ResourceArn":{ "shape":"ResourceArn", - "documentation":"

    The Amazon Resource Name (ARN) of the resource being snapshotted. This provides a globally unique identifier for the resource across AWS.

    " + "documentation":"

    The Amazon Resource Name (ARN) of the resource being snapshotted. This provides a globally unique identifier for the resource across AWS.

    " }, "ResourceId":{ "shape":"ResourceIdentifier", - "documentation":"

    The identifier of the specific resource being snapshotted. The format may vary depending on the ResourceType.

    " + "documentation":"

    The identifier of the specific resource being snapshotted. The format might vary depending on the ResourceType.

    " }, "ResourceSnapshotTemplateName":{ "shape":"ResourceTemplateName", - "documentation":"

    The name of the template used for creating the snapshot. This is the same as the template name. It defines the structure and content of the snapshot.

    " + "documentation":"

    The name of the template used for creating the snapshot. This is the same as the template name. It defines the structure and content of the snapshot.

    " }, "ResourceType":{ "shape":"ResourceType", - "documentation":"

    The type of resource being snapshotted. This would have Opportunity as a value as it is dependent on the supported resource type.

    " + "documentation":"

    The type of resource being snapshotted. This would have \"Opportunity\" as a value as it is dependent on the supported resource type.

    " }, "Status":{ "shape":"ResourceSnapshotJobStatus", - "documentation":"

    The current status of the snapshot job. Valid values:

    • STOPPED: The job is not currently running.

    • RUNNING: The job is actively executing.

    " + "documentation":"

    The current status of the snapshot job. Valid values:

    • STOPPED: The job is not currently running.

    • RUNNING: The job is actively executing.

    " } } }, @@ -3182,7 +3245,7 @@ "members":{ "Arn":{ "shape":"ResourceArn", - "documentation":"

    The Amazon Resource Name (ARN) of the snapshot. This globally unique identifier can be used for resource-specific operations across AWS services.

    " + "documentation":"

    The Amazon Resource Name (ARN) that uniquely identifies the resource snapshot.

    " }, "Catalog":{ "shape":"CatalogIdentifier", @@ -3203,19 +3266,19 @@ "Payload":{"shape":"ResourceSnapshotPayload"}, "ResourceId":{ "shape":"ResourceIdentifier", - "documentation":"

    The identifier of the specific resource that was snapshotted. Matches the ResourceIdentifier specified in the request.

    " + "documentation":"

    The identifier of the specific resource that was snapshotted. Matches the ResourceIdentifier specified in the request.

    " }, "ResourceSnapshotTemplateName":{ "shape":"ResourceTemplateName", - "documentation":"

    The name of the view used for this snapshot. This is the same as the template name.

    " + "documentation":"

    The name of the view used for this snapshot. This is the same as the template name.

    " }, "ResourceType":{ "shape":"ResourceType", - "documentation":"

    The type of the resource that was snapshotted. Matches the ResourceType specified in the request.

    " + "documentation":"

    The type of the resource that was snapshotted. Matches the ResourceType specified in the request.

    " }, "Revision":{ "shape":"ResourceSnapshotRevision", - "documentation":"

    The revision number of this snapshot. This is a positive integer that is sequential and unique within the context of a resource view.

    " + "documentation":"

    The revision number of this snapshot. This is a positive integer that is sequential and unique within the context of a resource view.

    " } } }, @@ -3595,7 +3658,7 @@ }, "EngagementInvitationId":{ "shape":"EngagementInvitationIdentifier", - "documentation":"

    The unique identifier of the engagement identifier created as a result of the task. This field is populated when the task is completed successfully.

    " + "documentation":"

    The unique identifier of the Engagement Invitation.

    " }, "Message":{ "shape":"String", @@ -3761,19 +3824,19 @@ "members":{ "Catalog":{ "shape":"CatalogIdentifier", - "documentation":"

    The catalog related to the request.

    " + "documentation":"

    The catalog related to the request.

    " }, "Identifier":{ "shape":"EngagementArnOrIdentifier", - "documentation":"

    Identifier of the engagement record to retrieve members from.

    " + "documentation":"

    Identifier of the Engagement record to retrieve members from.

    " }, "MaxResults":{ "shape":"MemberPageSize", - "documentation":"

    The maximum number of results to return in a single call.

    " + "documentation":"

    The maximum number of results to return in a single call.

    " }, "NextToken":{ "shape":"String", - "documentation":"

    The token for the next set of results.

    " + "documentation":"

    The token for the next set of results.

    " } } }, @@ -3787,7 +3850,7 @@ }, "NextToken":{ "shape":"String", - "documentation":"

    A pagination token used to retrieve the next set of results. If there are more results available than can be returned in a single response, this token will be present. Use this token in a subsequent request to retrieve the next page of results. If there are no more results, this value will be null.

    " + "documentation":"

    A pagination token used to retrieve the next set of results. If there are more results available than can be returned in a single response, this token will be present. Use this token in a subsequent request to retrieve the next page of results. If there are no more results, this value will be null.

    " } } }, @@ -3797,27 +3860,27 @@ "members":{ "Catalog":{ "shape":"CatalogIdentifier", - "documentation":"

    Specifies the catalog in which to search for engagement-resource associations.

    " + "documentation":"

    Specifies the catalog in which to search for engagement-resource associations. Valid Values: \"AWS\" or \"Sandbox\"

    • AWS for production environments.

    • Sandbox for testing and development purposes.

    " }, "CreatedBy":{ "shape":"AwsAccount", - "documentation":"

    Filters the results to include only associations with resources owned by the specified AWS account. Use this when you want to find associations related to resources owned by a particular account.

    " + "documentation":"

    Filters the response to include only snapshots of resources owned by the specified AWS account ID. Use this when you want to find associations related to resources owned by a particular account.

    " }, "EngagementIdentifier":{ "shape":"EngagementIdentifier", - "documentation":"

    Filters the results to include only associations related to the specified engagement. Use this when you want to find all resources associated with a specific engagement.

    " + "documentation":"

    Filters the results to include only associations related to the specified engagement. Use this when you want to find all resources associated with a specific engagement.

    " }, "MaxResults":{ "shape":"ListEngagementResourceAssociationsRequestMaxResultsInteger", - "documentation":"

    Limits the number of results returned in a single call. Use this to control the number of results returned, especially useful for pagination.

    " + "documentation":"

    Limits the number of results returned in a single call. Use this to control the number of results returned, especially useful for pagination.

    " }, "NextToken":{ "shape":"String", - "documentation":"

    A token used for pagination of results. Include this token in subsequent requests to retrieve the next set of results.

    " + "documentation":"

    A token used for pagination of results. Include this token in subsequent requests to retrieve the next set of results.

    " }, "ResourceIdentifier":{ "shape":"ResourceIdentifier", - "documentation":"

    Filters the results to include only associations with the specified resource. Varies depending on the resource type. Use this when you want to find all engagements associated with a specific resource.

    " + "documentation":"

    Filters the results to include only associations with the specified resource. Varies depending on the resource type. Use this when you want to find all engagements associated with a specific resource.

    " }, "ResourceType":{ "shape":"ResourceType", @@ -3859,19 +3922,19 @@ }, "EngagementIdentifier":{ "shape":"EngagementIdentifiers", - "documentation":"

    An array of strings representing engagement identifiers to retrieve.

    " + "documentation":"

    An array of strings representing engagement identifiers to retrieve.

    " }, "ExcludeCreatedBy":{ "shape":"AwsAccountList", - "documentation":"

    An array of strings representing AWS Account IDs. Use this to exclude engagements created by specific users.

    " + "documentation":"

    An array of strings representing AWS Account IDs. Use this to exclude engagements created by specific users.

    " }, "MaxResults":{ "shape":"EngagementPageSize", - "documentation":"

    The maximum number of results to return in a single call.

    " + "documentation":"

    The maximum number of results to return in a single call.

    " }, "NextToken":{ "shape":"String", - "documentation":"

    The token for the next set of results. This value is returned from a previous call.

    " + "documentation":"

    The token for the next set of results. This value is returned from a previous call.

    " }, "Sort":{ "shape":"EngagementSort", @@ -3885,11 +3948,11 @@ "members":{ "EngagementSummaryList":{ "shape":"EngagementSummaryList", - "documentation":"

    An array of engagement summary objects.

    " + "documentation":"

    An array of engagement summary objects.

    " }, "NextToken":{ "shape":"String", - "documentation":"

    The token to retrieve the next set of results. This field will be null if there are no more results.

    " + "documentation":"

    The token to retrieve the next set of results. This field will be null if there are no more results.

    " } } }, @@ -4036,7 +4099,7 @@ }, "CreatedBy":{ "shape":"AwsAccount", - "documentation":"

    Filters the response to include only snapshots of resources created by the specified AWS account.

    " + "documentation":"

    Filters the response to include only snapshots of resources owned by the specified AWS account.

    " }, "EngagementIdentifier":{ "shape":"EngagementIdentifier", @@ -4056,7 +4119,7 @@ }, "ResourceSnapshotTemplateIdentifier":{ "shape":"ResourceTemplateName", - "documentation":"

    Filters the response to include only snapshots created using the specified template.

    " + "documentation":"

    Filters the response to include only snapshots created using the specified template.

    " }, "ResourceType":{ "shape":"ResourceType", @@ -4150,6 +4213,26 @@ } } }, + "ListTagsForResourceRequest":{ + "type":"structure", + "required":["ResourceArn"], + "members":{ + "ResourceArn":{ + "shape":"TaggableResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the resource for which you want to retrieve tags.

    " + } + } + }, + "ListTagsForResourceResponse":{ + "type":"structure", + "required":["Tags"], + "members":{ + "Tags":{ + "shape":"TagList", + "documentation":"

    A map of the key-value pairs for the tag or tags assigned to the specified resource.

    " + } + } + }, "ListTasksSortBase":{ "type":"structure", "required":[ @@ -4731,12 +4814,12 @@ "EngagementConflict", "OpportunitySubmissionFailed", "EngagementInvitationConflict", + "InternalError", "OpportunityValidationFailed", "OpportunityConflict", "ResourceSnapshotAccessDenied", "ResourceSnapshotValidationFailed", "ResourceSnapshotConflict", - "InternalError", "ServiceQuotaExceeded", "RequestThrottled" ] @@ -4877,7 +4960,7 @@ }, "EngagementId":{ "shape":"EngagementIdentifier", - "documentation":"

    The unique identifier for the engagement within the AWS Partner Central system. This ID is used for direct references to the engagement within the service.

    " + "documentation":"

    The unique identifier of the Engagement.

    " }, "Id":{ "shape":"ResourceSnapshotJobIdentifier", @@ -4885,7 +4968,7 @@ }, "Status":{ "shape":"ResourceSnapshotJobStatus", - "documentation":"

    Represents the current status of the resource snapshot job.

    " + "documentation":"

    The current status of the snapshot job.

    Valid values:

    • STOPPED: The job is not currently running.

    • RUNNING: The job is actively executing.

    " } }, "documentation":"

    An object that contains a Resource Snapshot Job's subset of fields.

    " @@ -4919,7 +5002,7 @@ }, "CreatedBy":{ "shape":"AwsAccount", - "documentation":"

    The AWS account ID of the principal (user or role) who created the snapshot. This helps in tracking the origin of the snapshot.

    " + "documentation":"

    The AWS account ID of the entity that owns the resource from which the snapshot was created.

    " }, "ResourceId":{ "shape":"ResourceIdentifier", @@ -4935,7 +5018,7 @@ }, "Revision":{ "shape":"ResourceSnapshotRevision", - "documentation":"

    The revision number of the snapshot. This integer value is incremented each time the snapshot is updated, allowing for version tracking of the resource snapshot.

    " + "documentation":"

    The revision number of the snapshot. This integer value is incremented each time the snapshot is updated, allowing for version tracking of the resource snapshot.

    " } }, "documentation":"

    Provides a concise summary of a resource snapshot, including its unique identifier and version information. This structure is used to quickly reference and identify specific versions of resource snapshots.

    " @@ -5216,6 +5299,10 @@ "Identifier":{ "shape":"EngagementInvitationArnOrIdentifier", "documentation":"

    Specifies the unique identifier of the EngagementInvitation to be accepted. Providing the correct identifier helps ensure that the correct engagement is processed.

    " + }, + "Tags":{ + "shape":"TagList", + "documentation":"

    A list of objects specifying each tag name and value.

    " } } }, @@ -5245,7 +5332,7 @@ }, "ResourceSnapshotJobId":{ "shape":"ResourceSnapshotJobIdentifier", - "documentation":"

    The identifier of the resource snapshot job created as part of this task.

    " + "documentation":"

    The identifier of the Resource Snapshot Job created as part of this task.

    " }, "StartTime":{ "shape":"DateTime", @@ -5287,6 +5374,10 @@ "Identifier":{ "shape":"OpportunityIdentifier", "documentation":"

    The unique identifier of the opportunity from which the engagement task is to be initiated. This helps ensure that the task is applied to the correct opportunity.

    " + }, + "Tags":{ + "shape":"TagList", + "documentation":"

    A list of objects specifying each tag name and value.

    " } } }, @@ -5300,11 +5391,11 @@ "members":{ "EngagementId":{ "shape":"EngagementIdentifier", - "documentation":"

    The identifier of the newly created engagement. Only populated if TaskStatus is COMPLETE.

    " + "documentation":"

    The identifier of the newly created Engagement. Only populated if TaskStatus is COMPLETE.

    " }, "EngagementInvitationId":{ "shape":"EngagementInvitationIdentifier", - "documentation":"

    The identifier of the new engagement invitation. Only populated if TaskStatus is COMPLETE.

    " + "documentation":"

    The identifier of the new Engagement invitation. Only populated if TaskStatus is COMPLETE.

    " }, "Message":{ "shape":"String", @@ -5320,7 +5411,7 @@ }, "ResourceSnapshotJobId":{ "shape":"ResourceSnapshotJobIdentifier", - "documentation":"

    The identifier of the resource snapshot job created to add the opportunity resource snapshot to the Engagement. Only populated if TaskStatus is COMPLETE.

    " + "documentation":"

    The identifier of the resource snapshot job created to add the opportunity resource snapshot to the Engagement. Only populated if TaskStatus is COMPLETE

    " }, "StartTime":{ "shape":"DateTime", @@ -5349,11 +5440,11 @@ "members":{ "Catalog":{ "shape":"CatalogIdentifier", - "documentation":"

    Specifies the catalog related to the request.

    " + "documentation":"

    Specifies the catalog related to the request. Valid values are:

    • AWS: Starts the request from the production AWS environment.

    • Sandbox: Starts the request from a sandbox environment used for testing or development purposes.

    " }, "ResourceSnapshotJobIdentifier":{ "shape":"ResourceSnapshotJobIdentifier", - "documentation":"

    The identifier of the resource snapshot job to start.

    " + "documentation":"

    The identifier of the resource snapshot job to start.

    " } } }, @@ -5366,11 +5457,11 @@ "members":{ "Catalog":{ "shape":"CatalogIdentifier", - "documentation":"

    Specifies the catalog related to the request.

    " + "documentation":"

    Specifies the catalog related to the request. Valid values are:

    • AWS: Stops the request from the production AWS environment.

    • Sandbox: Stops the request from a sandbox environment used for testing or development purposes.

    " }, "ResourceSnapshotJobIdentifier":{ "shape":"ResourceSnapshotJobIdentifier", - "documentation":"

    The identifier of the job to stop.

    " + "documentation":"

    The identifier of the job to stop.

    " } } }, @@ -5385,22 +5476,92 @@ "members":{ "Catalog":{ "shape":"CatalogIdentifier", - "documentation":"

    Specifies the catalog related to the request.

    " + "documentation":"

    Specifies the catalog related to the request. Valid values are:

    • AWS: Submits the opportunity request from the production AWS environment.

    • Sandbox: Submits the opportunity request from a sandbox environment used for testing or development purposes.

    " }, "Identifier":{ "shape":"OpportunityIdentifier", - "documentation":"

    The identifier of the opportunity previously created by partner and needs to be submitted.

    " + "documentation":"

    The identifier of the Opportunity previously created by partner and needs to be submitted.

    " }, "InvolvementType":{ "shape":"SalesInvolvementType", - "documentation":"

    Specifies the level of AWS sellers' involvement on the opportunity.

    " + "documentation":"

    Specifies the level of AWS sellers' involvement on the opportunity. Valid values:

    • Co-sell: Indicates the user wants to co-sell with AWS. Share the opportunity with AWS to receive deal assistance and support.

    • For Visibility Only: Indicates that the user does not need support from AWS Sales Rep. Share this opportunity with AWS for visibility only, you will not receive deal assistance and support.

    " }, "Visibility":{ "shape":"Visibility", - "documentation":"

    Determines whether to restrict visibility of the opportunity from AWS sales. Default value is Full.

    " + "documentation":"

    Determines whether to restrict visibility of the opportunity from AWS sales. Default value is Full. Valid values:

    • Full: The opportunity is fully visible to AWS sales.

    • Limited: The opportunity has restricted visibility to AWS sales.

    " + } + } + }, + "Tag":{ + "type":"structure", + "required":[ + "Key", + "Value" + ], + "members":{ + "Key":{ + "shape":"TagKey", + "documentation":"

    The key in the tag.

    " + }, + "Value":{ + "shape":"TagValue", + "documentation":"

    The value in the tag.

    " + } + }, + "documentation":"

    The key-value pair assigned to a specified resource.

    " + }, + "TagKey":{ + "type":"string", + "max":128, + "min":1, + "pattern":"^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]*)$" + }, + "TagKeyList":{ + "type":"list", + "member":{"shape":"TagKey"}, + "max":50, + "min":1 + }, + "TagList":{ + "type":"list", + "member":{"shape":"Tag"}, + "max":200, + "min":1 + }, + "TagResourceRequest":{ + "type":"structure", + "required":[ + "ResourceArn", + "Tags" + ], + "members":{ + "ResourceArn":{ + "shape":"TaggableResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the resource that you want to tag.

    " + }, + "Tags":{ + "shape":"TagList", + "documentation":"

    A map of the key-value pairs of the tag or tags to assign to the resource.

    " } } }, + "TagResourceResponse":{ + "type":"structure", + "members":{ + } + }, + "TagValue":{ + "type":"string", + "max":256, + "min":0, + "pattern":"^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]*)$" + }, + "TaggableResourceArn":{ + "type":"string", + "max":1000, + "min":1, + "pattern":"^arn:[\\w+=/,.@-]+:partnercentral:[\\w+=/,.@-]*:[0-9]{12}:catalog/([a-zA-Z]+)/[\\w+=,.@-]+(/[\\w+=,.@-]+)*$" + }, "TaskArn":{ "type":"string", "pattern":"^arn:.*" @@ -5441,6 +5602,28 @@ "documentation":"

    This error occurs when there are too many requests sent. Review the provided quotas and adapt your usage to avoid throttling.

    This error occurs when there are too many requests sent. Review the provided Quotas and retry after the provided delay.

    ", "exception":true }, + "UntagResourceRequest":{ + "type":"structure", + "required":[ + "ResourceArn", + "TagKeys" + ], + "members":{ + "ResourceArn":{ + "shape":"TaggableResourceArn", + "documentation":"

    The Amazon Resource Name (ARN) of the resource that you want to untag.

    " + }, + "TagKeys":{ + "shape":"TagKeyList", + "documentation":"

    The keys of the key-value pairs for the tag or tags you want to remove from the specified resource.

    " + } + } + }, + "UntagResourceResponse":{ + "type":"structure", + "members":{ + } + }, "UpdateOpportunityRequest":{ "type":"structure", "required":[ @@ -5487,7 +5670,7 @@ }, "PrimaryNeedsFromAws":{ "shape":"PrimaryNeedsFromAws", - "documentation":"

    Identifies the type of support the partner needs from Amazon Web Services.

    Valid values:

    • Cosell—Architectural Validation: Confirmation from Amazon Web Services that the partner's proposed solution architecture is aligned with Amazon Web Services best practices and poses minimal architectural risks.

    • Cosell—Business Presentation: Request Amazon Web Services seller's participation in a joint customer presentation.

    • Cosell—Competitive Information: Access to Amazon Web Services competitive resources and support for the partner's proposed solution.

    • Cosell—Pricing Assistance: Connect with an AWS seller for support situations where a partner may be receiving an upfront discount on a service (for example: EDP deals).

    • Cosell—Technical Consultation: Connection with an Amazon Web Services Solutions Architect to address the partner's questions about the proposed solution.

    • Cosell—Total Cost of Ownership Evaluation: Assistance with quoting different cost savings of proposed solutions on Amazon Web Services versus on-premises or a traditional hosting environment.

    • Cosell—Deal Support: Request Amazon Web Services seller's support to progress the opportunity (for example: joint customer call, strategic positioning).

    • Cosell—Support for Public Tender/RFx: Opportunity related to the public sector where the partner needs RFx support from Amazon Web Services.

    • Do Not Need Support from AWS Sales Rep: Indicates that a partner doesn't need support from an Amazon Web Services Sales representative. The opportunity is managed solely by the partner. It's possible to request coselling support on these opportunities at any stage during their lifecycle. Also known as, for-visibility-only (FVO) opportunity.

    " + "documentation":"

    Identifies the type of support the partner needs from Amazon Web Services.

    Valid values:

    • Cosell—Architectural Validation: Confirmation from Amazon Web Services that the partner's proposed solution architecture is aligned with Amazon Web Services best practices and poses minimal architectural risks.

    • Cosell—Business Presentation: Request Amazon Web Services seller's participation in a joint customer presentation.

    • Cosell—Competitive Information: Access to Amazon Web Services competitive resources and support for the partner's proposed solution.

    • Cosell—Pricing Assistance: Connect with an AWS seller for support situations where a partner may be receiving an upfront discount on a service (for example: EDP deals).

    • Cosell—Technical Consultation: Connection with an Amazon Web Services Solutions Architect to address the partner's questions about the proposed solution.

    • Cosell—Total Cost of Ownership Evaluation: Assistance with quoting different cost savings of proposed solutions on Amazon Web Services versus on-premises or a traditional hosting environment.

    • Cosell—Deal Support: Request Amazon Web Services seller's support to progress the opportunity (for example: joint customer call, strategic positioning).

    • Cosell—Support for Public Tender/RFx: Opportunity related to the public sector where the partner needs RFx support from Amazon Web Services.

    " }, "Project":{ "shape":"Project", diff --git a/services/paymentcryptography/pom.xml b/services/paymentcryptography/pom.xml index 8f76187765a8..2568529283d5 100644 --- a/services/paymentcryptography/pom.xml +++ b/services/paymentcryptography/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 paymentcryptography AWS Java SDK :: Services :: Payment Cryptography diff --git a/services/paymentcryptographydata/pom.xml b/services/paymentcryptographydata/pom.xml index 3d51b57a2e86..b69e3ca804e4 100644 --- a/services/paymentcryptographydata/pom.xml +++ b/services/paymentcryptographydata/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 paymentcryptographydata AWS Java SDK :: Services :: Payment Cryptography Data diff --git a/services/pcaconnectorad/pom.xml b/services/pcaconnectorad/pom.xml index 1bb11708aea7..4558b83bc6ba 100644 --- a/services/pcaconnectorad/pom.xml +++ b/services/pcaconnectorad/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 pcaconnectorad AWS Java SDK :: Services :: Pca Connector Ad diff --git a/services/pcaconnectorscep/pom.xml b/services/pcaconnectorscep/pom.xml index b96c0d9db5a3..b5026487ca37 100644 --- a/services/pcaconnectorscep/pom.xml +++ b/services/pcaconnectorscep/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 pcaconnectorscep AWS Java SDK :: Services :: Pca Connector Scep diff --git a/services/pcs/pom.xml b/services/pcs/pom.xml index 9b14a3b84eca..5b6460a983df 100644 --- a/services/pcs/pom.xml +++ b/services/pcs/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 pcs AWS Java SDK :: Services :: PCS diff --git a/services/personalize/pom.xml b/services/personalize/pom.xml index 395ae04f333c..edc850c34c88 100644 --- a/services/personalize/pom.xml +++ b/services/personalize/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 personalize AWS Java SDK :: Services :: Personalize diff --git a/services/personalizeevents/pom.xml b/services/personalizeevents/pom.xml index 33dd82e6ac9d..508e8ceff3b4 100644 --- a/services/personalizeevents/pom.xml +++ b/services/personalizeevents/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 personalizeevents AWS Java SDK :: Services :: Personalize Events diff --git a/services/personalizeruntime/pom.xml b/services/personalizeruntime/pom.xml index 1b054329ce68..1631e61e58cf 100644 --- a/services/personalizeruntime/pom.xml +++ b/services/personalizeruntime/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 personalizeruntime AWS Java SDK :: Services :: Personalize Runtime diff --git a/services/pi/pom.xml b/services/pi/pom.xml index 634295e0eb47..b7c5c26a39ab 100644 --- a/services/pi/pom.xml +++ b/services/pi/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 pi AWS Java SDK :: Services :: PI diff --git a/services/pinpoint/pom.xml b/services/pinpoint/pom.xml index fdbbf4bae7f4..9c7ca5dd71c8 100644 --- a/services/pinpoint/pom.xml +++ b/services/pinpoint/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 pinpoint AWS Java SDK :: Services :: Amazon Pinpoint diff --git a/services/pinpointemail/pom.xml b/services/pinpointemail/pom.xml index 785a3b6a5260..9f5fa8e905bf 100644 --- a/services/pinpointemail/pom.xml +++ b/services/pinpointemail/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 pinpointemail AWS Java SDK :: Services :: Pinpoint Email diff --git a/services/pinpointsmsvoice/pom.xml b/services/pinpointsmsvoice/pom.xml index 05298ab708f4..61eddafca544 100644 --- a/services/pinpointsmsvoice/pom.xml +++ b/services/pinpointsmsvoice/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 pinpointsmsvoice AWS Java SDK :: Services :: Pinpoint SMS Voice diff --git a/services/pinpointsmsvoicev2/pom.xml b/services/pinpointsmsvoicev2/pom.xml index 70f5851c7131..15209e1d42d6 100644 --- a/services/pinpointsmsvoicev2/pom.xml +++ b/services/pinpointsmsvoicev2/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 pinpointsmsvoicev2 AWS Java SDK :: Services :: Pinpoint SMS Voice V2 diff --git a/services/pipes/pom.xml b/services/pipes/pom.xml index 193d5c8a5a4c..73f37b7bdca6 100644 --- a/services/pipes/pom.xml +++ b/services/pipes/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 pipes AWS Java SDK :: Services :: Pipes diff --git a/services/polly/pom.xml b/services/polly/pom.xml index 100ce9081b5a..9d6746619a88 100644 --- a/services/polly/pom.xml +++ b/services/polly/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 polly AWS Java SDK :: Services :: Amazon Polly diff --git a/services/pom.xml b/services/pom.xml index 58c8bf7a2cf7..9327dc4f2c0a 100644 --- a/services/pom.xml +++ b/services/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk aws-sdk-java-pom - 2.29.52 + 2.30.0 services AWS Java SDK :: Services diff --git a/services/pricing/pom.xml b/services/pricing/pom.xml index 4ba5f91015a5..0dc721038317 100644 --- a/services/pricing/pom.xml +++ b/services/pricing/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 pricing diff --git a/services/privatenetworks/pom.xml b/services/privatenetworks/pom.xml index e3134fa0f7c2..92e76b793ada 100644 --- a/services/privatenetworks/pom.xml +++ b/services/privatenetworks/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 privatenetworks AWS Java SDK :: Services :: Private Networks diff --git a/services/proton/pom.xml b/services/proton/pom.xml index 3ed07b68b6a5..997ec1f42d89 100644 --- a/services/proton/pom.xml +++ b/services/proton/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 proton AWS Java SDK :: Services :: Proton diff --git a/services/qapps/pom.xml b/services/qapps/pom.xml index 21eccd13c58a..9b150bbba342 100644 --- a/services/qapps/pom.xml +++ b/services/qapps/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 qapps AWS Java SDK :: Services :: Q Apps diff --git a/services/qbusiness/pom.xml b/services/qbusiness/pom.xml index c9325607ee64..5f9356644695 100644 --- a/services/qbusiness/pom.xml +++ b/services/qbusiness/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 qbusiness AWS Java SDK :: Services :: Q Business diff --git a/services/qconnect/pom.xml b/services/qconnect/pom.xml index cce4eeaeb94a..eb2c447799d6 100644 --- a/services/qconnect/pom.xml +++ b/services/qconnect/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 qconnect AWS Java SDK :: Services :: Q Connect diff --git a/services/qldb/pom.xml b/services/qldb/pom.xml index f5bf180af235..dfeb5d1d92f2 100644 --- a/services/qldb/pom.xml +++ b/services/qldb/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 qldb AWS Java SDK :: Services :: QLDB diff --git a/services/qldbsession/pom.xml b/services/qldbsession/pom.xml index 70266171d792..23cebb9562e8 100644 --- a/services/qldbsession/pom.xml +++ b/services/qldbsession/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 qldbsession AWS Java SDK :: Services :: QLDB Session diff --git a/services/quicksight/pom.xml b/services/quicksight/pom.xml index 0b7a6bc0b2ac..e3a80a5277b5 100644 --- a/services/quicksight/pom.xml +++ b/services/quicksight/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 quicksight AWS Java SDK :: Services :: QuickSight diff --git a/services/ram/pom.xml b/services/ram/pom.xml index f3143f494c52..a4f4ed6f98fb 100644 --- a/services/ram/pom.xml +++ b/services/ram/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 ram AWS Java SDK :: Services :: RAM diff --git a/services/rbin/pom.xml b/services/rbin/pom.xml index c79d7555dad7..848583e6aba2 100644 --- a/services/rbin/pom.xml +++ b/services/rbin/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 rbin AWS Java SDK :: Services :: Rbin diff --git a/services/rds/pom.xml b/services/rds/pom.xml index b78355168a8d..bb2d2e7568fb 100644 --- a/services/rds/pom.xml +++ b/services/rds/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 rds AWS Java SDK :: Services :: Amazon RDS diff --git a/services/rdsdata/pom.xml b/services/rdsdata/pom.xml index f47388a0524f..40d52c4c3365 100644 --- a/services/rdsdata/pom.xml +++ b/services/rdsdata/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 rdsdata AWS Java SDK :: Services :: RDS Data diff --git a/services/redshift/pom.xml b/services/redshift/pom.xml index e3c38b4f3ed6..83c715ef17d8 100644 --- a/services/redshift/pom.xml +++ b/services/redshift/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 redshift AWS Java SDK :: Services :: Amazon Redshift diff --git a/services/redshiftdata/pom.xml b/services/redshiftdata/pom.xml index 07192008c8c7..b3daf89e6618 100644 --- a/services/redshiftdata/pom.xml +++ b/services/redshiftdata/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 redshiftdata AWS Java SDK :: Services :: Redshift Data diff --git a/services/redshiftserverless/pom.xml b/services/redshiftserverless/pom.xml index b13c031381c5..4b347d96ba08 100644 --- a/services/redshiftserverless/pom.xml +++ b/services/redshiftserverless/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 redshiftserverless AWS Java SDK :: Services :: Redshift Serverless diff --git a/services/rekognition/pom.xml b/services/rekognition/pom.xml index c2dfc65d543d..03080a58b167 100644 --- a/services/rekognition/pom.xml +++ b/services/rekognition/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 rekognition AWS Java SDK :: Services :: Amazon Rekognition diff --git a/services/repostspace/pom.xml b/services/repostspace/pom.xml index 1b60570ade00..e8de35e77c14 100644 --- a/services/repostspace/pom.xml +++ b/services/repostspace/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 repostspace AWS Java SDK :: Services :: Repostspace diff --git a/services/resiliencehub/pom.xml b/services/resiliencehub/pom.xml index 3ebab55d7829..2a0db73c4fc2 100644 --- a/services/resiliencehub/pom.xml +++ b/services/resiliencehub/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 resiliencehub AWS Java SDK :: Services :: Resiliencehub diff --git a/services/resourceexplorer2/pom.xml b/services/resourceexplorer2/pom.xml index 0bc533ba329b..54b7f70782bd 100644 --- a/services/resourceexplorer2/pom.xml +++ b/services/resourceexplorer2/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 resourceexplorer2 AWS Java SDK :: Services :: Resource Explorer 2 diff --git a/services/resourcegroups/pom.xml b/services/resourcegroups/pom.xml index 9d67e7995d2e..b97ff3a85d70 100644 --- a/services/resourcegroups/pom.xml +++ b/services/resourcegroups/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 resourcegroups diff --git a/services/resourcegroupstaggingapi/pom.xml b/services/resourcegroupstaggingapi/pom.xml index a64ffe9e4570..4c52ad0ea65c 100644 --- a/services/resourcegroupstaggingapi/pom.xml +++ b/services/resourcegroupstaggingapi/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 resourcegroupstaggingapi AWS Java SDK :: Services :: AWS Resource Groups Tagging API diff --git a/services/robomaker/pom.xml b/services/robomaker/pom.xml index 0877fd5387ca..d87bb186a1d0 100644 --- a/services/robomaker/pom.xml +++ b/services/robomaker/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 robomaker AWS Java SDK :: Services :: RoboMaker diff --git a/services/rolesanywhere/pom.xml b/services/rolesanywhere/pom.xml index 1704557c791a..875bf1ece737 100644 --- a/services/rolesanywhere/pom.xml +++ b/services/rolesanywhere/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 rolesanywhere AWS Java SDK :: Services :: Roles Anywhere diff --git a/services/route53/pom.xml b/services/route53/pom.xml index f5aa61f9f191..f7f8a04f1217 100644 --- a/services/route53/pom.xml +++ b/services/route53/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 route53 AWS Java SDK :: Services :: Amazon Route53 diff --git a/services/route53domains/pom.xml b/services/route53domains/pom.xml index 0beb06fcc8ee..751b72bdf6f4 100644 --- a/services/route53domains/pom.xml +++ b/services/route53domains/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 route53domains AWS Java SDK :: Services :: Amazon Route53 Domains diff --git a/services/route53profiles/pom.xml b/services/route53profiles/pom.xml index 86db9674b577..7f1fa48609cf 100644 --- a/services/route53profiles/pom.xml +++ b/services/route53profiles/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 route53profiles AWS Java SDK :: Services :: Route53 Profiles diff --git a/services/route53recoverycluster/pom.xml b/services/route53recoverycluster/pom.xml index 438a3b2d7046..e6adf78bfc5f 100644 --- a/services/route53recoverycluster/pom.xml +++ b/services/route53recoverycluster/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 route53recoverycluster AWS Java SDK :: Services :: Route53 Recovery Cluster diff --git a/services/route53recoverycontrolconfig/pom.xml b/services/route53recoverycontrolconfig/pom.xml index 26e0f7a839f9..4c31bfa10494 100644 --- a/services/route53recoverycontrolconfig/pom.xml +++ b/services/route53recoverycontrolconfig/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 route53recoverycontrolconfig AWS Java SDK :: Services :: Route53 Recovery Control Config diff --git a/services/route53recoveryreadiness/pom.xml b/services/route53recoveryreadiness/pom.xml index 3d642b07f821..c404e37191b3 100644 --- a/services/route53recoveryreadiness/pom.xml +++ b/services/route53recoveryreadiness/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 route53recoveryreadiness AWS Java SDK :: Services :: Route53 Recovery Readiness diff --git a/services/route53resolver/pom.xml b/services/route53resolver/pom.xml index 2ed2d04b5cb8..eb5cabf05f34 100644 --- a/services/route53resolver/pom.xml +++ b/services/route53resolver/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 route53resolver AWS Java SDK :: Services :: Route53Resolver diff --git a/services/rum/pom.xml b/services/rum/pom.xml index c819257b5a02..63e694450b9f 100644 --- a/services/rum/pom.xml +++ b/services/rum/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 rum AWS Java SDK :: Services :: RUM diff --git a/services/s3/pom.xml b/services/s3/pom.xml index 61f18a702bae..ed56f311f110 100644 --- a/services/s3/pom.xml +++ b/services/s3/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 s3 AWS Java SDK :: Services :: Amazon S3 diff --git a/services/s3/src/it/java/software/amazon/awssdk/services/s3/PutObjectIntegrationTest.java b/services/s3/src/it/java/software/amazon/awssdk/services/s3/PutObjectIntegrationTest.java index 720589078ecb..22c8fb0f8f3a 100644 --- a/services/s3/src/it/java/software/amazon/awssdk/services/s3/PutObjectIntegrationTest.java +++ b/services/s3/src/it/java/software/amazon/awssdk/services/s3/PutObjectIntegrationTest.java @@ -27,10 +27,7 @@ import java.io.InputStream; import java.net.URI; import java.nio.charset.StandardCharsets; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; import java.util.ArrayList; -import java.util.Base64; import java.util.List; import java.util.concurrent.CompletableFuture; import org.junit.AfterClass; @@ -67,28 +64,6 @@ public static void tearDown() { deleteBucketAndAllContents(BUCKET); } - @Test - public void putObject_withUserCalculatedChecksum_doesNotPerformMd5Validation() throws NoSuchAlgorithmException { - CapturingInterceptor capturingInterceptor = new CapturingInterceptor(); - S3Client s3Client = s3ClientBuilder() - .overrideConfiguration(o -> o.addExecutionInterceptor(capturingInterceptor)) - .build(); - - MessageDigest md = MessageDigest.getInstance("SHA-1"); - md.update(CONTENT); - byte[] checksum = md.digest(); - String checksumVal = Base64.getEncoder().encodeToString(checksum); - - PutObjectRequest request = PutObjectRequest.builder() - .bucket(BUCKET) - .key(SYNC_KEY) - .checksumSHA1(checksumVal) - .build(); - - s3Client.putObject(request, RequestBody.fromString("Hello")); - assertThat(capturingInterceptor.isMd5Enabled).isFalse(); - } - @Test public void objectInputStreamsAreClosed() { TestContentProvider provider = new TestContentProvider(CONTENT); diff --git a/services/s3/src/it/java/software/amazon/awssdk/services/s3/checksum/AsyncHttpChecksumIntegrationTest.java b/services/s3/src/it/java/software/amazon/awssdk/services/s3/checksum/AsyncHttpChecksumIntegrationTest.java index ab0d8fac1dad..9dfbd0373a6e 100644 --- a/services/s3/src/it/java/software/amazon/awssdk/services/s3/checksum/AsyncHttpChecksumIntegrationTest.java +++ b/services/s3/src/it/java/software/amazon/awssdk/services/s3/checksum/AsyncHttpChecksumIntegrationTest.java @@ -16,6 +16,7 @@ package software.amazon.awssdk.services.s3.checksum; import static org.assertj.core.api.Assertions.assertThat; +import static software.amazon.awssdk.services.s3.checksum.HttpChecksumIntegrationTest.CHECKSUM_CRC32C_HEADER; import static software.amazon.awssdk.services.s3.utils.ChecksumUtils.KB; import static software.amazon.awssdk.services.s3.utils.ChecksumUtils.createDataOfSize; import static software.amazon.awssdk.testutils.service.S3BucketUtils.temporaryBucketName; @@ -37,19 +38,32 @@ import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.ValueSource; import software.amazon.awssdk.authcrt.signer.internal.DefaultAwsCrtS3V4aSigner; +import software.amazon.awssdk.checksums.DefaultChecksumAlgorithm; +import software.amazon.awssdk.core.ResponseBytes; import software.amazon.awssdk.core.SdkPlugin; import software.amazon.awssdk.core.async.AsyncRequestBody; import software.amazon.awssdk.core.async.AsyncResponseTransformer; import software.amazon.awssdk.core.checksums.Algorithm; import software.amazon.awssdk.core.checksums.ChecksumValidation; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidation; import software.amazon.awssdk.core.internal.async.FileAsyncRequestBody; +import software.amazon.awssdk.core.sync.RequestBody; +import software.amazon.awssdk.core.sync.ResponseTransformer; import software.amazon.awssdk.services.s3.S3AsyncClient; +import software.amazon.awssdk.services.s3.S3AsyncClientBuilder; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.S3ClientBuilder; import software.amazon.awssdk.services.s3.S3Configuration; import software.amazon.awssdk.services.s3.S3IntegrationTestBase; import software.amazon.awssdk.services.s3.internal.plugins.S3OverrideAuthSchemePropertiesPlugin; import software.amazon.awssdk.services.s3.model.ChecksumAlgorithm; import software.amazon.awssdk.services.s3.model.ChecksumMode; +import software.amazon.awssdk.services.s3.model.ExpirationStatus; import software.amazon.awssdk.services.s3.model.GetObjectRequest; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.awssdk.services.s3.model.LifecycleRule; +import software.amazon.awssdk.services.s3.model.PutBucketLifecycleConfigurationRequest; import software.amazon.awssdk.services.s3.model.PutObjectRequest; import software.amazon.awssdk.services.s3.model.PutObjectResponse; import software.amazon.awssdk.services.s3.utils.CaptureChecksumValidationInterceptor; @@ -100,7 +114,7 @@ void asyncValidUnsignedTrailerChecksumCalculatedBySdkClient() { String response = s3Async.getObject(GetObjectRequest.builder().bucket(BUCKET) .key(KEY).checksumMode(ChecksumMode.ENABLED) .build(), AsyncResponseTransformer.toBytes()).join().asUtf8String(); - assertThat(interceptor.validationAlgorithm()).isEqualTo(Algorithm.CRC32); + assertThat(interceptor.validationAlgorithm()).isEqualTo(DefaultChecksumAlgorithm.CRC32); assertThat(interceptor.responseValidation()).isEqualTo(ChecksumValidation.VALIDATED); assertThat(response).isEqualTo("Hello world"); } @@ -119,7 +133,7 @@ void asyncHttpsValidUnsignedTrailerChecksumCalculatedBySdkClient_withSmallReques String response = s3Async.getObject(GetObjectRequest.builder().bucket(BUCKET) .key(KEY).checksumMode(ChecksumMode.ENABLED) .build(), AsyncResponseTransformer.toBytes()).join().asUtf8String(); - assertThat(interceptor.validationAlgorithm()).isEqualTo(Algorithm.CRC32); + assertThat(interceptor.validationAlgorithm()).isEqualTo(DefaultChecksumAlgorithm.CRC32); assertThat(interceptor.responseValidation()).isEqualTo(ChecksumValidation.VALIDATED); assertThat(response).isEqualTo("Hello world"); } @@ -141,7 +155,7 @@ void asyncHttpsValidUnsignedTrailerChecksumCalculatedBySdkClient_withHugeRequest String response = s3Async.getObject(GetObjectRequest.builder().bucket(BUCKET) .key(KEY).checksumMode(ChecksumMode.ENABLED) .build(), AsyncResponseTransformer.toBytes()).join().asUtf8String(); - assertThat(interceptor.validationAlgorithm()).isEqualTo(Algorithm.CRC32); + assertThat(interceptor.validationAlgorithm()).isEqualTo(DefaultChecksumAlgorithm.CRC32); assertThat(interceptor.responseValidation()).isEqualTo(ChecksumValidation.VALIDATED); assertThat(response).isEqualTo(createDataOfSize(64 * KB, 'a')); } @@ -164,7 +178,7 @@ void asyncHttpsValidUnsignedTrailerChecksumCalculatedBySdkClient_withHugeRequest String response = s3Async.getObject(GetObjectRequest.builder().bucket(BUCKET) .key(KEY).checksumMode(ChecksumMode.ENABLED) .build(), AsyncResponseTransformer.toBytes()).join().asUtf8String(); - assertThat(interceptor.validationAlgorithm()).isEqualTo(Algorithm.CRC32); + assertThat(interceptor.validationAlgorithm()).isEqualTo(DefaultChecksumAlgorithm.CRC32); assertThat(interceptor.responseValidation()).isEqualTo(ChecksumValidation.VALIDATED); byte[] bytes = Files.readAllBytes(randomFileOfFixedLength.toPath()); @@ -211,7 +225,7 @@ void asyncHttpsValidUnsignedTrailer_TwoRequests_withDifferentChunkSize_OfFileAsy .key(keyTwo).checksumMode(ChecksumMode.ENABLED) .build(), AsyncResponseTransformer.toBytes()).join().asUtf8String(); - assertThat(interceptor.validationAlgorithm()).isEqualTo(Algorithm.CRC32); + assertThat(interceptor.validationAlgorithm()).isEqualTo(DefaultChecksumAlgorithm.CRC32); assertThat(interceptor.responseValidation()).isEqualTo(ChecksumValidation.VALIDATED); assertThat(response).isEqualTo(new String(Files.readAllBytes(randomFileOfFixedLengthOne.toPath()))); @@ -294,57 +308,117 @@ public void putObject_with_bufferCreatedFromZeroCapacityByteBuffer() { assertThat(response).isEqualTo(""); } - private static Stream getObjectChecksumValidationParams() { - return Stream.of(Arguments.of(true, ChecksumAlgorithm.CRC32, ChecksumMode.ENABLED), - Arguments.of(true, null, ChecksumMode.ENABLED), - Arguments.of(true, ChecksumAlgorithm.CRC32, null), - Arguments.of(true, null, null), - Arguments.of(false, ChecksumAlgorithm.CRC32, ChecksumMode.ENABLED), - Arguments.of(false, null, ChecksumMode.ENABLED), - Arguments.of(false, ChecksumAlgorithm.CRC32, null), - Arguments.of(false, null, null)); + @ParameterizedTest(name = "{index} {4}") + @MethodSource("software.amazon.awssdk.services.s3.checksum.HttpChecksumTestUtils#putObjectChecksumCalculationParams") + public void putObject_checksumCalculation(RequestChecksumCalculation requestChecksumCalculation, + ChecksumAlgorithm checksumAlgorithm, + String checksumCrc32CValue, + String expectedTrailer, + String description) { + try (S3AsyncClient s3 = createS3AsyncClient(requestChecksumCalculation)) { + s3.putObject(PutObjectRequest.builder() + .bucket(BUCKET) + .checksumCRC32C(checksumCrc32CValue) + .key(KEY) + .checksumAlgorithm(checksumAlgorithm) + .build(), AsyncRequestBody.fromString("Hello world")).join(); + + assertThat(interceptor.requestChecksumInTrailer()).isEqualTo(expectedTrailer); + if (checksumCrc32CValue != null) { + assertThat(interceptor.requestHeaders().keySet()).filteredOn(h -> h.contains("x-amz-checksum-")) + .containsExactly(CHECKSUM_CRC32C_HEADER); + assertThat(interceptor.requestHeaders().get(CHECKSUM_CRC32C_HEADER)).containsExactly(checksumCrc32CValue); + } + interceptor.reset(); + } } - @ParameterizedTest - @MethodSource("getObjectChecksumValidationParams") - public void testGetObjectChecksumValidation(boolean checksumValidationEnabled, ChecksumAlgorithm checksumAlgorithm, - ChecksumMode checksumMode) { - S3AsyncClient s3Async = s3AsyncClientBuilder().overrideConfiguration(o -> o.addExecutionInterceptor(interceptor)) - .serviceConfiguration(S3Configuration.builder() - .checksumValidationEnabled(checksumValidationEnabled) - .build()) - .build(); + @ParameterizedTest(name = "{index} {4}") + @MethodSource("software.amazon.awssdk.services.s3.checksum.HttpChecksumTestUtils#putObjectLifecycleChecksumCalculationParams") + public void putBucketLifecycleChecksumInHeaderRequired_checksumCalculation(RequestChecksumCalculation requestChecksumCalculation, + ChecksumAlgorithm checksumAlgorithm, + String checksumCrc32CValue, + String expectedHeader, + String description) { + try (S3AsyncClient s3 = createS3AsyncClient(requestChecksumCalculation)) { + LifecycleRule lifecycleRule = LifecycleRule.builder() + .status(ExpirationStatus.ENABLED) + .expiration(e -> e.days(1)) + .filter(f -> f.prefix("test")) + .build(); + PutBucketLifecycleConfigurationRequest.Builder builder = + PutBucketLifecycleConfigurationRequest.builder() + .bucket(BUCKET) + .checksumAlgorithm(checksumAlgorithm) + .lifecycleConfiguration(l -> l.rules(lifecycleRule)); + if (checksumCrc32CValue != null) { + builder.overrideConfiguration(o -> o.putHeader(CHECKSUM_CRC32C_HEADER, + checksumCrc32CValue)); + } + s3.putBucketLifecycleConfiguration(builder.build()).join(); + assertThat(interceptor.requestHeaders().keySet()).filteredOn(h -> h.contains("x-amz-checksum-")) + .containsExactly(expectedHeader); + assertThat(interceptor.requestChecksumInTrailer()).isNull(); + if (checksumCrc32CValue != null) { + assertThat(interceptor.requestHeaders().get(CHECKSUM_CRC32C_HEADER)); + } + } + } - s3Async.putObject(PutObjectRequest.builder() - .bucket(BUCKET) - .key(KEY) - .checksumAlgorithm(checksumAlgorithm) - .build(), AsyncRequestBody.fromString("Hello world")).join(); - - s3Async.getObject(GetObjectRequest.builder() - .bucket(BUCKET) - .key(KEY) - .checksumMode(checksumMode) - .build(), AsyncResponseTransformer.toBytes()).join(); - - validateChecksumValidation(checksumValidationEnabled, checksumAlgorithm, checksumMode); - interceptor.reset(); + private S3AsyncClient createS3AsyncClient(ResponseChecksumValidation responseChecksumValidation) { + S3AsyncClientBuilder builder = s3AsyncClientBuilder().overrideConfiguration(o -> o.addExecutionInterceptor(interceptor)); + builder.requestChecksumCalculation(RequestChecksumCalculation.WHEN_REQUIRED) + .responseChecksumValidation(responseChecksumValidation); + return builder.build(); } - private void validateChecksumValidation(boolean checksumValidationEnabled, ChecksumAlgorithm checksumAlgorithm, - ChecksumMode checksumMode) { - if (checksumValidationEnabled) { - if (checksumMode == ChecksumMode.ENABLED) { - assertChecksumModeEnabledWithChecksumValidationEnabled(checksumAlgorithm); - } else { - assertChecksumModeNotEnabledWithChecksumValidationEnabled(); - } - } else { - if (checksumMode == ChecksumMode.ENABLED) { - assertChecksumModeEnabledWithChecksumValidationDisabled(checksumAlgorithm); + private S3AsyncClient createS3AsyncClient(RequestChecksumCalculation responseChecksumValidation) { + S3AsyncClientBuilder builder = s3AsyncClientBuilder().overrideConfiguration(o -> o.addExecutionInterceptor(interceptor)); + builder.requestChecksumCalculation(responseChecksumValidation); + return builder.build(); + } + + @ParameterizedTest(name = "{index} {5}") + @MethodSource("software.amazon.awssdk.services.s3.checksum.HttpChecksumTestUtils#getObjectChecksumValidationParams") + public void getObject_noFlexibleChecksumInResponse_checksumValidation( + ResponseChecksumValidation responseChecksumValidation, + ChecksumMode checksumMode, + ChecksumAlgorithm checksumAlgorithm, + boolean shouldValidateMd5Checksum, + String expectedTrailerHeader, + String description) { + try (S3AsyncClient s3Async = s3AsyncClientBuilder().overrideConfiguration(o -> o.addExecutionInterceptor(interceptor)) + .requestChecksumCalculation(RequestChecksumCalculation.WHEN_REQUIRED) + .responseChecksumValidation(responseChecksumValidation) + .build()) { + s3Async.putObject(PutObjectRequest.builder() + .bucket(BUCKET) + .key(KEY) + .checksumAlgorithm(checksumAlgorithm) + .build(), AsyncRequestBody.fromString("Hello world")).join(); + + ResponseBytes responseBytes = s3Async.getObject(GetObjectRequest.builder() + .bucket(BUCKET) + .key(KEY) + .checksumMode(checksumMode) + .build(), + AsyncResponseTransformer.toBytes()).join(); + + if (shouldValidateMd5Checksum) { + assertRequestAndResponseContainMd5Header(); + assertThat(responseBytes.response() + .sdkHttpResponse() + .anyMatchingHeader(k -> k.startsWith("x-amz-checksum"))).isFalse(); } else { - assertChecksumModeNotEnabledWithChecksumValidationDisabled(); + assertRequestAndResponseDoNotContainMd5Header(); + if (expectedTrailerHeader != null) { + assertThat(responseBytes.response() + .sdkHttpResponse() + .firstMatchingHeader(expectedTrailerHeader)).isNotNull(); + } } + + } } diff --git a/services/s3/src/it/java/software/amazon/awssdk/services/s3/checksum/HttpChecksumIntegrationTest.java b/services/s3/src/it/java/software/amazon/awssdk/services/s3/checksum/HttpChecksumIntegrationTest.java index b02ffd06db49..4b0d88b94dd9 100644 --- a/services/s3/src/it/java/software/amazon/awssdk/services/s3/checksum/HttpChecksumIntegrationTest.java +++ b/services/s3/src/it/java/software/amazon/awssdk/services/s3/checksum/HttpChecksumIntegrationTest.java @@ -38,22 +38,32 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import software.amazon.awssdk.authcrt.signer.internal.DefaultAwsCrtS3V4aSigner; +import software.amazon.awssdk.checksums.DefaultChecksumAlgorithm; import software.amazon.awssdk.core.HttpChecksumConstant; +import software.amazon.awssdk.core.ResponseBytes; import software.amazon.awssdk.core.ResponseInputStream; import software.amazon.awssdk.core.checksums.Algorithm; import software.amazon.awssdk.core.checksums.ChecksumValidation; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidation; import software.amazon.awssdk.core.sync.RequestBody; +import software.amazon.awssdk.core.sync.ResponseTransformer; import software.amazon.awssdk.services.s3.S3AsyncClient; import software.amazon.awssdk.services.s3.S3Client; -import software.amazon.awssdk.services.s3.S3Configuration; +import software.amazon.awssdk.services.s3.S3ClientBuilder; import software.amazon.awssdk.services.s3.S3IntegrationTestBase; import software.amazon.awssdk.services.s3.model.ChecksumAlgorithm; import software.amazon.awssdk.services.s3.model.ChecksumMode; +import software.amazon.awssdk.services.s3.model.ExpirationStatus; import software.amazon.awssdk.services.s3.model.GetObjectRequest; import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.awssdk.services.s3.model.LifecycleRule; +import software.amazon.awssdk.services.s3.model.PutBucketLifecycleConfigurationRequest; +import software.amazon.awssdk.services.s3.model.PutBucketLifecycleConfigurationResponse; import software.amazon.awssdk.services.s3.model.PutObjectRequest; import software.amazon.awssdk.services.s3.model.PutObjectResponse; import software.amazon.awssdk.services.s3.model.S3Exception; +import software.amazon.awssdk.services.s3.model.Transition; import software.amazon.awssdk.services.s3.utils.CaptureChecksumValidationInterceptor; import software.amazon.awssdk.testutils.RandomTempFile; @@ -62,6 +72,7 @@ public class HttpChecksumIntegrationTest extends S3IntegrationTestBase { public static final int HUGE_MSG_SIZE = 1600 * KB; protected static final String KEY = "some-key"; private static final String BUCKET = temporaryBucketName(HttpChecksumIntegrationTest.class); + public static final String CHECKSUM_CRC32C_HEADER = "x-amz-checksum-crc32c"; public static CaptureChecksumValidationInterceptor interceptor = new CaptureChecksumValidationInterceptor(); protected static S3Client s3Https; protected static S3AsyncClient s3HttpAsync; @@ -169,7 +180,7 @@ public void syncValidUnsignedTrailerChecksumCalculatedBySdkClient() { new InputStreamReader(s3HttpsObject, StandardCharsets.UTF_8)) .lines() .collect(Collectors.joining("\n")); - assertThat(interceptor.validationAlgorithm()).isEqualTo(Algorithm.CRC32); + assertThat(interceptor.validationAlgorithm()).isEqualTo(DefaultChecksumAlgorithm.CRC32); assertThat(interceptor.responseValidation()).isEqualTo(ChecksumValidation.VALIDATED); assertThat(text).isEqualTo("Hello world"); } @@ -197,7 +208,7 @@ public void syncValidSignedTrailerChecksumCalculatedBySdkClient() { .lines() .collect(Collectors.joining("\n")); assertThat(interceptor.contentEncoding()).isEmpty(); - assertThat(interceptor.validationAlgorithm()).isEqualTo(Algorithm.CRC32); + assertThat(interceptor.validationAlgorithm()).isEqualTo(DefaultChecksumAlgorithm.CRC32); assertThat(interceptor.responseValidation()).isEqualTo(ChecksumValidation.VALIDATED); assertThat(text).isEqualTo("Hello world"); } @@ -221,7 +232,7 @@ public void syncValidSignedTrailerChecksumCalculatedBySdkClient_Empty_String() { new InputStreamReader(s3HttpsObject, StandardCharsets.UTF_8)) .lines() .collect(Collectors.joining("\n")); - assertThat(interceptor.validationAlgorithm()).isEqualTo(Algorithm.CRC32); + assertThat(interceptor.validationAlgorithm()).isEqualTo(DefaultChecksumAlgorithm.CRC32); assertThat(interceptor.responseValidation()).isEqualTo(ChecksumValidation.VALIDATED); assertThat(text).isEqualTo(""); @@ -245,7 +256,7 @@ public void syncValidSignedTrailerChecksumCalculatedBySdkClientWithSigv4a() { new InputStreamReader(s3HttpsObject, StandardCharsets.UTF_8)) .lines() .collect(Collectors.joining("\n")); - assertThat(interceptor.validationAlgorithm()).isEqualTo(Algorithm.CRC32); + assertThat(interceptor.validationAlgorithm()).isEqualTo(DefaultChecksumAlgorithm.CRC32); assertThat(interceptor.responseValidation()).isEqualTo(ChecksumValidation.VALIDATED); assertThat(text).isEqualTo("Hello world"); } @@ -270,7 +281,7 @@ public void syncValidSignedTrailerChecksumCalculatedBySdkClientWithSigv4a_withCo new InputStreamReader(s3HttpsObject, StandardCharsets.UTF_8)) .lines() .collect(Collectors.joining("\n")); - assertThat(interceptor.validationAlgorithm()).isEqualTo(Algorithm.CRC32); + assertThat(interceptor.validationAlgorithm()).isEqualTo(DefaultChecksumAlgorithm.CRC32); assertThat(interceptor.responseValidation()).isEqualTo(ChecksumValidation.VALIDATED); assertThat(text).isEqualTo("Hello world"); } @@ -299,7 +310,7 @@ public void syncUnsignedPayloadForHugeMessage() throws InterruptedException { new InputStreamReader(s3HttpsObject, StandardCharsets.UTF_8)) .lines() .collect(Collectors.joining("\n")); - assertThat(interceptor.validationAlgorithm()).isEqualTo(Algorithm.CRC32); + assertThat(interceptor.validationAlgorithm()).isEqualTo(DefaultChecksumAlgorithm.CRC32); assertThat(interceptor.responseValidation()).isEqualTo(ChecksumValidation.VALIDATED); assertThat(text).isEqualTo(createDataOfSize(HUGE_MSG_SIZE, 'a')); } @@ -325,7 +336,7 @@ public void syncSignedPayloadForHugeMessage() { new InputStreamReader(s3HttpsObject, StandardCharsets.UTF_8)) .lines() .collect(Collectors.joining("\n")); - assertThat(interceptor.validationAlgorithm()).isEqualTo(Algorithm.CRC32); + assertThat(interceptor.validationAlgorithm()).isEqualTo(DefaultChecksumAlgorithm.CRC32); assertThat(interceptor.responseValidation()).isEqualTo(ChecksumValidation.VALIDATED); assertThat(text).isEqualTo(createDataOfSize(HUGE_MSG_SIZE, 'a')); } @@ -375,7 +386,7 @@ public void syncValidUnsignedTrailerChecksumCalculatedBySdkClient_withSmallFileR new InputStreamReader(s3HttpsObject, StandardCharsets.UTF_8)) .lines() .collect(Collectors.joining("\n")); - assertThat(interceptor.validationAlgorithm()).isEqualTo(Algorithm.CRC32); + assertThat(interceptor.validationAlgorithm()).isEqualTo(DefaultChecksumAlgorithm.CRC32); assertThat(interceptor.responseValidation()).isEqualTo(ChecksumValidation.VALIDATED); byte[] bytes = Files.readAllBytes(randomFileOfFixedLength.toPath()); assertThat(text).isEqualTo(new String(bytes)); @@ -400,52 +411,130 @@ public void syncValidUnsignedTrailerChecksumCalculatedBySdkClient_withHugeFileRe new InputStreamReader(s3HttpsObject, StandardCharsets.UTF_8)) .lines() .collect(Collectors.joining("\n")); - assertThat(interceptor.validationAlgorithm()).isEqualTo(Algorithm.CRC32); + assertThat(interceptor.validationAlgorithm()).isEqualTo(DefaultChecksumAlgorithm.CRC32); assertThat(interceptor.responseValidation()).isEqualTo(ChecksumValidation.VALIDATED); byte[] bytes = Files.readAllBytes(randomFileOfFixedLength.toPath()); assertThat(text).isEqualTo(new String(bytes)); } - private static Stream getObjectChecksumValidationParams() { - return Stream.of(Arguments.of(true, ChecksumAlgorithm.CRC32, ChecksumMode.ENABLED), - Arguments.of(true, null, ChecksumMode.ENABLED), - Arguments.of(true, ChecksumAlgorithm.CRC32, null), - Arguments.of(true, null, null), - Arguments.of(false, ChecksumAlgorithm.CRC32, ChecksumMode.ENABLED), - Arguments.of(false, null, ChecksumMode.ENABLED), - Arguments.of(false, ChecksumAlgorithm.CRC32, null), - Arguments.of(false, null, null)); + private S3Client createS3Client(RequestChecksumCalculation calculation) { + S3ClientBuilder builder = s3ClientBuilder().overrideConfiguration(o -> o.addExecutionInterceptor(interceptor)); + builder.requestChecksumCalculation(calculation); + return builder.build(); } - @ParameterizedTest - @MethodSource("getObjectChecksumValidationParams") - public void testGetObjectChecksumValidation(boolean checksumValidationEnabled, ChecksumAlgorithm checksumAlgorithm, - ChecksumMode checksumMode) { - S3Client s3 = s3ClientBuilder().overrideConfiguration(o -> o.addExecutionInterceptor(interceptor)) - .serviceConfiguration(S3Configuration.builder() - .checksumValidationEnabled(checksumValidationEnabled) - .build()) - .build(); + private S3Client createS3Client(ResponseChecksumValidation responseChecksumValidation) { + S3ClientBuilder builder = s3ClientBuilder().overrideConfiguration(o -> o.addExecutionInterceptor(interceptor)); + builder.requestChecksumCalculation(RequestChecksumCalculation.WHEN_REQUIRED) + .responseChecksumValidation(responseChecksumValidation); + return builder.build(); + } - s3.putObject(PutObjectRequest.builder() - .bucket(BUCKET) - .key(KEY) - .checksumAlgorithm(checksumAlgorithm) - .build(), RequestBody.fromString("Hello world")); + @ParameterizedTest(name = "{index} {5}") + @MethodSource("software.amazon.awssdk.services.s3.checksum.HttpChecksumTestUtils#getObjectChecksumValidationParams") + public void getObject_checksumValidation( + ResponseChecksumValidation responseChecksumValidation, + ChecksumMode checksumMode, + ChecksumAlgorithm checksumAlgorithm, + boolean shouldValidateMd5Checksum, + String expectedTrailerHeader, + String description) { + try (S3Client s3 = s3ClientBuilder().overrideConfiguration(o -> o.addExecutionInterceptor(interceptor)) + .requestChecksumCalculation(RequestChecksumCalculation.WHEN_REQUIRED) + .responseChecksumValidation(responseChecksumValidation) + .build()) { + s3.putObject(PutObjectRequest.builder() + .bucket(BUCKET) + .checksumAlgorithm(checksumAlgorithm) + .key(KEY) + .build(), RequestBody.fromString("Hello world")); + + ResponseBytes responseBytes = s3.getObject(GetObjectRequest.builder() + .bucket(BUCKET) + .checksumMode(checksumMode) + .key(KEY) + .build(), + ResponseTransformer.toBytes()); + + if (shouldValidateMd5Checksum) { + assertRequestAndResponseContainMd5Header(); + assertThat(responseBytes.response() + .sdkHttpResponse() + .anyMatchingHeader(k -> k.startsWith("x-amz-checksum"))).isFalse(); + } else { + assertRequestAndResponseDoNotContainMd5Header(); + if (expectedTrailerHeader != null) { + assertThat(responseBytes.response() + .sdkHttpResponse() + .firstMatchingHeader(expectedTrailerHeader)).isNotNull(); + } + } + } + } - s3.getObject(GetObjectRequest.builder() - .bucket(BUCKET) - .key(KEY) - .checksumMode(checksumMode) - .build()); + @ParameterizedTest(name = "{index} {4}") + @MethodSource("software.amazon.awssdk.services.s3.checksum.HttpChecksumTestUtils#putObjectChecksumCalculationParams") + public void putObject_checksumCalculation(RequestChecksumCalculation requestChecksumCalculation, + ChecksumAlgorithm checksumAlgorithm, + String checksumCrc32CValue, + String expectedTrailer, + String description) { + try (S3Client s3 = createS3Client(requestChecksumCalculation)) { + s3.putObject(PutObjectRequest.builder() + .bucket(BUCKET) + .checksumCRC32C(checksumCrc32CValue) + .key(KEY) + .checksumAlgorithm(checksumAlgorithm) + .build(), RequestBody.fromString("Hello world")); - validateChecksumValidation(checksumValidationEnabled, checksumAlgorithm, checksumMode); - interceptor.reset(); + assertThat(interceptor.requestChecksumInTrailer()).isEqualTo(expectedTrailer); + if (checksumCrc32CValue != null) { + + assertThat(interceptor.requestHeaders().keySet()).filteredOn(h -> h.contains("x-amz-checksum-")) + .containsExactly(CHECKSUM_CRC32C_HEADER); + assertThat(interceptor.requestHeaders().get(CHECKSUM_CRC32C_HEADER)).containsExactly(checksumCrc32CValue); + } + interceptor.reset(); + } } - private void validateChecksumValidation(boolean checksumValidationEnabled, ChecksumAlgorithm checksumAlgorithm, - ChecksumMode checksumMode) { - if (checksumValidationEnabled) { + @ParameterizedTest(name = "{index} {4}") + @MethodSource("software.amazon.awssdk.services.s3.checksum.HttpChecksumTestUtils#putObjectLifecycleChecksumCalculationParams") + public void putBucketLifecycleChecksumInHeaderRequired_checksumCalculation(RequestChecksumCalculation requestChecksumCalculation, + ChecksumAlgorithm checksumAlgorithm, + String checksumCrc32CValue, + String expectedHeader, + String description) { + try (S3Client s3 = createS3Client(requestChecksumCalculation)) { + LifecycleRule lifecycleRule = LifecycleRule.builder() + .status(ExpirationStatus.ENABLED) + .expiration(e -> e.days(1)) + .filter(f -> f.prefix("test")) + .build(); + PutBucketLifecycleConfigurationRequest.Builder builder = + PutBucketLifecycleConfigurationRequest.builder() + .bucket(BUCKET) + .checksumAlgorithm(checksumAlgorithm) + .lifecycleConfiguration(l -> l.rules(lifecycleRule)); + if (checksumCrc32CValue != null) { + builder.overrideConfiguration(o -> o.putHeader(CHECKSUM_CRC32C_HEADER, + checksumCrc32CValue)); + } + s3.putBucketLifecycleConfiguration(builder.build()); + assertThat(interceptor.requestHeaders().keySet()).filteredOn(h -> h.contains("x-amz-checksum-")) + .containsExactly(expectedHeader); + assertThat(interceptor.requestChecksumInTrailer()).isNull(); + if (checksumCrc32CValue != null) { + assertThat(interceptor.requestHeaders().get(CHECKSUM_CRC32C_HEADER)); + } + } + } + + private void validateChecksumValidation( + ResponseChecksumValidation responseChecksumValidation, + ChecksumAlgorithm checksumAlgorithm, + ChecksumMode checksumMode) { + if (responseChecksumValidation == ResponseChecksumValidation.WHEN_SUPPORTED) { if (checksumMode == ChecksumMode.ENABLED) { assertChecksumModeEnabledWithChecksumValidationEnabled(checksumAlgorithm); } else { @@ -470,6 +559,7 @@ private void assertChecksumModeEnabledWithChecksumValidationEnabled(ChecksumAlgo } } + private void assertChecksumModeNotEnabledWithChecksumValidationEnabled() { assertRequestAndResponseContainMd5Header(); assertThat(interceptor.responseFlexibleChecksumHeader()).isNull(); diff --git a/services/s3/src/it/java/software/amazon/awssdk/services/s3/checksum/HttpChecksumTestUtils.java b/services/s3/src/it/java/software/amazon/awssdk/services/s3/checksum/HttpChecksumTestUtils.java new file mode 100644 index 000000000000..a425460435c4 --- /dev/null +++ b/services/s3/src/it/java/software/amazon/awssdk/services/s3/checksum/HttpChecksumTestUtils.java @@ -0,0 +1,111 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.services.s3.checksum; + +import java.util.stream.Stream; +import org.junit.jupiter.params.provider.Arguments; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidation; +import software.amazon.awssdk.services.s3.model.ChecksumAlgorithm; +import software.amazon.awssdk.services.s3.model.ChecksumMode; + +public final class HttpChecksumTestUtils { + + private HttpChecksumTestUtils() { + } + + public static Stream getObjectChecksumValidationParams() { + return Stream.of( + Arguments.of(ResponseChecksumValidation.WHEN_SUPPORTED, null, ChecksumAlgorithm.CRC32, true, null, + "responseChecksumWhenSupported_checksumModeNotEnabledAndHasChecksum_shouldUseMd5"), + + Arguments.of(ResponseChecksumValidation.WHEN_SUPPORTED, null, null, true, null, + "responseChecksumWhenSupported_checksumModeNotEnabledAndNoChecksum_shouldUseMd5"), + + Arguments.of(ResponseChecksumValidation.WHEN_SUPPORTED, ChecksumMode.ENABLED, ChecksumAlgorithm.CRC32, + false, "x-amz-checksum-crc32", + "responseChecksumWhenSupported_checksumModeEnabledAndHasChecksum_shouldNotUseMd5"), + + Arguments.of(ResponseChecksumValidation.WHEN_SUPPORTED, ChecksumMode.ENABLED, null, + false, null, + "responseChecksumWhenSupported_checksumModeEnabledAndNoChecksum_shouldNotUseMd5"), + + Arguments.of(ResponseChecksumValidation.WHEN_REQUIRED, null, ChecksumAlgorithm.CRC32, false, null, + "responseChecksumWhenRequired_checksumModeNotEnabled_shouldNotUseMd5"), + + Arguments.of(ResponseChecksumValidation.WHEN_REQUIRED, ChecksumMode.ENABLED, ChecksumAlgorithm.CRC32, + false, null, + "responseChecksumWhenRequired_checksumModeEnabled_shouldNotUseToMd5")); + } + + /** + * Checksum is optional for putObject + */ + public static Stream putObjectChecksumCalculationParams() { + return Stream.of(Arguments.of(RequestChecksumCalculation.WHEN_SUPPORTED, null, null, "x-amz-checksum-crc32", + "requestChecksumWhenSupported_checksumAlgorithmAndChecksumValueNotProvided_shouldAddCrc32ChecksumTrailerByDefault"), + + Arguments.of(RequestChecksumCalculation.WHEN_SUPPORTED, ChecksumAlgorithm.SHA1, null, + "x-amz-checksum-sha1", + "requestChecksumWhenSupported_checksumAlgorithmProvided_shouldHonor"), + + Arguments.of(RequestChecksumCalculation.WHEN_SUPPORTED, null, "crUfeA==", + null, + "requestChecksumWhenSupported_checksumValueProvided_shouldHonor"), + + Arguments.of(RequestChecksumCalculation.WHEN_REQUIRED, null, null, null, + "requestChecksumWhenRequired_checksumAlgorithmAndChecksumValueNotProvided_shouldNotAddChecksum"), + + Arguments.of(RequestChecksumCalculation.WHEN_REQUIRED, null, "crUfeA==", + null, + "requestChecksumWhenRequired_checksumValueProvided_shouldAddChecksumTrailer"), + + Arguments.of(RequestChecksumCalculation.WHEN_REQUIRED, ChecksumAlgorithm.CRC32_C, null, + "x-amz-checksum-crc32c", + "requestChecksumWhenRequired_checksumAlgorithmProvided_shouldAddChecksumTrailer")); + } + + /** + * Checksum header is required for putObjectLifeCycle + */ + public static Stream putObjectLifecycleChecksumCalculationParams() { + return Stream.of(Arguments.of(RequestChecksumCalculation.WHEN_SUPPORTED, null, null, + "x-amz-checksum-crc32", + "requestChecksumWhenSupported_checksumAlgorithmAndValueNotProvided_shouldAddCrc32ChecksumHeaderByDefault"), + + Arguments.of(RequestChecksumCalculation.WHEN_SUPPORTED, ChecksumAlgorithm.SHA1, null, + "x-amz-checksum-sha1", + "requestChecksumWhenSupported_checksumAlgorithmProvided_shouldHonor"), + + Arguments.of(RequestChecksumCalculation.WHEN_SUPPORTED, null, "7khuxQ==", + "x-amz-checksum-crc32c", + "requestChecksumWhenSupported_checksumValueProvided_shouldHonor"), + + Arguments.of(RequestChecksumCalculation.WHEN_REQUIRED, null, null, + "x-amz-checksum-crc32", + "requestChecksumWhenRequired_checksumAlgorithmAndValueNotProvided_shouldAddCrc32Checksum"), + + Arguments.of(RequestChecksumCalculation.WHEN_REQUIRED, null, "7khuxQ==", + "x-amz-checksum-crc32c", + "requestChecksumWhenRequired_checksumValueProvided_shouldHonor"), + + Arguments.of(RequestChecksumCalculation.WHEN_REQUIRED, ChecksumAlgorithm.CRC32_C, null, + "x-amz-checksum-crc32c", + "requestChecksumWhenRequired_checksumAlgorithmProvided_shouldAddChecksumHeader")); + } + + +} diff --git a/services/s3/src/it/java/software/amazon/awssdk/services/s3/crt/CrtChecksumIntegrationTest.java b/services/s3/src/it/java/software/amazon/awssdk/services/s3/crt/CrtChecksumIntegrationTest.java index d5123f340b17..7d8ef4f13b8b 100644 --- a/services/s3/src/it/java/software/amazon/awssdk/services/s3/crt/CrtChecksumIntegrationTest.java +++ b/services/s3/src/it/java/software/amazon/awssdk/services/s3/crt/CrtChecksumIntegrationTest.java @@ -27,6 +27,8 @@ import software.amazon.awssdk.core.async.AsyncRequestBody; import software.amazon.awssdk.core.async.AsyncResponseTransformer; import software.amazon.awssdk.core.checksums.Algorithm; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidation; import software.amazon.awssdk.services.s3.S3AsyncClient; import software.amazon.awssdk.services.s3.S3IntegrationTestBase; import software.amazon.awssdk.services.s3.internal.crt.S3CrtAsyncClient; @@ -62,8 +64,8 @@ public static void setup() throws Exception { testFileCrc32 = ChecksumUtils.calculatedChecksum(testFile.toPath(), Algorithm.CRC32); s3Crt = S3CrtAsyncClient.builder() - .credentialsProvider(AwsTestBase.CREDENTIALS_PROVIDER_CHAIN) - .region(S3IntegrationTestBase.DEFAULT_REGION) + .credentialsProvider(CREDENTIALS_PROVIDER_CHAIN) + .region(DEFAULT_REGION) // make sure we don't do a multipart upload, it will mess with validation against the precomputed // checksums above .thresholdInBytes(2L * OBJ_SIZE) @@ -106,7 +108,8 @@ void checksumDisabled_shouldNotPerformChecksumValidationByDefault() { try (S3AsyncClient s3Crt = S3CrtAsyncClient.builder() .credentialsProvider(AwsTestBase.CREDENTIALS_PROVIDER_CHAIN) .region(S3IntegrationTestBase.DEFAULT_REGION) - .checksumValidationEnabled(Boolean.FALSE) + .requestChecksumCalculation(RequestChecksumCalculation.WHEN_REQUIRED) + .responseChecksumValidation(ResponseChecksumValidation.WHEN_REQUIRED) .build()) { AsyncRequestBody body = AsyncRequestBody.fromFile(testFile.toPath()); PutObjectResponse putObjectResponse = diff --git a/services/s3/src/it/java/software/amazon/awssdk/services/s3/multipart/S3MultipartClientPutObjectIntegrationTest.java b/services/s3/src/it/java/software/amazon/awssdk/services/s3/multipart/S3MultipartClientPutObjectIntegrationTest.java index 3e6811f69b3c..69a296e6b98f 100644 --- a/services/s3/src/it/java/software/amazon/awssdk/services/s3/multipart/S3MultipartClientPutObjectIntegrationTest.java +++ b/services/s3/src/it/java/software/amazon/awssdk/services/s3/multipart/S3MultipartClientPutObjectIntegrationTest.java @@ -20,8 +20,11 @@ import static software.amazon.awssdk.services.s3.model.ServerSideEncryption.AES256; import static software.amazon.awssdk.testutils.service.S3BucketUtils.temporaryBucketName; +import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.nio.file.Files; @@ -32,6 +35,8 @@ import java.util.Map; import java.util.Optional; import java.util.UUID; +import java.util.zip.CRC32; +import java.util.zip.CheckedInputStream; import javax.crypto.KeyGenerator; import org.apache.commons.lang3.RandomStringUtils; import org.junit.jupiter.api.AfterAll; @@ -48,15 +53,19 @@ import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; import software.amazon.awssdk.core.internal.async.FileAsyncRequestBody; import software.amazon.awssdk.core.sync.ResponseTransformer; -import software.amazon.awssdk.http.SdkHttpRequest; import software.amazon.awssdk.services.s3.S3AsyncClient; import software.amazon.awssdk.services.s3.S3IntegrationTestBase; import software.amazon.awssdk.services.s3.model.ChecksumAlgorithm; +import software.amazon.awssdk.services.s3.model.ChecksumMode; +import software.amazon.awssdk.services.s3.model.CompleteMultipartUploadRequest; +import software.amazon.awssdk.services.s3.model.CreateMultipartUploadRequest; import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.awssdk.services.s3.model.UploadPartRequest; import software.amazon.awssdk.services.s3.utils.ChecksumUtils; +import software.amazon.awssdk.utils.IoUtils; import software.amazon.awssdk.utils.Md5Utils; -@Timeout(value = 30, unit = SECONDS) +@Timeout(value = 60, unit = SECONDS) public class S3MultipartClientPutObjectIntegrationTest extends S3IntegrationTestBase { private static final String TEST_BUCKET = temporaryBucketName(S3MultipartClientPutObjectIntegrationTest.class); @@ -69,8 +78,8 @@ public class S3MultipartClientPutObjectIntegrationTest extends S3IntegrationTest @BeforeAll public static void setup() throws Exception { - S3IntegrationTestBase.setUp(); - S3IntegrationTestBase.createBucket(TEST_BUCKET); + setUp(); + createBucket(TEST_BUCKET); testFile = File.createTempFile("SplittingPublisherTest", UUID.randomUUID().toString()); Files.write(testFile.toPath(), CONTENT); mpuS3Client = S3AsyncClient @@ -100,11 +109,11 @@ void putObject_fileRequestBody_objectSentCorrectly() throws Exception { AsyncRequestBody body = AsyncRequestBody.fromFile(testFile.toPath()); mpuS3Client.putObject(r -> r.bucket(TEST_BUCKET).key(TEST_KEY), body).join(); - assertThat(CAPTURING_INTERCEPTOR.checksumHeader).isEqualTo("CRC32"); + assertThat(CAPTURING_INTERCEPTOR.createMpuChecksumAlgorithm).isEqualTo("CRC32"); + assertThat(CAPTURING_INTERCEPTOR.uploadPartChecksumAlgorithm).isEqualTo("CRC32"); - ResponseInputStream objContent = - S3IntegrationTestBase.s3.getObject(r -> r.bucket(TEST_BUCKET).key(TEST_KEY), - ResponseTransformer.toInputStream()); + ResponseInputStream objContent = s3.getObject(r -> r.bucket(TEST_BUCKET).key(TEST_KEY), + ResponseTransformer.toInputStream()); assertThat(objContent.response().contentLength()).isEqualTo(testFile.length()); byte[] expectedSum = ChecksumUtils.computeCheckSum(Files.newInputStream(testFile.toPath())); @@ -117,11 +126,11 @@ void putObject_byteAsyncRequestBody_objectSentCorrectly() throws Exception { AsyncRequestBody body = AsyncRequestBody.fromBytes(bytes); mpuS3Client.putObject(r -> r.bucket(TEST_BUCKET).key(TEST_KEY), body).join(); - assertThat(CAPTURING_INTERCEPTOR.checksumHeader).isEqualTo("CRC32"); + assertThat(CAPTURING_INTERCEPTOR.createMpuChecksumAlgorithm).isEqualTo("CRC32"); + assertThat(CAPTURING_INTERCEPTOR.uploadPartChecksumAlgorithm).isEqualTo("CRC32"); - ResponseInputStream objContent = - S3IntegrationTestBase.s3.getObject(r -> r.bucket(TEST_BUCKET).key(TEST_KEY), - ResponseTransformer.toInputStream()); + ResponseInputStream objContent = s3.getObject(r -> r.bucket(TEST_BUCKET).key(TEST_KEY), + ResponseTransformer.toInputStream()); assertThat(objContent.response().contentLength()).isEqualTo(OBJ_SIZE); byte[] expectedSum = ChecksumUtils.computeCheckSum(new ByteArrayInputStream(bytes)); @@ -145,11 +154,11 @@ public void subscribe(Subscriber s) { } }).get(30, SECONDS); - assertThat(CAPTURING_INTERCEPTOR.checksumHeader).isEqualTo("CRC32"); + assertThat(CAPTURING_INTERCEPTOR.createMpuChecksumAlgorithm).isEqualTo("CRC32"); + assertThat(CAPTURING_INTERCEPTOR.uploadPartChecksumAlgorithm).isEqualTo("CRC32"); - ResponseInputStream objContent = - S3IntegrationTestBase.s3.getObject(r -> r.bucket(TEST_BUCKET).key(TEST_KEY), - ResponseTransformer.toInputStream()); + ResponseInputStream objContent = s3.getObject(r -> r.bucket(TEST_BUCKET).key(TEST_KEY), + ResponseTransformer.toInputStream()); assertThat(objContent.response().contentLength()).isEqualTo(testFile.length()); byte[] expectedSum = ChecksumUtils.computeCheckSum(Files.newInputStream(testFile.toPath())); @@ -170,15 +179,15 @@ void putObject_withSSECAndChecksum_objectSentCorrectly() throws Exception { .sseCustomerKeyMD5(b64KeyMd5), body).join(); - assertThat(CAPTURING_INTERCEPTOR.checksumHeader).isEqualTo("CRC32"); + assertThat(CAPTURING_INTERCEPTOR.createMpuChecksumAlgorithm).isEqualTo("CRC32"); + assertThat(CAPTURING_INTERCEPTOR.uploadPartChecksumAlgorithm).isEqualTo("CRC32"); - ResponseInputStream objContent = - S3IntegrationTestBase.s3.getObject(r -> r.bucket(TEST_BUCKET) - .key(TEST_KEY) - .sseCustomerKey(b64Key) - .sseCustomerAlgorithm(AES256.name()) - .sseCustomerKeyMD5(b64KeyMd5), - ResponseTransformer.toInputStream()); + ResponseInputStream objContent = s3.getObject(r -> r.bucket(TEST_BUCKET) + .key(TEST_KEY) + .sseCustomerKey(b64Key) + .sseCustomerAlgorithm(AES256.name()) + .sseCustomerKeyMD5(b64KeyMd5), + ResponseTransformer.toInputStream()); assertThat(objContent.response().contentLength()).isEqualTo(testFile.length()); byte[] expectedSum = ChecksumUtils.computeCheckSum(Files.newInputStream(testFile.toPath())); @@ -186,24 +195,46 @@ void putObject_withSSECAndChecksum_objectSentCorrectly() throws Exception { } @Test - void putObject_withUserSpecifiedChecksumValue_objectSentCorrectly() throws Exception { - String sha1Val = calculateSHA1AsString(); + void putObject_withoutSpecifiedChecksum_shouldDefaultToCRC32() { + AsyncRequestBody body = AsyncRequestBody.fromFile(testFile.toPath()); + mpuS3Client.putObject(r -> r.bucket(TEST_BUCKET) + .key(TEST_KEY), + body).join(); + + assertThat(CAPTURING_INTERCEPTOR.createMpuChecksumAlgorithm).isEqualTo("CRC32"); + assertThat(CAPTURING_INTERCEPTOR.uploadPartChecksumAlgorithm).isEqualTo("CRC32"); + assertThat(CAPTURING_INTERCEPTOR.createMpuChecksumType).isNull(); + assertThat(CAPTURING_INTERCEPTOR.completeMpuChecksumType).isNull(); + + ResponseInputStream objContent = + s3.getObject(r -> r.bucket(TEST_BUCKET).key(TEST_KEY).checksumMode(ChecksumMode.ENABLED), + ResponseTransformer.toInputStream()); + + assertThat(objContent.response().contentLength()).isEqualTo(testFile.length()); + assertThat(objContent.response().checksumCRC32()).isNotNull(); + } + + @Test + void putObject_withUserSpecifiedCrc32_setsChecksumTypeFullObject() throws Exception { + String crc32Val = calculateCRC32AsString(testFile.getPath()); AsyncRequestBody body = AsyncRequestBody.fromFile(testFile.toPath()); mpuS3Client.putObject(r -> r.bucket(TEST_BUCKET) .key(TEST_KEY) - .checksumSHA1(sha1Val), + .checksumCRC32(crc32Val), body).join(); - assertThat(CAPTURING_INTERCEPTOR.headers.get("x-amz-checksum-sha1")).contains(sha1Val); - assertThat(CAPTURING_INTERCEPTOR.checksumHeader).isNull(); + assertThat(CAPTURING_INTERCEPTOR.completeMpuHeaders.get("x-amz-checksum-crc32")).contains(crc32Val); + assertThat(CAPTURING_INTERCEPTOR.createMpuChecksumAlgorithm).isEqualTo("CRC32"); + assertThat(CAPTURING_INTERCEPTOR.uploadPartChecksumAlgorithm).isEqualTo("CRC32"); + assertThat(CAPTURING_INTERCEPTOR.createMpuChecksumType).isEqualTo("FULL_OBJECT"); + assertThat(CAPTURING_INTERCEPTOR.completeMpuChecksumType).isEqualTo("FULL_OBJECT"); ResponseInputStream objContent = - S3IntegrationTestBase.s3.getObject(r -> r.bucket(TEST_BUCKET).key(TEST_KEY), - ResponseTransformer.toInputStream()); + s3.getObject(r -> r.bucket(TEST_BUCKET).key(TEST_KEY).checksumMode(ChecksumMode.ENABLED), + ResponseTransformer.toInputStream()); assertThat(objContent.response().contentLength()).isEqualTo(testFile.length()); - byte[] expectedSum = ChecksumUtils.computeCheckSum(Files.newInputStream(testFile.toPath())); - assertThat(ChecksumUtils.computeCheckSum(objContent)).isEqualTo(expectedSum); + assertThat(objContent.response().checksumCRC32()).isEqualTo(crc32Val); } @Test @@ -214,7 +245,20 @@ void putObject_withUserSpecifiedChecksumTypeOtherThanCrc32_shouldHonorChecksum() .checksumAlgorithm(ChecksumAlgorithm.SHA1), body).join(); - assertThat(CAPTURING_INTERCEPTOR.checksumHeader).isEqualTo("SHA1"); + assertThat(CAPTURING_INTERCEPTOR.createMpuChecksumAlgorithm).isEqualTo("SHA1"); + assertThat(CAPTURING_INTERCEPTOR.uploadPartChecksumAlgorithm).isEqualTo("SHA1"); + } + + private static String calculateCRC32AsString(String filePath) throws IOException { + try (FileInputStream fis = new FileInputStream(filePath); + BufferedInputStream bis = new BufferedInputStream(fis); + CheckedInputStream cis = new CheckedInputStream(bis, new CRC32())) { + + IoUtils.drainInputStream(cis); + long checksumValue = cis.getChecksum().getValue(); + byte[] checksumBytes = ByteBuffer.allocate(4).putInt((int) checksumValue).array(); + return Base64.getEncoder().encodeToString(checksumBytes); + } } private static String calculateSHA1AsString() throws Exception { @@ -236,22 +280,60 @@ private static byte[] generateSecretKey() { } private static final class CapturingInterceptor implements ExecutionInterceptor { - String checksumHeader; - Map> headers; + private static final String CHECKSUM_ALGORITHM_HEADER = "x-amz-checksum-algorithm"; + private static final String CHECKSUM_TYPE_HEADER = "x-amz-checksum-type"; + private static final String MP_OBJECT_SIZE_HEADER = "x-amz-mp-object-size"; + private static final String SDK_CHECKSUM_ALGORITHM_HEADER = "x-amz-sdk-checksum-algorithm"; + Map> completeMpuHeaders; + String createMpuChecksumType; + String createMpuChecksumAlgorithm; + String uploadPartChecksumAlgorithm; + String completeMpuChecksumType; + Long completeMpuMpObjectSize; + @Override public void beforeTransmission(Context.BeforeTransmission context, ExecutionAttributes executionAttributes) { - SdkHttpRequest sdkHttpRequest = context.httpRequest(); - headers = sdkHttpRequest.headers(); - String checksumHeaderName = "x-amz-sdk-checksum-algorithm"; - if (headers.containsKey(checksumHeaderName)) { - List checksumHeaderVals = headers.get(checksumHeaderName); - assertThat(checksumHeaderVals).hasSize(1); - checksumHeader = checksumHeaderVals.get(0); + Map> headers = context.httpRequest().headers(); + if (isCreateMpuRequest(context) && headers.containsKey(CHECKSUM_ALGORITHM_HEADER)) { + createMpuChecksumAlgorithm = headers.get(CHECKSUM_ALGORITHM_HEADER).get(0); + } + + if (isUploadPartRequest(context) && headers.containsKey(SDK_CHECKSUM_ALGORITHM_HEADER)) { + uploadPartChecksumAlgorithm = headers.get(SDK_CHECKSUM_ALGORITHM_HEADER).get(0); + } + + if (headers.containsKey(CHECKSUM_TYPE_HEADER)) { + if (isCreateMpuRequest(context)) { + createMpuChecksumType = headers.get(CHECKSUM_TYPE_HEADER).get(0); + } else if (isCompleteMpuRequest(context)) { + completeMpuChecksumType = headers.get(CHECKSUM_TYPE_HEADER).get(0); + } + } + + if (isCompleteMpuRequest(context) && headers.containsKey(MP_OBJECT_SIZE_HEADER)) { + completeMpuMpObjectSize = Long.valueOf(headers.get(MP_OBJECT_SIZE_HEADER).get(0)); + completeMpuHeaders = headers; } } public void reset() { - checksumHeader = null; + createMpuChecksumType = null; + createMpuChecksumAlgorithm = null; + uploadPartChecksumAlgorithm = null; + completeMpuChecksumType = null; + completeMpuMpObjectSize = null; + } + + private static boolean isCreateMpuRequest(Context.BeforeTransmission context) { + return context.request() instanceof CreateMultipartUploadRequest; + } + + private static boolean isCompleteMpuRequest(Context.BeforeTransmission context) { + return context.request() instanceof CompleteMultipartUploadRequest; + } + + private static boolean isUploadPartRequest(Context.BeforeTransmission context) { + return context.request() instanceof UploadPartRequest; } } -} +} \ No newline at end of file diff --git a/services/s3/src/it/java/software/amazon/awssdk/services/s3/s3express/S3ExpressIntegrationTest.java b/services/s3/src/it/java/software/amazon/awssdk/services/s3/s3express/S3ExpressIntegrationTest.java index 7e93b299c272..46494b3ac9b2 100644 --- a/services/s3/src/it/java/software/amazon/awssdk/services/s3/s3express/S3ExpressIntegrationTest.java +++ b/services/s3/src/it/java/software/amazon/awssdk/services/s3/s3express/S3ExpressIntegrationTest.java @@ -63,6 +63,8 @@ import software.amazon.awssdk.services.s3.S3AsyncClient; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.internal.plugins.S3OverrideAuthSchemePropertiesPlugin; +import software.amazon.awssdk.services.s3.model.ChecksumAlgorithm; +import software.amazon.awssdk.services.s3.model.ChecksumType; import software.amazon.awssdk.services.s3.model.CompleteMultipartUploadRequest; import software.amazon.awssdk.services.s3.model.CompleteMultipartUploadResponse; import software.amazon.awssdk.services.s3.model.CompletedMultipartUpload; @@ -194,6 +196,43 @@ public void uploadMultiplePartAsync(S3AsyncClient s3AsyncClient) { assertThat(objectAsBytes.asUtf8String()).isEqualTo(appendedString); } + @ParameterizedTest(autoCloseArguments = false) + @MethodSource("asyncClients") + public void uploadMultiplePartAsync_withChecksum(S3AsyncClient s3AsyncClient) { + String uploadId = s3AsyncClient.createMultipartUpload(b -> b.bucket(testBucket) + .checksumAlgorithm(ChecksumAlgorithm.CRC64_NVME) + .checksumType(ChecksumType.FULL_OBJECT) + .key(KEY)).join().uploadId(); + + + UploadPartRequest uploadPartRequest = UploadPartRequest.builder().bucket(testBucket).key(KEY) + .uploadId(uploadId) + .checksumAlgorithm(ChecksumAlgorithm.CRC64_NVME) + .partNumber(1) + .build(); + + UploadPartResponse response = s3AsyncClient.uploadPart(uploadPartRequest, AsyncRequestBody.fromString(CONTENTS)).join(); + + List completedParts = new ArrayList<>(); + completedParts.add(CompletedPart.builder() + .checksumCRC64NVME(response.checksumCRC64NVME()) + .eTag(response.eTag()).partNumber(1).build()); + CompletedMultipartUpload completedUploadParts = CompletedMultipartUpload.builder().parts(completedParts).build(); + CompleteMultipartUploadRequest completeRequest = CompleteMultipartUploadRequest.builder() + .bucket(testBucket) + .key(KEY) + .checksumType(ChecksumType.FULL_OBJECT) + .uploadId(uploadId) + .multipartUpload(completedUploadParts) + .build(); + CompleteMultipartUploadResponse completeMultipartUploadResponse = s3AsyncClient.completeMultipartUpload(completeRequest).join(); + assertThat(completeMultipartUploadResponse).isNotNull(); + + ResponseBytes objectAsBytes = s3.getObject(b -> b.bucket(testBucket).key(KEY), ResponseTransformer.toBytes()); + String appendedString = String.join("", CONTENTS); + assertThat(objectAsBytes.asUtf8String()).isEqualTo(appendedString); + } + @MethodSource("syncTestCases") @ParameterizedTest public void s3Express_nonObjectTransferApis_Sync(SyncTestCase tc) { diff --git a/services/s3/src/it/java/software/amazon/awssdk/services/s3/s3express/S3ExpressIntegrationTestBase.java b/services/s3/src/it/java/software/amazon/awssdk/services/s3/s3express/S3ExpressIntegrationTestBase.java index 0f0001313506..d8c3fb86e6fe 100644 --- a/services/s3/src/it/java/software/amazon/awssdk/services/s3/s3express/S3ExpressIntegrationTestBase.java +++ b/services/s3/src/it/java/software/amazon/awssdk/services/s3/s3express/S3ExpressIntegrationTestBase.java @@ -40,8 +40,10 @@ import software.amazon.awssdk.services.s3.model.S3Exception; import software.amazon.awssdk.services.s3.model.S3Object; import software.amazon.awssdk.testutils.Waiter; +import software.amazon.awssdk.utils.Logger; public class S3ExpressIntegrationTestBase { + private static final Logger log = Logger.loggerFor(S3ExpressIntegrationTestBase.class); protected static S3ClientBuilder s3ClientBuilder(Region region) { return S3Client.builder() @@ -80,9 +82,9 @@ protected static void createBucketS3Express(S3Client client, String bucketName, .createBucketConfiguration(bucketConfiguration) .build()); } catch (S3Exception e) { - System.err.println("Error attempting to create bucket: " + bucketName); + log.error(() -> "Error attempting to create bucket: " + bucketName, e); if (e.awsErrorDetails().errorCode().equals("BucketAlreadyOwnedByYou")) { - System.err.printf("%s bucket already exists, likely leaked by a previous run\n", bucketName); + log.error(() -> bucketName + " bucket already exists, likely leaked by a previous run"); } else { throw e; } diff --git a/services/s3/src/it/java/software/amazon/awssdk/services/s3/signer/PayloadSigningIntegrationTest.java b/services/s3/src/it/java/software/amazon/awssdk/services/s3/signer/PayloadSigningIntegrationTest.java index dbe9bc2f7486..41934a21ac3f 100644 --- a/services/s3/src/it/java/software/amazon/awssdk/services/s3/signer/PayloadSigningIntegrationTest.java +++ b/services/s3/src/it/java/software/amazon/awssdk/services/s3/signer/PayloadSigningIntegrationTest.java @@ -48,8 +48,8 @@ public class PayloadSigningIntegrationTest extends S3IntegrationTestBase { private static final String BUCKET = temporaryBucketName(PayloadSigningIntegrationTest.class); private static final String KEY = "key"; - private static final String SIGNED_PAYLOAD_HEADER_VALUE = "STREAMING-AWS4-HMAC-SHA256-PAYLOAD"; - private static final String UNSIGNED_PAYLOAD_HEADER_VALUE = "UNSIGNED-PAYLOAD"; + private static final String SIGNED_PAYLOAD_TAILER_HEADER_VALUE = "STREAMING-AWS4-HMAC-SHA256-PAYLOAD-TRAILER"; + private static final String UNSIGNED_PAYLOAD_TRAILER_HEADER_VALUE = "STREAMING-UNSIGNED-PAYLOAD-TRAILER"; private static final CapturingInterceptor capturingInterceptor = new CapturingInterceptor(); @@ -78,7 +78,7 @@ public void standardSyncApacheHttpClient_unsignedPayload() { assertThat(syncClient.putObject(b -> b.bucket(BUCKET).key(KEY), RequestBody.fromBytes("helloworld".getBytes()))).isNotNull(); List capturedSha256Values = getSha256Values(); - assertThat(capturedSha256Values).containsExactly(UNSIGNED_PAYLOAD_HEADER_VALUE); + assertThat(capturedSha256Values).containsExactly(UNSIGNED_PAYLOAD_TRAILER_HEADER_VALUE); syncClient.close(); } @@ -91,7 +91,7 @@ public void standardSyncApacheHttpClient_httpCauses_signedPayload() { assertThat(syncClient.putObject(b -> b.bucket(BUCKET).key(KEY), RequestBody.fromBytes("helloworld".getBytes()))).isNotNull(); List capturedSha256Values = getSha256Values(); - assertThat(capturedSha256Values).containsExactly(SIGNED_PAYLOAD_HEADER_VALUE); + assertThat(capturedSha256Values).containsExactly(SIGNED_PAYLOAD_TAILER_HEADER_VALUE); syncClient.close(); } @@ -105,7 +105,7 @@ public void standardSyncApacheHttpClient_manuallyEnabled_signedPayload() { assertThat(syncClient.putObject(b -> b.bucket(BUCKET).key(KEY), RequestBody.fromBytes("helloworld".getBytes()))).isNotNull(); List capturedSha256Values = getSha256Values(); - assertThat(capturedSha256Values).containsExactly(SIGNED_PAYLOAD_HEADER_VALUE); + assertThat(capturedSha256Values).containsExactly(SIGNED_PAYLOAD_TAILER_HEADER_VALUE); syncClient.close(); } diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/S3Configuration.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/S3Configuration.java index e017da24fc54..c640ce5b39b1 100644 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/S3Configuration.java +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/S3Configuration.java @@ -22,6 +22,8 @@ import software.amazon.awssdk.annotations.SdkPublicApi; import software.amazon.awssdk.annotations.ThreadSafe; import software.amazon.awssdk.core.ServiceConfiguration; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidation; import software.amazon.awssdk.profiles.ProfileFile; import software.amazon.awssdk.profiles.ProfileFileSupplier; import software.amazon.awssdk.profiles.ProfileFileSystemSetting; @@ -299,6 +301,13 @@ public interface Builder extends CopyableBuilder { */ Builder pathStyleAccessEnabled(Boolean pathStyleAccessEnabled); + /** + * @deprecated This option has been replaced with + * {@link S3ClientBuilder#requestChecksumCalculation(RequestChecksumCalculation)} and + * {@link S3ClientBuilder#responseChecksumValidation(ResponseChecksumValidation)}. If both this and one of those options + * are set, an exception will be thrown. + */ + @Deprecated Boolean checksumValidationEnabled(); /** @@ -325,7 +334,13 @@ public interface Builder extends CopyableBuilder { * * * @see S3Configuration#checksumValidationEnabled(). + * + * @deprecated This option has been replaced with + * {@link S3ClientBuilder#requestChecksumCalculation(RequestChecksumCalculation)} and + * {@link S3ClientBuilder#responseChecksumValidation(ResponseChecksumValidation)}. If both this and one of those options + * are set, an exception will be thrown. */ + @Deprecated Builder checksumValidationEnabled(Boolean checksumValidationEnabled); Boolean chunkedEncodingEnabled(); diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/S3CrtAsyncClientBuilder.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/S3CrtAsyncClientBuilder.java index cd5cf77554cb..a31c11ee5877 100644 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/S3CrtAsyncClientBuilder.java +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/S3CrtAsyncClientBuilder.java @@ -23,6 +23,8 @@ import java.util.function.Consumer; import software.amazon.awssdk.annotations.SdkPublicApi; import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidation; import software.amazon.awssdk.identity.spi.AwsCredentialsIdentity; import software.amazon.awssdk.identity.spi.IdentityProvider; import software.amazon.awssdk.regions.Region; @@ -192,9 +194,25 @@ S3CrtAsyncClientBuilder maxNativeMemoryLimitInBytes(Long maxNativeMemoryLimitInB * *

    * Checksum validation using CRC32 is enabled by default. + * + * @deprecated This option has been replaced with + * {@link S3CrtAsyncClientBuilder#requestChecksumCalculation(RequestChecksumCalculation)} and + * {@link S3CrtAsyncClientBuilder#responseChecksumValidation(ResponseChecksumValidation)}. If both this and one of those + * options are set, an exception will be thrown. */ + @Deprecated S3CrtAsyncClientBuilder checksumValidationEnabled(Boolean checksumValidationEnabled); + /** + * Configures the client behavior for request checksum calculation. + */ + S3CrtAsyncClientBuilder requestChecksumCalculation(RequestChecksumCalculation requestChecksumCalculation); + + /** + * Configures the client behavior for response checksum validation. + */ + S3CrtAsyncClientBuilder responseChecksumValidation(ResponseChecksumValidation responseChecksumValidation); + /** * Configure the starting buffer size the client will use to buffer the parts downloaded from S3. Maintain a larger window to * keep up a high download throughput; parts cannot download in parallel unless the window is large enough to hold multiple diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/checksums/ChecksumCalculatingAsyncRequestBody.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/checksums/ChecksumCalculatingAsyncRequestBody.java deleted file mode 100644 index bd19c9209889..000000000000 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/checksums/ChecksumCalculatingAsyncRequestBody.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -package software.amazon.awssdk.services.s3.internal.checksums; - -import java.nio.ByteBuffer; -import java.util.Optional; -import java.util.concurrent.atomic.AtomicLong; -import org.reactivestreams.Subscriber; -import org.reactivestreams.Subscription; -import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.core.async.AsyncRequestBody; -import software.amazon.awssdk.core.checksums.SdkChecksum; -import software.amazon.awssdk.http.SdkHttpRequest; -import software.amazon.awssdk.utils.BinaryUtils; - -@SdkInternalApi -public class ChecksumCalculatingAsyncRequestBody implements AsyncRequestBody { - private final Long contentLength; - private final AsyncRequestBody wrapped; - private final SdkChecksum sdkChecksum; - - public ChecksumCalculatingAsyncRequestBody(SdkHttpRequest request, AsyncRequestBody wrapped, SdkChecksum sdkChecksum) { - this.contentLength = request.firstMatchingHeader("Content-Length") - .map(Long::parseLong) - .orElseGet(() -> wrapped.contentLength() - .orElse(null)); - this.wrapped = wrapped; - this.sdkChecksum = sdkChecksum; - } - - @Override - public Optional contentLength() { - return wrapped.contentLength(); - } - - @Override - public String contentType() { - return wrapped.contentType(); - } - - @Override - public void subscribe(Subscriber s) { - sdkChecksum.reset(); - wrapped.subscribe(new ChecksumCalculatingSubscriber(s, sdkChecksum, contentLength)); - } - - private static final class ChecksumCalculatingSubscriber implements Subscriber { - private final AtomicLong contentRead = new AtomicLong(0); - private final Subscriber wrapped; - private final SdkChecksum checksum; - private final Long contentLength; - - ChecksumCalculatingSubscriber(Subscriber wrapped, - SdkChecksum sdkChecksum, - Long contentLength) { - this.wrapped = wrapped; - this.checksum = sdkChecksum; - this.contentLength = contentLength; - } - - @Override - public void onSubscribe(Subscription s) { - wrapped.onSubscribe(s); - } - - @Override - public void onNext(ByteBuffer byteBuffer) { - int amountToReadFromByteBuffer = getAmountToReadFromByteBuffer(byteBuffer); - - if (amountToReadFromByteBuffer > 0) { - byte[] buf = BinaryUtils.copyBytesFrom(byteBuffer, amountToReadFromByteBuffer); - checksum.update(buf, 0, amountToReadFromByteBuffer); - } - - - wrapped.onNext(byteBuffer); - } - - private int getAmountToReadFromByteBuffer(ByteBuffer byteBuffer) { - // If content length is null, we should include everything in the checksum because the stream is essentially - // unbounded. - if (contentLength == null) { - return byteBuffer.remaining(); - } - - long amountReadSoFar = contentRead.getAndAdd(byteBuffer.remaining()); - long amountRemaining = Math.max(0, contentLength - amountReadSoFar); - - if (amountRemaining > byteBuffer.remaining()) { - return byteBuffer.remaining(); - } else { - return Math.toIntExact(amountRemaining); - } - } - - @Override - public void onError(Throwable t) { - wrapped.onError(t); - } - - @Override - public void onComplete() { - wrapped.onComplete(); - } - } -} diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/checksums/ChecksumCalculatingInputStream.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/checksums/ChecksumCalculatingInputStream.java deleted file mode 100644 index e1136df93f1f..000000000000 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/checksums/ChecksumCalculatingInputStream.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -package software.amazon.awssdk.services.s3.internal.checksums; - -import java.io.FilterInputStream; -import java.io.IOException; -import java.io.InputStream; -import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.core.checksums.SdkChecksum; - -@SdkInternalApi -public class ChecksumCalculatingInputStream extends FilterInputStream { - - private final SdkChecksum checkSum; - private final InputStream inputStream; - private boolean endOfStream = false; - - /** - * Creates an input stream using the specified Checksum. - * - * @param in the input stream to read - * @param cksum the Checksum implementation to use for computing the checksum - */ - public ChecksumCalculatingInputStream(final InputStream in, final SdkChecksum cksum) { - super(in); - inputStream = in; - checkSum = cksum; - } - - /** - * Reads from the underlying stream. If the end of the stream is reached, the - * running checksum will be appended a byte at a time (1 per read call). - * - * @return byte read, if eos has been reached, -1 will be returned. - */ - @Override - public int read() throws IOException { - int read = -1; - - if (!endOfStream) { - read = inputStream.read(); - - if (read != -1) { - checkSum.update(read); - } - - if (read == -1) { - endOfStream = true; - } - } - - return read; - } - - /** - * Reads up to len bytes at a time from the input stream, updates the checksum. If the end of the stream has been reached - * the checksum will be appended to the last 4 bytes. - * - * @param buf buffer to write into - * @param off offset in the buffer to write to - * @param len maximum number of bytes to attempt to read. - * @return number of bytes written into buf, otherwise -1 will be returned to indicate eos. - */ - @Override - public int read(byte[] buf, int off, int len) throws IOException { - if (buf == null) { - throw new NullPointerException(); - } - - int read = -1; - - if (!endOfStream) { - read = inputStream.read(buf, off, len); - - if (read != -1) { - checkSum.update(buf, off, read); - } - - if (read == -1) { - endOfStream = true; - } - } - - return read; - } - - /** - * Resets stream state, including the running checksum. - */ - @Override - public synchronized void reset() throws IOException { - inputStream.reset(); - checkSum.reset(); - endOfStream = false; - } - - public byte[] getChecksumBytes() { - return checkSum.getChecksumBytes(); - } -} diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/checksums/ChecksumsEnabledValidator.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/checksums/ChecksumsEnabledValidator.java index 854899df08e8..1b13e0d9f893 100644 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/checksums/ChecksumsEnabledValidator.java +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/checksums/ChecksumsEnabledValidator.java @@ -17,32 +17,20 @@ import static software.amazon.awssdk.services.s3.model.ServerSideEncryption.AWS_KMS; -import java.util.Arrays; -import java.util.Optional; -import java.util.stream.Stream; import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.core.ClientType; import software.amazon.awssdk.core.SdkRequest; -import software.amazon.awssdk.core.checksums.ChecksumSpecs; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidation; import software.amazon.awssdk.core.checksums.SdkChecksum; -import software.amazon.awssdk.core.exception.RetryableException; import software.amazon.awssdk.core.interceptor.ExecutionAttribute; import software.amazon.awssdk.core.interceptor.ExecutionAttributes; -import software.amazon.awssdk.core.interceptor.SdkExecutionAttribute; +import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute; import software.amazon.awssdk.http.SdkHttpHeaders; -import software.amazon.awssdk.http.SdkHttpRequest; import software.amazon.awssdk.http.SdkHttpResponse; import software.amazon.awssdk.services.s3.S3Client; -import software.amazon.awssdk.services.s3.S3Configuration; import software.amazon.awssdk.services.s3.internal.handlers.AsyncChecksumValidationInterceptor; import software.amazon.awssdk.services.s3.internal.handlers.SyncChecksumValidationInterceptor; import software.amazon.awssdk.services.s3.model.ChecksumMode; import software.amazon.awssdk.services.s3.model.GetObjectRequest; -import software.amazon.awssdk.services.s3.model.PutObjectRequest; -import software.amazon.awssdk.services.s3.model.PutObjectResponse; -import software.amazon.awssdk.utils.BinaryUtils; -import software.amazon.awssdk.utils.StringUtils; -import software.amazon.awssdk.utils.internal.Base16Lower; /** * Class used by {@link SyncChecksumValidationInterceptor} and @@ -53,6 +41,8 @@ public final class ChecksumsEnabledValidator { public static final ExecutionAttribute CHECKSUM = new ExecutionAttribute<>("checksum"); + public static final ExecutionAttribute SKIP_MD5_TRAILING_CHECKSUM = new ExecutionAttribute<>( + "skipMd5TrailingChecksum"); private ChecksumsEnabledValidator() { } @@ -69,7 +59,7 @@ public static boolean getObjectChecksumEnabledPerRequest(SdkRequest request, ExecutionAttributes executionAttributes) { return request instanceof GetObjectRequest && ((GetObjectRequest) request).checksumMode() != ChecksumMode.ENABLED - && checksumEnabledPerConfig(executionAttributes); + && checksumEnabledPerConfigForGet(executionAttributes); } /** @@ -77,63 +67,23 @@ public static boolean getObjectChecksumEnabledPerRequest(SdkRequest request, * * @param request the request * @param responseHeaders the response headers + * @param executionAttributes the executionAttributes * @return true if trailing checksums is enabled, false otherwise */ - public static boolean getObjectChecksumEnabledPerResponse(SdkRequest request, SdkHttpHeaders responseHeaders) { - return request instanceof GetObjectRequest && checksumEnabledPerResponse(responseHeaders); - } - - /** - * Validates that checksums should be enabled based on {@link ClientType} and the presence of S3 specific headers. - * - * @param expectedClientType - The expected client type for enabling checksums - * @param executionAttributes - {@link ExecutionAttributes} to determine the actual client type - * @return If trailing checksums should be enabled for this request. - */ - public static boolean shouldRecordChecksum(SdkRequest sdkRequest, - ClientType expectedClientType, - ExecutionAttributes executionAttributes, - SdkHttpRequest httpRequest) { - if (!(sdkRequest instanceof PutObjectRequest)) { - return false; - } - - ClientType actualClientType = executionAttributes.getAttribute(SdkExecutionAttribute.CLIENT_TYPE); - - if (expectedClientType != actualClientType) { + public static boolean getObjectChecksumEnabledPerResponse(SdkRequest request, SdkHttpHeaders responseHeaders, + ExecutionAttributes executionAttributes) { + if (!(request instanceof GetObjectRequest)) { return false; } + ResponseChecksumValidation responseChecksumValidation = + executionAttributes.getAttribute(SdkInternalExecutionAttribute.RESPONSE_CHECKSUM_VALIDATION); - if (hasServerSideEncryptionHeader(httpRequest)) { - return false; - } - - //Checksum validation is done at Service side when HTTP Checksum algorithm attribute is set. - if (isHttpCheckSumValidationEnabled(executionAttributes, sdkRequest)) { + if (responseChecksumValidation != null && responseChecksumValidation == ResponseChecksumValidation.WHEN_REQUIRED) { return false; } - return checksumEnabledPerConfig(executionAttributes); - } - - private static boolean isHttpCheckSumValidationEnabled(ExecutionAttributes executionAttributes, SdkRequest request) { - if (isChecksumValueSpecified(request)) { - return true; - } - - Optional resolvedChecksum = - executionAttributes.getOptionalAttribute(SdkExecutionAttribute.RESOLVED_CHECKSUM_SPECS); - if (resolvedChecksum.isPresent()) { - ChecksumSpecs checksumSpecs = resolvedChecksum.get(); - return checksumSpecs.algorithm() != null; - } - return false; - } - - private static boolean isChecksumValueSpecified(SdkRequest request) { - return Stream.of("ChecksumCRC32", "ChecksumCRC32C", "ChecksumSHA1", "ChecksumSHA256") - .anyMatch(s -> request.getValueForField(s, String.class).isPresent()); + return checksumEnabledPerResponse(responseHeaders); } public static boolean responseChecksumIsValid(SdkHttpResponse httpResponse) { @@ -155,30 +105,6 @@ private static boolean hasServerSideEncryptionHeader(SdkHttpHeaders httpRequest) return false; } - /** - * Client side validation for {@link PutObjectRequest} - * - * @param response the response - * @param executionAttributes the execution attributes - */ - public static void validatePutObjectChecksum(PutObjectResponse response, ExecutionAttributes executionAttributes) { - SdkChecksum checksum = executionAttributes.getAttribute(CHECKSUM); - - if (response.eTag() != null) { - String contentMd5 = BinaryUtils.toBase64(checksum.getChecksumBytes()); - byte[] digest = BinaryUtils.fromBase64(contentMd5); - byte[] ssHash = Base16Lower.decode(StringUtils.replace(response.eTag(), "\"", "")); - - if (!Arrays.equals(digest, ssHash)) { - throw RetryableException.create( - String.format("Data read has a different checksum than expected. Was 0x%s, but expected 0x%s. " + - "This commonly means that the data was corrupted between the client and " + - "service. Note: Despite this error, the upload still completed and was persisted in S3.", - BinaryUtils.toHex(digest), BinaryUtils.toHex(ssHash))); - } - } - } - /** * Check the response header to see if the trailing checksum is enabled. * @@ -192,15 +118,20 @@ private static boolean checksumEnabledPerResponse(SdkHttpHeaders responseHeaders } /** - * Check the {@link S3Configuration#checksumValidationEnabled()} to see if the checksum is enabled. + * Check the {@code SdkExecutionAttribute.RESPONSE_CHECKSUM_VALIDATION} to see if the checksum is enabled for GET. * * @param executionAttributes the execution attributes - * @return true if the trailing checksum is enabled in the config, false otherwise. + * @return true if the checksum is enabled in the config, false otherwise. */ - private static boolean checksumEnabledPerConfig(ExecutionAttributes executionAttributes) { - S3Configuration serviceConfiguration = - (S3Configuration) executionAttributes.getAttribute(SdkExecutionAttribute.SERVICE_CONFIG); + private static boolean checksumEnabledPerConfigForGet(ExecutionAttributes executionAttributes) { + Boolean skipTrailingChecksum = executionAttributes.getAttribute(SKIP_MD5_TRAILING_CHECKSUM); + if (skipTrailingChecksum != null && skipTrailingChecksum) { + return false; + } + + ResponseChecksumValidation responseChecksumValidation = + executionAttributes.getAttribute(SdkInternalExecutionAttribute.RESPONSE_CHECKSUM_VALIDATION); - return serviceConfiguration == null || serviceConfiguration.checksumValidationEnabled(); + return responseChecksumValidation == ResponseChecksumValidation.WHEN_SUPPORTED; } } diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/client/S3AsyncClientDecorator.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/client/S3AsyncClientDecorator.java index fe2997a7d73c..90f07d42eace 100644 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/client/S3AsyncClientDecorator.java +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/client/S3AsyncClientDecorator.java @@ -19,6 +19,7 @@ import java.util.List; import java.util.function.Predicate; import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; import software.amazon.awssdk.core.client.config.SdkClientConfiguration; import software.amazon.awssdk.core.client.config.SdkClientOption; import software.amazon.awssdk.services.s3.S3AsyncClient; @@ -51,7 +52,9 @@ public S3AsyncClient decorate(S3AsyncClient base, isMultipartEnable(clientContextParams), client -> { MultipartConfiguration multipartConfiguration = clientContextParams.get(MULTIPART_CONFIGURATION_KEY); - return MultipartS3AsyncClient.create(client, multipartConfiguration); + boolean checksumEnabled = clientConfiguration.option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION) + == RequestChecksumCalculation.WHEN_SUPPORTED; + return MultipartS3AsyncClient.create(client, multipartConfiguration, checksumEnabled); })); return ConditionalDecorator.decorate(base, decorators); } diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/CrtChecksumUtils.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/CrtChecksumUtils.java index 212d7c4a3e39..c9b72e6c57b4 100644 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/CrtChecksumUtils.java +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/CrtChecksumUtils.java @@ -18,6 +18,8 @@ import java.util.List; import java.util.stream.Collectors; import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidation; import software.amazon.awssdk.core.interceptor.trait.HttpChecksum; import software.amazon.awssdk.crt.s3.ChecksumAlgorithm; import software.amazon.awssdk.crt.s3.ChecksumConfig; @@ -31,25 +33,29 @@ private CrtChecksumUtils() { } /** - * CRT checksum is only enabled for PUT_OBJECT and GET_OBJECT, for everything else, - * we rely on SDK checksum implementation + * Rely on CRT for checksums, we disable SDK checksum implementation in DefaultS3CrtAsyncClient */ public static ChecksumConfig checksumConfig(HttpChecksum httpChecksum, - S3MetaRequestOptions.MetaRequestType requestType, - boolean checksumValidationEnabled) { - if (checksumNotApplicable(requestType, httpChecksum)) { + S3MetaRequestOptions.MetaRequestType requestType, + RequestChecksumCalculation requestChecksumCalculation, + ResponseChecksumValidation responseChecksumValidation) { + if (httpChecksum == null) { return new ChecksumConfig(); } - ChecksumAlgorithm checksumAlgorithm = - crtChecksumAlgorithm(httpChecksum, requestType, checksumValidationEnabled); + ChecksumAlgorithm checksumAlgorithm = crtChecksumAlgorithm(httpChecksum, requestChecksumCalculation); - boolean validateChecksum = - validateResponseChecksum(httpChecksum, requestType, checksumValidationEnabled); + boolean validateChecksum = validateResponseChecksum(httpChecksum, requestType, responseChecksumValidation); - ChecksumConfig.ChecksumLocation checksumLocation = checksumAlgorithm == ChecksumAlgorithm.NONE ? - ChecksumConfig.ChecksumLocation.NONE : - ChecksumConfig.ChecksumLocation.TRAILER; + ChecksumConfig.ChecksumLocation checksumLocation; + + if (checksumAlgorithm == ChecksumAlgorithm.NONE) { + checksumLocation = ChecksumConfig.ChecksumLocation.NONE; + } else if (httpChecksum.isRequestStreaming()) { + checksumLocation = ChecksumConfig.ChecksumLocation.TRAILER; + } else { + checksumLocation = ChecksumConfig.ChecksumLocation.HEADER; + } return new ChecksumConfig() .withChecksumAlgorithm(checksumAlgorithm) @@ -58,15 +64,6 @@ public static ChecksumConfig checksumConfig(HttpChecksum httpChecksum, .withValidateChecksumAlgorithmList(checksumAlgorithmList(httpChecksum)); } - private static boolean checksumNotApplicable(S3MetaRequestOptions.MetaRequestType requestType, HttpChecksum httpChecksum) { - if (requestType != S3MetaRequestOptions.MetaRequestType.PUT_OBJECT && - requestType != S3MetaRequestOptions.MetaRequestType.GET_OBJECT) { - return true; - } - - return httpChecksum == null; - } - private static List checksumAlgorithmList(HttpChecksum httpChecksum) { if (httpChecksum.responseAlgorithms() == null) { return null; @@ -78,14 +75,13 @@ private static List checksumAlgorithmList(HttpChecksum httpCh } private static ChecksumAlgorithm crtChecksumAlgorithm(HttpChecksum httpChecksum, - S3MetaRequestOptions.MetaRequestType requestType, - boolean checksumValidationEnabled) { - if (requestType != S3MetaRequestOptions.MetaRequestType.PUT_OBJECT) { - return ChecksumAlgorithm.NONE; - } + RequestChecksumCalculation requestChecksumCalculation) { if (httpChecksum.requestAlgorithm() == null) { - return checksumValidationEnabled ? DEFAULT_CHECKSUM_ALGO : ChecksumAlgorithm.NONE; + if (requestChecksumCalculation == RequestChecksumCalculation.WHEN_REQUIRED) { + return ChecksumAlgorithm.NONE; + } + return DEFAULT_CHECKSUM_ALGO; } return toCrtChecksumAlgorithm(httpChecksum.requestAlgorithm()); @@ -97,16 +93,17 @@ private static ChecksumAlgorithm toCrtChecksumAlgorithm(String sdkChecksum) { /** * Only validate response checksum if this is getObject operation AND it supports checksum validation AND if either of the - * following applies: 1. checksum validation is enabled at request level via request validation mode OR 2. checksum validation - * is enabled at client level + * following applies: 1. checksum validation is enabled at request level via request validation mode OR 2. response checksum + * validation is enabled at client level */ private static boolean validateResponseChecksum(HttpChecksum httpChecksum, - S3MetaRequestOptions.MetaRequestType requestType, - boolean checksumValidationEnabled) { + S3MetaRequestOptions.MetaRequestType requestType, + ResponseChecksumValidation responseChecksumValidation) { if (requestType != S3MetaRequestOptions.MetaRequestType.GET_OBJECT) { return false; } - return checksumValidationEnabled || httpChecksum.requestValidationMode() != null; + return responseChecksumValidation == ResponseChecksumValidation.WHEN_SUPPORTED || + httpChecksum.requestValidationMode() != null; } } diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/DefaultS3CrtAsyncClient.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/DefaultS3CrtAsyncClient.java index 8f5ea1a1ec83..0ad7081770c4 100644 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/DefaultS3CrtAsyncClient.java +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/DefaultS3CrtAsyncClient.java @@ -17,10 +17,11 @@ import static software.amazon.awssdk.auth.signer.AwsSignerExecutionAttribute.SERVICE_SIGNING_NAME; import static software.amazon.awssdk.core.client.config.SdkAdvancedAsyncClientOption.FUTURE_COMPLETION_EXECUTOR; -import static software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute.AUTH_SCHEMES; import static software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute.SDK_HTTP_EXECUTION_ATTRIBUTES; import static software.amazon.awssdk.services.s3.internal.crt.S3InternalSdkHttpExecutionAttribute.HTTP_CHECKSUM; import static software.amazon.awssdk.services.s3.internal.crt.S3InternalSdkHttpExecutionAttribute.OPERATION_NAME; +import static software.amazon.awssdk.services.s3.internal.crt.S3InternalSdkHttpExecutionAttribute.REQUEST_CHECKSUM_CALCULATION; +import static software.amazon.awssdk.services.s3.internal.crt.S3InternalSdkHttpExecutionAttribute.RESPONSE_CHECKSUM_VALIDATION; import static software.amazon.awssdk.services.s3.internal.crt.S3InternalSdkHttpExecutionAttribute.SIGNING_NAME; import static software.amazon.awssdk.services.s3.internal.crt.S3InternalSdkHttpExecutionAttribute.SIGNING_REGION; import static software.amazon.awssdk.services.s3.internal.crt.S3InternalSdkHttpExecutionAttribute.USE_S3_EXPRESS_AUTH; @@ -40,6 +41,8 @@ import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; import software.amazon.awssdk.core.SdkRequest; import software.amazon.awssdk.core.checksums.ChecksumValidation; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidation; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption; import software.amazon.awssdk.core.interceptor.Context; @@ -59,15 +62,14 @@ import software.amazon.awssdk.services.s3.DelegatingS3AsyncClient; import software.amazon.awssdk.services.s3.S3AsyncClient; import software.amazon.awssdk.services.s3.S3AsyncClientBuilder; -import software.amazon.awssdk.services.s3.S3Configuration; import software.amazon.awssdk.services.s3.S3CrtAsyncClientBuilder; import software.amazon.awssdk.services.s3.crt.S3CrtHttpConfiguration; import software.amazon.awssdk.services.s3.crt.S3CrtRetryConfiguration; +import software.amazon.awssdk.services.s3.internal.checksums.ChecksumsEnabledValidator; import software.amazon.awssdk.services.s3.internal.multipart.CopyObjectHelper; import software.amazon.awssdk.services.s3.internal.s3express.S3ExpressUtils; import software.amazon.awssdk.services.s3.model.CopyObjectRequest; import software.amazon.awssdk.services.s3.model.CopyObjectResponse; -import software.amazon.awssdk.services.s3.model.GetObjectRequest; import software.amazon.awssdk.services.s3.model.PutObjectRequest; import software.amazon.awssdk.services.s3.model.PutObjectResponse; import software.amazon.awssdk.utils.CollectionUtils; @@ -115,6 +117,7 @@ private static S3AsyncClient initializeS3AsyncClient(DefaultS3CrtClientBuilder b .putAdvancedOption(SdkAdvancedClientOption.SIGNER, new NoOpSigner()) .putExecutionAttribute(SdkExecutionAttribute.HTTP_RESPONSE_CHECKSUM_VALIDATION, ChecksumValidation.FORCE_SKIP) + .putExecutionAttribute(ChecksumsEnabledValidator.SKIP_MD5_TRAILING_CHECKSUM, true) .retryStrategy(AwsRetryStrategy.doNotRetry()) .addExecutionInterceptor(new ValidateRequestInterceptor()) .addExecutionInterceptor(new AttachHttpAttributesExecutionInterceptor()); @@ -123,32 +126,53 @@ private static S3AsyncClient initializeS3AsyncClient(DefaultS3CrtClientBuilder b builder.executionInterceptors.forEach(overrideConfigurationBuilder::addExecutionInterceptor); } + DefaultS3CrtClientBuilder finalBuilder = resolveChecksumConfiguration(builder); + S3AsyncClientBuilder s3AsyncClientBuilder = S3AsyncClient.builder() - // Disable checksum for streaming operations, it is handled in - // CRT. Checksumming for non-streaming - // operations is still handled in HttpChecksumStage - .serviceConfiguration(S3Configuration.builder() - .checksumValidationEnabled(false) - .build()) - .region(builder.region) - .endpointOverride(builder.endpointOverride) - .credentialsProvider(builder.credentialsProvider) + .requestChecksumCalculation(finalBuilder.requestChecksumCalculation) + .responseChecksumValidation(finalBuilder.responseChecksumValidation) + .region(finalBuilder.region) + .endpointOverride(finalBuilder.endpointOverride) + .credentialsProvider(finalBuilder.credentialsProvider) .overrideConfiguration(overrideConfigurationBuilder.build()) - .accelerate(builder.accelerate) - .forcePathStyle(builder.forcePathStyle) - .crossRegionAccessEnabled(builder.crossRegionAccessEnabled) + .accelerate(finalBuilder.accelerate) + .forcePathStyle(finalBuilder.forcePathStyle) + .crossRegionAccessEnabled(finalBuilder.crossRegionAccessEnabled) .putAuthScheme(new CrtS3ExpressNoOpAuthScheme()) - .httpClientBuilder(initializeS3CrtAsyncHttpClient(builder)); + .httpClientBuilder(initializeS3CrtAsyncHttpClient(finalBuilder)); - if (builder.futureCompletionExecutor != null) { + if (finalBuilder.futureCompletionExecutor != null) { s3AsyncClientBuilder.asyncConfiguration(b -> b.advancedOption(FUTURE_COMPLETION_EXECUTOR, - builder.futureCompletionExecutor)); + finalBuilder.futureCompletionExecutor)); } return s3AsyncClientBuilder.build(); } + private static DefaultS3CrtClientBuilder resolveChecksumConfiguration(DefaultS3CrtClientBuilder builder) { + Boolean checksumEnabledValidation = builder.checksumValidationEnabled; + RequestChecksumCalculation requestChecksumCalculation = builder.requestChecksumCalculation; + ResponseChecksumValidation responseChecksumValidation = builder.responseChecksumValidation; + + if (checksumEnabledValidation != null) { + Validate.validState(requestChecksumCalculation == null && responseChecksumValidation == null, + "Checksum behavior has been configured on the S3CrtAsyncClientBuilder using the deprecated " + + "checksumEnabledValidation() AND one or both of requestChecksumCalculation() and " + + "responseChecksumValidation()"); + if (checksumEnabledValidation) { + requestChecksumCalculation = RequestChecksumCalculation.WHEN_SUPPORTED; + responseChecksumValidation = ResponseChecksumValidation.WHEN_SUPPORTED; + } else { + requestChecksumCalculation = RequestChecksumCalculation.WHEN_REQUIRED; + responseChecksumValidation = ResponseChecksumValidation.WHEN_REQUIRED; + } + } + + return builder.requestChecksumCalculation(requestChecksumCalculation) + .responseChecksumValidation(responseChecksumValidation); + } + private static S3CrtAsyncHttpClient.Builder initializeS3CrtAsyncHttpClient(DefaultS3CrtClientBuilder builder) { validateCrtInClassPath(); Validate.isPositiveOrNull(builder.readBufferSizeInBytes, "initialReadBufferSizeInBytes"); @@ -159,7 +183,6 @@ private static S3CrtAsyncHttpClient.Builder initializeS3CrtAsyncHttpClient(Defau S3NativeClientConfiguration.Builder nativeClientBuilder = S3NativeClientConfiguration.builder() - .checksumValidationEnabled(builder.checksumValidationEnabled) .targetThroughputInGbps(builder.targetThroughputInGbps) .partSizeInBytes(builder.minimalPartSizeInBytes) .maxConcurrency(builder.maxConcurrency) @@ -187,11 +210,12 @@ public static final class DefaultS3CrtClientBuilder implements S3CrtAsyncClientB private Region region; private Long minimalPartSizeInBytes; private Double targetThroughputInGbps; - private Long maxNativeMemoryLimitInBytes -; + private Long maxNativeMemoryLimitInBytes; private Integer maxConcurrency; private URI endpointOverride; private Boolean checksumValidationEnabled; + private RequestChecksumCalculation requestChecksumCalculation; + private ResponseChecksumValidation responseChecksumValidation; private S3CrtHttpConfiguration httpConfiguration; private Boolean accelerate; private Boolean forcePathStyle; @@ -203,80 +227,92 @@ public static final class DefaultS3CrtClientBuilder implements S3CrtAsyncClientB private Executor futureCompletionExecutor; @Override - public S3CrtAsyncClientBuilder credentialsProvider( + public DefaultS3CrtClientBuilder credentialsProvider( IdentityProvider credentialsProvider) { this.credentialsProvider = credentialsProvider; return this; } @Override - public S3CrtAsyncClientBuilder region(Region region) { + public DefaultS3CrtClientBuilder region(Region region) { this.region = region; return this; } @Override - public S3CrtAsyncClientBuilder minimumPartSizeInBytes(Long partSizeBytes) { + public DefaultS3CrtClientBuilder minimumPartSizeInBytes(Long partSizeBytes) { this.minimalPartSizeInBytes = partSizeBytes; return this; } @Override - public S3CrtAsyncClientBuilder targetThroughputInGbps(Double targetThroughputInGbps) { + public DefaultS3CrtClientBuilder targetThroughputInGbps(Double targetThroughputInGbps) { this.targetThroughputInGbps = targetThroughputInGbps; return this; } @Override - public S3CrtAsyncClientBuilder maxNativeMemoryLimitInBytes(Long maxNativeMemoryLimitInBytes) { + public DefaultS3CrtClientBuilder maxNativeMemoryLimitInBytes(Long maxNativeMemoryLimitInBytes) { this.maxNativeMemoryLimitInBytes = maxNativeMemoryLimitInBytes; return this; } @Override - public S3CrtAsyncClientBuilder maxConcurrency(Integer maxConcurrency) { + public DefaultS3CrtClientBuilder maxConcurrency(Integer maxConcurrency) { this.maxConcurrency = maxConcurrency; return this; } @Override - public S3CrtAsyncClientBuilder endpointOverride(URI endpointOverride) { + public DefaultS3CrtClientBuilder endpointOverride(URI endpointOverride) { this.endpointOverride = endpointOverride; return this; } @Override - public S3CrtAsyncClientBuilder checksumValidationEnabled(Boolean checksumValidationEnabled) { + public DefaultS3CrtClientBuilder checksumValidationEnabled(Boolean checksumValidationEnabled) { this.checksumValidationEnabled = checksumValidationEnabled; return this; } @Override - public S3CrtAsyncClientBuilder initialReadBufferSizeInBytes(Long readBufferSizeInBytes) { + public DefaultS3CrtClientBuilder requestChecksumCalculation(RequestChecksumCalculation requestChecksumCalculation) { + this.requestChecksumCalculation = requestChecksumCalculation; + return this; + } + + @Override + public DefaultS3CrtClientBuilder responseChecksumValidation(ResponseChecksumValidation responseChecksumValidation) { + this.responseChecksumValidation = responseChecksumValidation; + return this; + } + + @Override + public DefaultS3CrtClientBuilder initialReadBufferSizeInBytes(Long readBufferSizeInBytes) { this.readBufferSizeInBytes = readBufferSizeInBytes; return this; } @Override - public S3CrtAsyncClientBuilder httpConfiguration(S3CrtHttpConfiguration configuration) { + public DefaultS3CrtClientBuilder httpConfiguration(S3CrtHttpConfiguration configuration) { this.httpConfiguration = configuration; return this; } @Override - public S3CrtAsyncClientBuilder accelerate(Boolean accelerate) { + public DefaultS3CrtClientBuilder accelerate(Boolean accelerate) { this.accelerate = accelerate; return this; } @Override - public S3CrtAsyncClientBuilder forcePathStyle(Boolean forcePathStyle) { + public DefaultS3CrtClientBuilder forcePathStyle(Boolean forcePathStyle) { this.forcePathStyle = forcePathStyle; return this; } @SdkTestInternalApi - S3CrtAsyncClientBuilder addExecutionInterceptor(ExecutionInterceptor executionInterceptor) { + DefaultS3CrtClientBuilder addExecutionInterceptor(ExecutionInterceptor executionInterceptor) { if (executionInterceptors == null) { this.executionInterceptors = new ArrayList<>(); } @@ -285,25 +321,25 @@ S3CrtAsyncClientBuilder addExecutionInterceptor(ExecutionInterceptor executionIn } @Override - public S3CrtAsyncClientBuilder retryConfiguration(S3CrtRetryConfiguration retryConfiguration) { + public DefaultS3CrtClientBuilder retryConfiguration(S3CrtRetryConfiguration retryConfiguration) { this.retryConfiguration = retryConfiguration; return this; } @Override - public S3CrtAsyncClientBuilder crossRegionAccessEnabled(Boolean crossRegionAccessEnabled) { + public DefaultS3CrtClientBuilder crossRegionAccessEnabled(Boolean crossRegionAccessEnabled) { this.crossRegionAccessEnabled = crossRegionAccessEnabled; return this; } @Override - public S3CrtAsyncClientBuilder thresholdInBytes(Long thresholdInBytes) { + public DefaultS3CrtClientBuilder thresholdInBytes(Long thresholdInBytes) { this.thresholdInBytes = thresholdInBytes; return this; } @Override - public S3CrtAsyncClientBuilder futureCompletionExecutor(Executor futureCompletionExecutor) { + public DefaultS3CrtClientBuilder futureCompletionExecutor(Executor futureCompletionExecutor) { this.futureCompletionExecutor = futureCompletionExecutor; return this; } @@ -316,14 +352,6 @@ public S3CrtAsyncClient build() { private static final class AttachHttpAttributesExecutionInterceptor implements ExecutionInterceptor { - @Override - public void beforeExecution(Context.BeforeExecution context, ExecutionAttributes executionAttributes) { - // Hack to disable new SRA path because we still rely on HttpChecksumStage to perform checksum for - // non-streaming operation. - // TODO: remove this once CRT supports checksum for default requests - executionAttributes.putAttribute(AUTH_SCHEMES, null); - } - @Override public void afterMarshalling(Context.AfterMarshalling context, ExecutionAttributes executionAttributes) { @@ -343,24 +371,19 @@ public void afterMarshalling(Context.AfterMarshalling context, executionAttributes.getAttribute(OBJECT_FILE_PATH)) .put(USE_S3_EXPRESS_AUTH, S3ExpressUtils.useS3ExpressAuthScheme(executionAttributes)) .put(SIGNING_NAME, executionAttributes.getAttribute(SERVICE_SIGNING_NAME)) + .put(REQUEST_CHECKSUM_CALCULATION, + executionAttributes.getAttribute(SdkInternalExecutionAttribute.REQUEST_CHECKSUM_CALCULATION)) + .put(RESPONSE_CHECKSUM_VALIDATION, + executionAttributes.getAttribute(SdkInternalExecutionAttribute.RESPONSE_CHECKSUM_VALIDATION)) .build(); - // For putObject and getObject, we rely on CRT to perform checksum validation - disableChecksumForPutAndGet(context, executionAttributes); + // We rely on CRT to perform checksum validation, disable SDK flexible checksum implementation + executionAttributes.putAttribute(SdkInternalExecutionAttribute.HTTP_CHECKSUM, null); + executionAttributes.putAttribute(SdkExecutionAttribute.RESOLVED_CHECKSUM_SPECS, null); executionAttributes.putAttribute(SDK_HTTP_EXECUTION_ATTRIBUTES, attributes); } - - private static void disableChecksumForPutAndGet(Context.AfterMarshalling context, - ExecutionAttributes executionAttributes) { - if (context.request() instanceof PutObjectRequest || context.request() instanceof GetObjectRequest) { - // TODO: we can remove this once we are fully on SRA signing AND CRT supports checksum for default requests - // Clear HTTP_CHECKSUM and RESOLVED_CHECKSUM_SPECS to disable SDK flexible checksum implementation. - executionAttributes.putAttribute(SdkInternalExecutionAttribute.HTTP_CHECKSUM, null); - executionAttributes.putAttribute(SdkExecutionAttribute.RESOLVED_CHECKSUM_SPECS, null); - } - } } private static final class ValidateRequestInterceptor implements ExecutionInterceptor { diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/S3CrtAsyncHttpClient.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/S3CrtAsyncHttpClient.java index da1095d9edea..665b4d2213c4 100644 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/S3CrtAsyncHttpClient.java +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/S3CrtAsyncHttpClient.java @@ -22,6 +22,8 @@ import static software.amazon.awssdk.services.s3.internal.crt.S3InternalSdkHttpExecutionAttribute.HTTP_CHECKSUM; import static software.amazon.awssdk.services.s3.internal.crt.S3InternalSdkHttpExecutionAttribute.OBJECT_FILE_PATH; import static software.amazon.awssdk.services.s3.internal.crt.S3InternalSdkHttpExecutionAttribute.OPERATION_NAME; +import static software.amazon.awssdk.services.s3.internal.crt.S3InternalSdkHttpExecutionAttribute.REQUEST_CHECKSUM_CALCULATION; +import static software.amazon.awssdk.services.s3.internal.crt.S3InternalSdkHttpExecutionAttribute.RESPONSE_CHECKSUM_VALIDATION; import static software.amazon.awssdk.services.s3.internal.crt.S3InternalSdkHttpExecutionAttribute.SIGNING_NAME; import static software.amazon.awssdk.services.s3.internal.crt.S3InternalSdkHttpExecutionAttribute.SIGNING_REGION; import static software.amazon.awssdk.services.s3.internal.crt.S3InternalSdkHttpExecutionAttribute.USE_S3_EXPRESS_AUTH; @@ -36,6 +38,8 @@ import java.util.concurrent.CompletableFuture; import software.amazon.awssdk.annotations.SdkInternalApi; import software.amazon.awssdk.annotations.SdkTestInternalApi; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidation; import software.amazon.awssdk.core.interceptor.trait.HttpChecksum; import software.amazon.awssdk.crt.auth.signing.AwsSigningConfig; import software.amazon.awssdk.crt.http.HttpHeader; @@ -140,12 +144,18 @@ public CompletableFuture execute(AsyncExecuteRequest asyncRequest) { String operationName = asyncRequest.httpExecutionAttributes().getAttribute(OPERATION_NAME); S3MetaRequestOptions.MetaRequestType requestType = requestType(operationName); - HttpChecksum httpChecksum = httpExecutionAttributes.getAttribute(HTTP_CHECKSUM); ResumeToken resumeToken = httpExecutionAttributes.getAttribute(CRT_PAUSE_RESUME_TOKEN); Region signingRegion = httpExecutionAttributes.getAttribute(SIGNING_REGION); Path requestFilePath = httpExecutionAttributes.getAttribute(OBJECT_FILE_PATH); - ChecksumConfig checksumConfig = - checksumConfig(httpChecksum, requestType, s3NativeClientConfiguration.checksumValidationEnabled()); + + HttpChecksum httpChecksum = httpExecutionAttributes.getAttribute(HTTP_CHECKSUM); + RequestChecksumCalculation requestChecksumCalculation = + httpExecutionAttributes.getAttribute(REQUEST_CHECKSUM_CALCULATION); + ResponseChecksumValidation responseChecksumValidation = + httpExecutionAttributes.getAttribute(RESPONSE_CHECKSUM_VALIDATION); + ChecksumConfig checksumConfig = checksumConfig(httpChecksum, requestType, requestChecksumCalculation, + responseChecksumValidation); + URI endpoint = getEndpoint(uri); AwsSigningConfig signingConfig = awsSigningConfig(signingRegion, httpExecutionAttributes); diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/S3InternalSdkHttpExecutionAttribute.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/S3InternalSdkHttpExecutionAttribute.java index 62c2b3a6b3e0..072bcd1fb608 100644 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/S3InternalSdkHttpExecutionAttribute.java +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/S3InternalSdkHttpExecutionAttribute.java @@ -17,6 +17,8 @@ import java.nio.file.Path; import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidation; import software.amazon.awssdk.core.interceptor.trait.HttpChecksum; import software.amazon.awssdk.crt.s3.ResumeToken; import software.amazon.awssdk.http.SdkHttpExecutionAttribute; @@ -49,6 +51,12 @@ public final class S3InternalSdkHttpExecutionAttribute extends SdkHttpExecuti public static final S3InternalSdkHttpExecutionAttribute USE_S3_EXPRESS_AUTH = new S3InternalSdkHttpExecutionAttribute<>(Boolean.class); + public static final S3InternalSdkHttpExecutionAttribute REQUEST_CHECKSUM_CALCULATION = + new S3InternalSdkHttpExecutionAttribute<>(RequestChecksumCalculation.class); + + public static final S3InternalSdkHttpExecutionAttribute RESPONSE_CHECKSUM_VALIDATION = + new S3InternalSdkHttpExecutionAttribute<>(ResponseChecksumValidation.class); + private S3InternalSdkHttpExecutionAttribute(Class valueClass) { super(valueClass); } diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/S3NativeClientConfiguration.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/S3NativeClientConfiguration.java index e0ee6199c23e..4925a708c818 100644 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/S3NativeClientConfiguration.java +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/crt/S3NativeClientConfiguration.java @@ -56,7 +56,6 @@ public class S3NativeClientConfiguration implements SdkAutoCloseable { private final double targetThroughputInGbps; private final int maxConcurrency; private final URI endpointOverride; - private final boolean checksumValidationEnabled; private final Long readBufferSizeInBytes; private final TlsContext tlsContext; private final TlsContextOptions clientTlsContextOptions; @@ -101,7 +100,6 @@ public S3NativeClientConfiguration(Builder builder) { this.endpointOverride = builder.endpointOverride; - this.checksumValidationEnabled = builder.checksumValidationEnabled == null || builder.checksumValidationEnabled; this.readBufferSizeInBytes = builder.readBufferSizeInBytes == null ? partSizeInBytes * 10 : builder.readBufferSizeInBytes; @@ -191,10 +189,6 @@ public URI endpointOverride() { return endpointOverride; } - public boolean checksumValidationEnabled() { - return checksumValidationEnabled; - } - public Long readBufferSizeInBytes() { return readBufferSizeInBytes; } @@ -215,7 +209,6 @@ public static final class Builder { private Double targetThroughputInGbps; private Integer maxConcurrency; private URI endpointOverride; - private Boolean checksumValidationEnabled; private S3CrtHttpConfiguration httpConfiguration; private StandardRetryOptions standardRetryOptions; @@ -260,14 +253,6 @@ public Builder endpointOverride(URI endpointOverride) { return this; } - /** - * Option to disable checksum validation of an object stored in S3. - */ - public Builder checksumValidationEnabled(Boolean checksumValidationEnabled) { - this.checksumValidationEnabled = checksumValidationEnabled; - return this; - } - public S3NativeClientConfiguration build() { return new S3NativeClientConfiguration(this); } diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/handlers/AsyncChecksumValidationInterceptor.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/handlers/AsyncChecksumValidationInterceptor.java index 3e9854e3b8f6..b6f4e4114d2d 100644 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/handlers/AsyncChecksumValidationInterceptor.java +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/handlers/AsyncChecksumValidationInterceptor.java @@ -15,54 +15,28 @@ package software.amazon.awssdk.services.s3.internal.handlers; -import static software.amazon.awssdk.core.ClientType.ASYNC; import static software.amazon.awssdk.services.s3.internal.checksums.ChecksumConstant.CONTENT_LENGTH_HEADER; import static software.amazon.awssdk.services.s3.internal.checksums.ChecksumsEnabledValidator.CHECKSUM; import static software.amazon.awssdk.services.s3.internal.checksums.ChecksumsEnabledValidator.getObjectChecksumEnabledPerResponse; -import static software.amazon.awssdk.services.s3.internal.checksums.ChecksumsEnabledValidator.responseChecksumIsValid; -import static software.amazon.awssdk.services.s3.internal.checksums.ChecksumsEnabledValidator.shouldRecordChecksum; -import static software.amazon.awssdk.services.s3.internal.checksums.ChecksumsEnabledValidator.validatePutObjectChecksum; import java.nio.ByteBuffer; import java.util.Optional; import org.reactivestreams.Publisher; import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.core.async.AsyncRequestBody; import software.amazon.awssdk.core.checksums.Md5Checksum; import software.amazon.awssdk.core.checksums.SdkChecksum; import software.amazon.awssdk.core.interceptor.Context; -import software.amazon.awssdk.core.interceptor.ExecutionAttribute; import software.amazon.awssdk.core.interceptor.ExecutionAttributes; import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; -import software.amazon.awssdk.services.s3.internal.checksums.ChecksumCalculatingAsyncRequestBody; import software.amazon.awssdk.services.s3.internal.checksums.S3ChecksumValidatingPublisher; -import software.amazon.awssdk.services.s3.model.PutObjectResponse; @SdkInternalApi public final class AsyncChecksumValidationInterceptor implements ExecutionInterceptor { - private static ExecutionAttribute ASYNC_RECORDING_CHECKSUM = new ExecutionAttribute<>("asyncRecordingChecksum"); - - @Override - public Optional modifyAsyncHttpContent(Context.ModifyHttpRequest context, - ExecutionAttributes executionAttributes) { - boolean shouldRecordChecksum = shouldRecordChecksum(context.request(), ASYNC, executionAttributes, context.httpRequest()); - - if (shouldRecordChecksum && context.asyncRequestBody().isPresent()) { - SdkChecksum checksum = new Md5Checksum(); - executionAttributes.putAttribute(ASYNC_RECORDING_CHECKSUM, true); - executionAttributes.putAttribute(CHECKSUM, checksum); - return Optional.of(new ChecksumCalculatingAsyncRequestBody(context.httpRequest(), - context.asyncRequestBody().get(), - checksum)); - } - - return context.asyncRequestBody(); - } @Override public Optional> modifyAsyncHttpResponseContent(Context.ModifyHttpResponse context, ExecutionAttributes executionAttributes) { - if (getObjectChecksumEnabledPerResponse(context.request(), context.httpResponse()) + if (getObjectChecksumEnabledPerResponse(context.request(), context.httpResponse(), executionAttributes) && context.responsePublisher().isPresent()) { long contentLength = context.httpResponse() .firstMatchingHeader(CONTENT_LENGTH_HEADER) @@ -78,14 +52,4 @@ public Optional> modifyAsyncHttpResponseContent(Context.Mo return context.responsePublisher(); } - - @Override - public void afterUnmarshalling(Context.AfterUnmarshalling context, ExecutionAttributes executionAttributes) { - boolean recordingChecksum = Boolean.TRUE.equals(executionAttributes.getAttribute(ASYNC_RECORDING_CHECKSUM)); - boolean responseChecksumIsValid = responseChecksumIsValid(context.httpResponse()); - - if (recordingChecksum && responseChecksumIsValid) { - validatePutObjectChecksum((PutObjectResponse) context.response(), executionAttributes); - } - } } diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/handlers/EnableTrailingChecksumInterceptor.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/handlers/EnableTrailingChecksumInterceptor.java index 956444e71942..098ecff45f5f 100644 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/handlers/EnableTrailingChecksumInterceptor.java +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/handlers/EnableTrailingChecksumInterceptor.java @@ -81,7 +81,7 @@ public SdkResponse modifyResponse(Context.ModifyResponse context, ExecutionAttri SdkResponse response = context.response(); SdkHttpResponse httpResponse = context.httpResponse(); - if (getObjectChecksumEnabledPerResponse(context.request(), httpResponse)) { + if (getObjectChecksumEnabledPerResponse(context.request(), httpResponse, executionAttributes)) { GetObjectResponse getResponse = (GetObjectResponse) response; Long contentLength = getResponse.contentLength(); Validate.notNull(contentLength, "Service returned null 'Content-Length'."); diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/handlers/GetObjectInterceptor.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/handlers/GetObjectInterceptor.java index 5357dff9964f..7e13f6b97473 100644 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/handlers/GetObjectInterceptor.java +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/handlers/GetObjectInterceptor.java @@ -18,15 +18,14 @@ import java.util.Optional; import java.util.regex.Pattern; import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.checksums.spi.ChecksumAlgorithm; import software.amazon.awssdk.core.SdkResponse; -import software.amazon.awssdk.core.checksums.Algorithm; import software.amazon.awssdk.core.checksums.ChecksumSpecs; import software.amazon.awssdk.core.checksums.ChecksumValidation; import software.amazon.awssdk.core.interceptor.Context; import software.amazon.awssdk.core.interceptor.ExecutionAttributes; import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; import software.amazon.awssdk.core.interceptor.SdkExecutionAttribute; -import software.amazon.awssdk.core.internal.util.HttpChecksumResolver; import software.amazon.awssdk.core.internal.util.HttpChecksumUtils; import software.amazon.awssdk.http.SdkHttpResponse; import software.amazon.awssdk.services.s3.model.GetObjectRequest; @@ -47,10 +46,10 @@ public void afterTransmission(Context.AfterTransmission context, ExecutionAttrib if (!(context.request() instanceof GetObjectRequest)) { return; } - ChecksumSpecs resolvedChecksumSpecs = HttpChecksumResolver.getResolvedChecksumSpecs(executionAttributes); + ChecksumSpecs resolvedChecksumSpecs = executionAttributes.getAttribute(SdkExecutionAttribute.RESOLVED_CHECKSUM_SPECS); if (HttpChecksumUtils.isHttpChecksumValidationEnabled(resolvedChecksumSpecs)) { - Pair algorithmChecksumValuePair = + Pair algorithmChecksumValuePair = HttpChecksumUtils.getAlgorithmChecksumValuePair(context.httpResponse(), resolvedChecksumSpecs); // Multipart uploaded objects the received Checksum is the checksum of checksums of individual parts and part number. diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/handlers/S3ExpressChecksumInterceptor.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/handlers/S3ExpressChecksumInterceptor.java deleted file mode 100644 index 2cd3401f7487..000000000000 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/handlers/S3ExpressChecksumInterceptor.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -package software.amazon.awssdk.services.s3.internal.handlers; - -import static software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute.SELECTED_AUTH_SCHEME; - -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.stream.Stream; -import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.checksums.DefaultChecksumAlgorithm; -import software.amazon.awssdk.checksums.spi.ChecksumAlgorithm; -import software.amazon.awssdk.core.SdkRequest; -import software.amazon.awssdk.core.SelectedAuthScheme; -import software.amazon.awssdk.core.checksums.Algorithm; -import software.amazon.awssdk.core.checksums.ChecksumSpecs; -import software.amazon.awssdk.core.interceptor.Context; -import software.amazon.awssdk.core.interceptor.ExecutionAttributes; -import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; -import software.amazon.awssdk.core.interceptor.SdkExecutionAttribute; -import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute; -import software.amazon.awssdk.core.interceptor.trait.HttpChecksum; -import software.amazon.awssdk.http.SdkHttpRequest; -import software.amazon.awssdk.http.auth.aws.signer.AwsV4FamilyHttpSigner; -import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption; -import software.amazon.awssdk.identity.spi.Identity; -import software.amazon.awssdk.services.s3.internal.s3express.S3ExpressUtils; -import software.amazon.awssdk.services.s3.model.PutObjectRequest; - -/** - * S3Express has different checksum requirements compared to standard S3 calls. This interceptor modifies checksums only - * for S3Express calls. - *

    - * Checksums can be configured through model traits on operations as follows - *

      - *
    1. httpChecksumRequired - older setting used in S3Control -> not allowed
    2. - *
    3. httpChecksum is set and required -> always add CRC32 checksum even if algorithm is not specified.
    4. - *
    5. httpChecksum is set but not required -> if algorithm is not specified, behavior differs
    6. - *
    - *

    Note that, if httpChecksum is not present, no checksum may be calculated. PutBucketPolicy, DeleteObjects are examples - * of operations that require checksums. PutObject, UploadPart are examples of operations that do not require checksums. - *

    - * Special cases - *

      - *
    • PutObject -> always calculate CRC32
    • - *
    • UploadPart -> do not calculate CRC32 if algorithm is missing, unless TM is used
    • - *
    -*/ -@SdkInternalApi -public final class S3ExpressChecksumInterceptor implements ExecutionInterceptor { - - @Override - public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) { - SdkRequest request = context.request(); - if (!S3ExpressUtils.useS3Express(executionAttributes)) { - return request; - } - Optional resolvedChecksumSpecs = - executionAttributes.getOptionalAttribute(SdkExecutionAttribute.RESOLVED_CHECKSUM_SPECS); - HttpChecksum httpChecksumTraitInOperation = executionAttributes.getAttribute(SdkInternalExecutionAttribute.HTTP_CHECKSUM); - if (!resolvedChecksumSpecs.isPresent()) { - if (httpChecksumTraitInOperation != null) { - throw new IllegalStateException("S3Express: illegal checksum parameter combination"); - } - return request; - } - ChecksumSpecs checksumSpecs = resolvedChecksumSpecs.get(); - if (checksumSpecs.algorithm() != null || requestContainsUserCalculatedChecksum(request)) { - return request; - } - if (shouldAlwaysAddChecksum(checksumSpecs, request)) { - SelectedAuthScheme authScheme = - (SelectedAuthScheme) getAuthScheme(executionAttributes); - AuthSchemeOption authSchemeOption = - authScheme.authSchemeOption().copy(o -> o.putSignerProperty(AwsV4FamilyHttpSigner.CHECKSUM_ALGORITHM, - DefaultChecksumAlgorithm.CRC32)); - SelectedAuthScheme authSchemeWithCrc32 = new SelectedAuthScheme<>(authScheme.identity(), - authScheme.signer(), - authSchemeOption); - executionAttributes.putAttribute(SELECTED_AUTH_SCHEME, authSchemeWithCrc32); - } - return request; - } - - private boolean requestContainsUserCalculatedChecksum(SdkRequest request) { - return Stream.of("ChecksumCRC32", "ChecksumCRC32C", "ChecksumSHA1", "ChecksumSHA256") - .anyMatch(s -> request.getValueForField(s, String.class).isPresent()); - } - - private boolean shouldAlwaysAddChecksum(ChecksumSpecs checksumSpecs, SdkRequest request) { - return checksumSpecs.isRequestChecksumRequired() || request instanceof PutObjectRequest; - } - - @Override - public SdkHttpRequest modifyHttpRequest(Context.ModifyHttpRequest context, ExecutionAttributes executionAttributes) { - // TODO (s3express) - possibly migrate elsewhere - // if algorithm is set in modifyRequest(), the marshaller won't add this header, since it checks in the request object - SdkHttpRequest sdkHttpRequest = context.httpRequest(); - SelectedAuthScheme selectedAuthScheme = getAuthScheme(executionAttributes); - ChecksumAlgorithm algorithm = - selectedAuthScheme.authSchemeOption().signerProperty(AwsV4FamilyHttpSigner.CHECKSUM_ALGORITHM); - if (Objects.equals(algorithm, DefaultChecksumAlgorithm.CRC32)) { - Optional headerValue = getFirstNestedValue(sdkHttpRequest.headers(), "x-amz-sdk-checksum-algorithm"); - if (!headerValue.isPresent()) { - return sdkHttpRequest.toBuilder().appendHeader("x-amz-sdk-checksum-algorithm", Algorithm.CRC32.name()).build(); - } - } - return sdkHttpRequest; - } - - private SelectedAuthScheme getAuthScheme(ExecutionAttributes executionAttributes) { - SelectedAuthScheme selectedAuthScheme = executionAttributes.getAttribute(SELECTED_AUTH_SCHEME); - if (selectedAuthScheme == null) { - throw new IllegalStateException("Auth scheme should not be null"); - } - return selectedAuthScheme; - } - - private Optional getFirstNestedValue(Map> map, String key) { - List value = map.get(key); - if (value == null) { - return Optional.empty(); - } - String firstValue = value.get(0); - return firstValue.isEmpty() ? Optional.empty() : Optional.of(firstValue); - } -} diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/handlers/SyncChecksumValidationInterceptor.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/handlers/SyncChecksumValidationInterceptor.java index c599fb1c3605..0147c2a9971f 100644 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/handlers/SyncChecksumValidationInterceptor.java +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/handlers/SyncChecksumValidationInterceptor.java @@ -15,14 +15,8 @@ package software.amazon.awssdk.services.s3.internal.handlers; -import static software.amazon.awssdk.core.ClientType.SYNC; import static software.amazon.awssdk.services.s3.internal.checksums.ChecksumConstant.CONTENT_LENGTH_HEADER; -import static software.amazon.awssdk.services.s3.internal.checksums.ChecksumsEnabledValidator.CHECKSUM; import static software.amazon.awssdk.services.s3.internal.checksums.ChecksumsEnabledValidator.getObjectChecksumEnabledPerResponse; -import static software.amazon.awssdk.services.s3.internal.checksums.ChecksumsEnabledValidator.responseChecksumIsValid; -import static software.amazon.awssdk.services.s3.internal.checksums.ChecksumsEnabledValidator.shouldRecordChecksum; -import static software.amazon.awssdk.services.s3.internal.checksums.ChecksumsEnabledValidator.validatePutObjectChecksum; -import static software.amazon.awssdk.utils.FunctionalUtils.invokeSafely; import java.io.InputStream; import java.util.Optional; @@ -30,45 +24,17 @@ import software.amazon.awssdk.core.checksums.Md5Checksum; import software.amazon.awssdk.core.checksums.SdkChecksum; import software.amazon.awssdk.core.interceptor.Context; -import software.amazon.awssdk.core.interceptor.ExecutionAttribute; import software.amazon.awssdk.core.interceptor.ExecutionAttributes; import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; -import software.amazon.awssdk.core.sync.RequestBody; -import software.amazon.awssdk.http.ContentStreamProvider; -import software.amazon.awssdk.services.s3.internal.checksums.ChecksumCalculatingInputStream; import software.amazon.awssdk.services.s3.internal.checksums.S3ChecksumValidatingInputStream; -import software.amazon.awssdk.services.s3.model.PutObjectResponse; @SdkInternalApi public final class SyncChecksumValidationInterceptor implements ExecutionInterceptor { - private static ExecutionAttribute SYNC_RECORDING_CHECKSUM = new ExecutionAttribute<>("syncRecordingChecksum"); - - @Override - public Optional modifyHttpContent(Context.ModifyHttpRequest context, - ExecutionAttributes executionAttributes) { - if (shouldRecordChecksum(context.request(), SYNC, executionAttributes, context.httpRequest()) - && context.requestBody().isPresent()) { - SdkChecksum checksum = new Md5Checksum(); - executionAttributes.putAttribute(CHECKSUM, checksum); - executionAttributes.putAttribute(SYNC_RECORDING_CHECKSUM, true); - - RequestBody requestBody = context.requestBody().get(); - - ChecksumCalculatingStreamProvider streamProvider = - new ChecksumCalculatingStreamProvider(requestBody.contentStreamProvider(), checksum); - - return Optional.of(RequestBody.fromContentProvider(streamProvider, - requestBody.contentLength(), - requestBody.contentType())); - } - - return context.requestBody(); - } @Override public Optional modifyHttpResponseContent(Context.ModifyHttpResponse context, ExecutionAttributes executionAttributes) { - if (getObjectChecksumEnabledPerResponse(context.request(), context.httpResponse()) + if (getObjectChecksumEnabledPerResponse(context.request(), context.httpResponse(), executionAttributes) && context.responseBody().isPresent()) { SdkChecksum checksum = new Md5Checksum(); @@ -85,42 +51,4 @@ public Optional modifyHttpResponseContent(Context.ModifyHttpRespons return context.responseBody(); } - - @Override - public void afterUnmarshalling(Context.AfterUnmarshalling context, ExecutionAttributes executionAttributes) { - boolean recordingChecksum = Boolean.TRUE.equals(executionAttributes.getAttribute(SYNC_RECORDING_CHECKSUM)); - boolean responseChecksumIsValid = responseChecksumIsValid(context.httpResponse()); - - if (recordingChecksum && responseChecksumIsValid) { - validatePutObjectChecksum((PutObjectResponse) context.response(), executionAttributes); - } - } - - static final class ChecksumCalculatingStreamProvider implements ContentStreamProvider { - private final SdkChecksum checksum; - private InputStream currentStream; - private final ContentStreamProvider underlyingInputStreamProvider; - - ChecksumCalculatingStreamProvider(ContentStreamProvider underlyingInputStreamProvider, SdkChecksum checksum) { - this.underlyingInputStreamProvider = underlyingInputStreamProvider; - this.checksum = checksum; - } - - @Override - public InputStream newStream() { - closeCurrentStream(); - currentStream = invokeSafely(() -> new ChecksumCalculatingInputStream(underlyingInputStreamProvider.newStream(), - checksum)); - return currentStream; - } - - private void closeCurrentStream() { - checksum.reset(); - if (currentStream != null) { - invokeSafely(currentStream::close); - currentStream = null; - } - } - } - } diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/DownloadObjectHelper.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/DownloadObjectHelper.java index 9dd72fa5dfab..2d6fadc5f505 100644 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/DownloadObjectHelper.java +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/DownloadObjectHelper.java @@ -21,7 +21,6 @@ import software.amazon.awssdk.core.SplittingTransformerConfiguration; import software.amazon.awssdk.core.async.AsyncResponseTransformer; import software.amazon.awssdk.services.s3.S3AsyncClient; -import software.amazon.awssdk.services.s3.model.ChecksumMode; import software.amazon.awssdk.services.s3.model.GetObjectRequest; import software.amazon.awssdk.services.s3.model.GetObjectResponse; import software.amazon.awssdk.utils.Logger; @@ -44,12 +43,11 @@ public CompletableFuture downloadObject( logSinglePartMessage(getObjectRequest); return s3AsyncClient.getObject(getObjectRequest, asyncResponseTransformer); } - GetObjectRequest requestToPerform = getObjectRequest.toBuilder().checksumMode(ChecksumMode.ENABLED).build(); AsyncResponseTransformer.SplitResult split = asyncResponseTransformer.split(SplittingTransformerConfiguration.builder() .bufferSizeInBytes(bufferSizeInBytes) .build()); - MultipartDownloaderSubscriber subscriber = subscriber(requestToPerform); + MultipartDownloaderSubscriber subscriber = subscriber(getObjectRequest); split.publisher().subscribe(subscriber); return split.resultFuture(); } diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/GenericMultipartHelper.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/GenericMultipartHelper.java index bc4d1eda7373..5e557c9fe7b0 100644 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/GenericMultipartHelper.java +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/GenericMultipartHelper.java @@ -83,12 +83,13 @@ public int determinePartCount(long contentLength, long partSize) { } public CompletableFuture completeMultipartUpload( - PutObjectRequest request, String uploadId, CompletedPart[] parts) { + PutObjectRequest request, String uploadId, CompletedPart[] parts, long contentLength) { log.debug(() -> String.format("Sending completeMultipartUploadRequest, uploadId: %s", uploadId)); CompleteMultipartUploadRequest completeMultipartUploadRequest = toCompleteMultipartUploadRequest(request, uploadId, - parts); + parts, contentLength); + return s3AsyncClient.completeMultipartUpload(completeMultipartUploadRequest); } diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/KnownContentLengthAsyncRequestBodySubscriber.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/KnownContentLengthAsyncRequestBodySubscriber.java index b41fbf836dcb..7a27e60e31dc 100644 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/KnownContentLengthAsyncRequestBodySubscriber.java +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/KnownContentLengthAsyncRequestBodySubscriber.java @@ -54,6 +54,7 @@ public class KnownContentLengthAsyncRequestBodySubscriber implements Subscriber< private final AtomicBoolean failureActionInitiated = new AtomicBoolean(false); private final AtomicInteger partNumber = new AtomicInteger(1); private final MultipartUploadHelper multipartUploadHelper; + private final long contentLength; private final long partSize; private final int partCount; private final int numExistingParts; @@ -76,8 +77,9 @@ public class KnownContentLengthAsyncRequestBodySubscriber implements Subscriber< KnownContentLengthAsyncRequestBodySubscriber(MpuRequestContext mpuRequestContext, CompletableFuture returnFuture, MultipartUploadHelper multipartUploadHelper) { + this.contentLength = mpuRequestContext.contentLength(); this.partSize = mpuRequestContext.partSize(); - this.partCount = determinePartCount(mpuRequestContext.contentLength(), partSize); + this.partCount = determinePartCount(contentLength, partSize); this.putObjectRequest = mpuRequestContext.request().left(); this.returnFuture = returnFuture; this.uploadId = mpuRequestContext.uploadId(); @@ -210,7 +212,8 @@ private void completeMultipartUploadIfFinished(int requestsInFlight) { // List of CompletedParts needs to be in ascending order parts = mergeCompletedParts(); } - completeMpuFuture = multipartUploadHelper.completeMultipartUpload(returnFuture, uploadId, parts, putObjectRequest); + completeMpuFuture = multipartUploadHelper.completeMultipartUpload(returnFuture, uploadId, parts, putObjectRequest, + contentLength); } } diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/MultipartS3AsyncClient.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/MultipartS3AsyncClient.java index 266eb081cf24..6142db7772f7 100644 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/MultipartS3AsyncClient.java +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/MultipartS3AsyncClient.java @@ -16,19 +16,15 @@ package software.amazon.awssdk.services.s3.internal.multipart; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.function.Function; -import java.util.stream.Stream; import software.amazon.awssdk.annotations.SdkInternalApi; import software.amazon.awssdk.core.ApiName; -import software.amazon.awssdk.core.RequestOverrideConfiguration; import software.amazon.awssdk.core.async.AsyncRequestBody; import software.amazon.awssdk.core.async.AsyncResponseTransformer; -import software.amazon.awssdk.core.interceptor.ExecutionAttributes; -import software.amazon.awssdk.core.interceptor.SdkExecutionAttribute; import software.amazon.awssdk.services.s3.DelegatingS3AsyncClient; import software.amazon.awssdk.services.s3.S3AsyncClient; -import software.amazon.awssdk.services.s3.S3Configuration; import software.amazon.awssdk.services.s3.internal.UserAgentUtils; import software.amazon.awssdk.services.s3.model.ChecksumAlgorithm; import software.amazon.awssdk.services.s3.model.CopyObjectRequest; @@ -56,8 +52,10 @@ public final class MultipartS3AsyncClient extends DelegatingS3AsyncClient { private final UploadObjectHelper mpuHelper; private final CopyObjectHelper copyObjectHelper; private final DownloadObjectHelper downloadObjectHelper; + private final boolean checksumEnabled; - private MultipartS3AsyncClient(S3AsyncClient delegate, MultipartConfiguration multipartConfiguration) { + private MultipartS3AsyncClient(S3AsyncClient delegate, MultipartConfiguration multipartConfiguration, + boolean checksumEnabled) { super(delegate); MultipartConfiguration validConfiguration = Validate.getOrDefault(multipartConfiguration, MultipartConfiguration.builder()::build); @@ -68,42 +66,21 @@ private MultipartS3AsyncClient(S3AsyncClient delegate, MultipartConfiguration mu mpuHelper = new UploadObjectHelper(delegate, resolver); copyObjectHelper = new CopyObjectHelper(delegate, minPartSizeInBytes, threshold); downloadObjectHelper = new DownloadObjectHelper(delegate, apiCallBufferSize); + this.checksumEnabled = checksumEnabled; } @Override public CompletableFuture putObject(PutObjectRequest putObjectRequest, AsyncRequestBody requestBody) { - if (shouldEnableCrc32(putObjectRequest)) { - putObjectRequest = putObjectRequest.toBuilder().checksumAlgorithm(ChecksumAlgorithm.CRC32).build(); - } - - return mpuHelper.uploadObject(putObjectRequest, requestBody); - } - - private boolean shouldEnableCrc32(PutObjectRequest putObjectRequest) { - return !checksumSetOnRequest(putObjectRequest) && checksumEnabledPerConfig(putObjectRequest); - } - private boolean checksumSetOnRequest(PutObjectRequest putObjectRequest) { - if (putObjectRequest.checksumAlgorithm() != null) { - return true; - } - - return Stream.of("ChecksumCRC32", "ChecksumCRC32C", "ChecksumSHA1", "ChecksumSHA256") - .anyMatch(s -> putObjectRequest.getValueForField(s, String.class).isPresent()); - } - - private boolean checksumEnabledPerConfig(PutObjectRequest putObjectRequest) { - ExecutionAttributes executionAttributes = - putObjectRequest.overrideConfiguration().map(RequestOverrideConfiguration::executionAttributes).orElse(null); + Optional checksumAlgorithm = S3ChecksumUtils.checksumAlgorithmFromPutObjectRequest(putObjectRequest); - if (executionAttributes == null) { - return true; + if (checksumAlgorithm.isPresent()) { + putObjectRequest = putObjectRequest.toBuilder().checksumAlgorithm(checksumAlgorithm.get()).build(); + } else if (checksumEnabled) { + putObjectRequest = putObjectRequest.toBuilder().checksumAlgorithm(ChecksumAlgorithm.CRC32).build(); } - S3Configuration serviceConfiguration = - (S3Configuration) executionAttributes.getAttribute(SdkExecutionAttribute.SERVICE_CONFIG); - - return serviceConfiguration == null || serviceConfiguration.checksumValidationEnabled(); + return mpuHelper.uploadObject(putObjectRequest, requestBody); } @Override @@ -122,7 +99,8 @@ public void close() { delegate().close(); } - public static MultipartS3AsyncClient create(S3AsyncClient client, MultipartConfiguration multipartConfiguration) { + public static MultipartS3AsyncClient create(S3AsyncClient client, MultipartConfiguration multipartConfiguration, + boolean checksumEnabled) { S3AsyncClient clientWithUserAgent = new DelegatingS3AsyncClient(client) { @Override protected CompletableFuture invokeOperation(T request, Function CompletableFuture invokeOperat return operation.apply(requestWithUserAgent); } }; - return new MultipartS3AsyncClient(clientWithUserAgent, multipartConfiguration); + return new MultipartS3AsyncClient(clientWithUserAgent, multipartConfiguration, checksumEnabled); } } diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/MultipartUploadHelper.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/MultipartUploadHelper.java index 71cc364915cc..e752a40e6262 100644 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/MultipartUploadHelper.java +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/MultipartUploadHelper.java @@ -80,9 +80,10 @@ CompletableFuture createMultipartUpload(PutObject CompletableFuture completeMultipartUpload(CompletableFuture returnFuture, String uploadId, CompletedPart[] completedParts, - PutObjectRequest putObjectRequest) { + PutObjectRequest putObjectRequest, + long contentLength) { CompletableFuture future = - genericMultipartHelper.completeMultipartUpload(putObjectRequest, uploadId, completedParts); + genericMultipartHelper.completeMultipartUpload(putObjectRequest, uploadId, completedParts, contentLength); future.handle(genericMultipartHelper.handleExceptionOrResponse(putObjectRequest, returnFuture, uploadId)) .exceptionally(throwable -> { diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/S3ChecksumUtils.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/S3ChecksumUtils.java new file mode 100644 index 000000000000..a1d3910d458c --- /dev/null +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/S3ChecksumUtils.java @@ -0,0 +1,68 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.services.s3.internal.multipart; + +import java.util.Optional; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.core.SdkField; +import software.amazon.awssdk.core.SdkRequest; +import software.amazon.awssdk.services.s3.model.ChecksumAlgorithm; +import software.amazon.awssdk.services.s3.model.PutObjectRequest; +import software.amazon.awssdk.utils.Logger; + +@SdkInternalApi +public final class S3ChecksumUtils { + private static final Logger log = Logger.loggerFor(S3ChecksumUtils.class); + + private S3ChecksumUtils() { + + } + + public static boolean checksumValueSpecified(SdkRequest request) { + for (ChecksumAlgorithm algorithm : ChecksumAlgorithm.knownValues()) { + String s = "Checksum" + algorithm; + if (request.getValueForField(s, String.class).isPresent()) { + return true; + } + } + return false; + } + + public static Optional checksumAlgorithmFromPutObjectRequest(PutObjectRequest request) { + + if (request.checksumAlgorithm() != null) { + return Optional.of(request.checksumAlgorithm()); + } + + try { + // Remove prefix "Checksum" + for (SdkField field : request.sdkFields()) { + if (field.memberName().startsWith("Checksum")) { + if (request.getValueForField(field.memberName(), String.class).isPresent()) { + String substring = field.memberName().substring(8); + return Optional.of(ChecksumAlgorithm.fromValue(substring)); + } + } + } + } catch (Exception e) { + log.debug(() -> "Failed to retrieve checksum algorithm from PutObjectRequest, will use the SDK default checksum " + + "algorithm", e); + return Optional.empty(); + } + + return Optional.empty(); + } +} \ No newline at end of file diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/SdkPojoConversionUtils.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/SdkPojoConversionUtils.java index 241f01b0affc..efe9599dbf6c 100644 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/SdkPojoConversionUtils.java +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/SdkPojoConversionUtils.java @@ -25,6 +25,7 @@ import software.amazon.awssdk.core.SdkField; import software.amazon.awssdk.core.SdkPojo; import software.amazon.awssdk.services.s3.model.AbortMultipartUploadRequest; +import software.amazon.awssdk.services.s3.model.ChecksumType; import software.amazon.awssdk.services.s3.model.CompleteMultipartUploadRequest; import software.amazon.awssdk.services.s3.model.CompleteMultipartUploadResponse; import software.amazon.awssdk.services.s3.model.CompletedPart; @@ -48,8 +49,9 @@ @SdkInternalApi public final class SdkPojoConversionUtils { - private static final HashSet PUT_OBJECT_REQUEST_TO_UPLOAD_PART_FIELDS_TO_IGNORE = - new HashSet<>(Arrays.asList("ChecksumSHA1", "ChecksumSHA256", "ContentMD5", "ChecksumCRC32C", "ChecksumCRC32")); + protected static final Set PUT_OBJECT_REQUEST_TO_UPLOAD_PART_FIELDS_TO_IGNORE = + new HashSet<>(Arrays.asList("ChecksumSHA1", "ChecksumSHA256", "ContentMD5", "ChecksumCRC32C", "ChecksumCRC32", + "ChecksumCRC64NVME")); private SdkPojoConversionUtils() { } @@ -62,9 +64,17 @@ public static UploadPartRequest toUploadPartRequest(PutObjectRequest putObjectRe } public static CompleteMultipartUploadRequest toCompleteMultipartUploadRequest(PutObjectRequest putObjectRequest, - String uploadId, CompletedPart[] parts) { + String uploadId, CompletedPart[] parts, + long contentLength) { CompleteMultipartUploadRequest.Builder builder = CompleteMultipartUploadRequest.builder(); setSdkFields(builder, putObjectRequest); + + builder.mpuObjectSize(Math.toIntExact(contentLength)); + + if (S3ChecksumUtils.checksumValueSpecified(putObjectRequest)) { + builder.checksumType(ChecksumType.FULL_OBJECT); + } + return builder.uploadId(uploadId).multipartUpload(c -> c.parts(parts)).build(); } @@ -72,6 +82,11 @@ public static CreateMultipartUploadRequest toCreateMultipartUploadRequest(PutObj CreateMultipartUploadRequest.Builder builder = CreateMultipartUploadRequest.builder(); setSdkFields(builder, putObjectRequest); + + if (S3ChecksumUtils.checksumValueSpecified(putObjectRequest)) { + builder.checksumType(ChecksumType.FULL_OBJECT); + } + return builder.build(); } diff --git a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/UploadWithUnknownContentLengthHelper.java b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/UploadWithUnknownContentLengthHelper.java index 18e3a9291d58..fd89bb92e737 100644 --- a/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/UploadWithUnknownContentLengthHelper.java +++ b/services/s3/src/main/java/software/amazon/awssdk/services/s3/internal/multipart/UploadWithUnknownContentLengthHelper.java @@ -20,17 +20,20 @@ import java.util.Collection; import java.util.Comparator; +import java.util.Optional; import java.util.Queue; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; import org.reactivestreams.Subscriber; import org.reactivestreams.Subscription; import software.amazon.awssdk.annotations.SdkInternalApi; import software.amazon.awssdk.core.async.AsyncRequestBody; import software.amazon.awssdk.core.async.SdkPublisher; import software.amazon.awssdk.core.async.listener.PublisherListener; +import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.services.s3.S3AsyncClient; import software.amazon.awssdk.services.s3.model.CompletedPart; import software.amazon.awssdk.services.s3.model.CreateMultipartUploadResponse; @@ -110,6 +113,7 @@ private class UnknownContentLengthAsyncRequestBodySubscriber implements Subscrib private final AtomicBoolean failureActionInitiated = new AtomicBoolean(false); private AtomicInteger partNumber = new AtomicInteger(1); + private AtomicLong contentLength = new AtomicLong(0); private final Queue completedParts = new ConcurrentLinkedQueue<>(); private final Collection> futures = new ConcurrentLinkedQueue<>(); @@ -199,6 +203,13 @@ public void onNext(AsyncRequestBody asyncRequestBody) { } private void sendUploadPartRequest(String uploadId, AsyncRequestBody asyncRequestBody) { + Optional contentLength = asyncRequestBody.contentLength(); + if (!contentLength.isPresent()) { + SdkClientException e = SdkClientException.create("Content length must be present on the AsyncRequestBody"); + multipartUploadHelper.failRequestsElegantly(futures, e, uploadId, returnFuture, putObjectRequest); + } + this.contentLength.getAndAdd(contentLength.get()); + multipartUploadHelper.sendIndividualUploadPartRequest(uploadId, completedParts::add, futures, uploadPart(asyncRequestBody), progressListener) .whenComplete((r, t) -> { @@ -249,7 +260,8 @@ private void completeMultipartUploadIfFinish(int requestsInFlight) { CompletedPart[] parts = completedParts.stream() .sorted(Comparator.comparingInt(CompletedPart::partNumber)) .toArray(CompletedPart[]::new); - multipartUploadHelper.completeMultipartUpload(returnFuture, uploadId, parts, putObjectRequest); + multipartUploadHelper.completeMultipartUpload(returnFuture, uploadId, parts, putObjectRequest, + this.contentLength.get()); } } } diff --git a/services/s3/src/main/resources/codegen-resources/customization.config b/services/s3/src/main/resources/codegen-resources/customization.config index ccb726181f1a..8acd43509eab 100644 --- a/services/s3/src/main/resources/codegen-resources/customization.config +++ b/services/s3/src/main/resources/codegen-resources/customization.config @@ -202,7 +202,8 @@ "hasMultiRegionEnabledProperty": true, "hasPathStyleAccessEnabledProperty":true, "hasAccelerateModeEnabledProperty":true, - "hasCrossRegionAccessEnabledProperty":true + "hasCrossRegionAccessEnabledProperty":true, + "hasChecksumValidationEnabledProperty":true }, "skipEndpointTests": { "Invalid access point ARN: Not S3": "Test assumes UseArnRegion is true but SDK defaults to false", @@ -299,7 +300,6 @@ "software.amazon.awssdk.services.s3.internal.handlers.CreateMultipartUploadRequestInterceptor", "software.amazon.awssdk.services.s3.internal.handlers.DecodeUrlEncodedResponseInterceptor", "software.amazon.awssdk.services.s3.internal.handlers.GetBucketPolicyInterceptor", - "software.amazon.awssdk.services.s3.internal.handlers.S3ExpressChecksumInterceptor", "software.amazon.awssdk.services.s3.internal.handlers.AsyncChecksumValidationInterceptor", "software.amazon.awssdk.services.s3.internal.handlers.SyncChecksumValidationInterceptor", "software.amazon.awssdk.services.s3.internal.handlers.EnableTrailingChecksumInterceptor", diff --git a/services/s3/src/main/resources/codegen-resources/service-2.json b/services/s3/src/main/resources/codegen-resources/service-2.json index 6890770d93de..669fe1e13921 100644 --- a/services/s3/src/main/resources/codegen-resources/service-2.json +++ b/services/s3/src/main/resources/codegen-resources/service-2.json @@ -28,7 +28,7 @@ {"shape":"NoSuchUpload"} ], "documentationUrl":"http://docs.amazonwebservices.com/AmazonS3/latest/API/mpUploadAbort.html", - "documentation":"

    This operation aborts a multipart upload. After a multipart upload is aborted, no additional parts can be uploaded using that upload ID. The storage consumed by any previously uploaded parts will be freed. However, if any part uploads are currently in progress, those part uploads might or might not succeed. As a result, it might be necessary to abort a given multipart upload multiple times in order to completely free all storage consumed by all parts.

    To verify that all parts have been removed and prevent getting charged for the part storage, you should call the ListParts API operation and ensure that the parts list is empty.

    • Directory buckets - If multipart uploads in a directory bucket are in progress, you can't delete the bucket until all the in-progress multipart uploads are aborted or completed. To delete these in-progress multipart uploads, use the ListMultipartUploads operation to list the in-progress multipart uploads in the bucket and use the AbortMultipartUpload operation to abort all the in-progress multipart uploads.

    • Directory buckets - For directory buckets, you must make requests for this API operation to the Zonal endpoint. These endpoints support virtual-hosted-style requests in the format https://bucket-name.s3express-zone-id.region-code.amazonaws.com/key-name . Path-style requests are not supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Concepts for directory buckets in Local Zones in the Amazon S3 User Guide.

    Permissions
    • General purpose bucket permissions - For information about permissions required to use the multipart upload, see Multipart Upload and Permissions in the Amazon S3 User Guide.

    • Directory bucket permissions - To grant access to this API operation on a directory bucket, we recommend that you use the CreateSession API operation for session-based authorization. Specifically, you grant the s3express:CreateSession permission to the directory bucket in a bucket policy or an IAM identity-based policy. Then, you make the CreateSession API call on the bucket to obtain a session token. With the session token in your request header, you can make API requests to this operation. After the session token expires, you make another CreateSession API call to generate a new session token for use. Amazon Web Services CLI or SDKs create session and refresh the session token automatically to avoid service interruptions when a session expires. For more information about authorization, see CreateSession .

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is Bucket-name.s3express-zone-id.region-code.amazonaws.com.

    The following operations are related to AbortMultipartUpload:

    " + "documentation":"

    This operation aborts a multipart upload. After a multipart upload is aborted, no additional parts can be uploaded using that upload ID. The storage consumed by any previously uploaded parts will be freed. However, if any part uploads are currently in progress, those part uploads might or might not succeed. As a result, it might be necessary to abort a given multipart upload multiple times in order to completely free all storage consumed by all parts.

    To verify that all parts have been removed and prevent getting charged for the part storage, you should call the ListParts API operation and ensure that the parts list is empty.

    • Directory buckets - If multipart uploads in a directory bucket are in progress, you can't delete the bucket until all the in-progress multipart uploads are aborted or completed. To delete these in-progress multipart uploads, use the ListMultipartUploads operation to list the in-progress multipart uploads in the bucket and use the AbortMultipartUpload operation to abort all the in-progress multipart uploads.

    • Directory buckets - For directory buckets, you must make requests for this API operation to the Zonal endpoint. These endpoints support virtual-hosted-style requests in the format https://bucket-name.s3express-zone-id.region-code.amazonaws.com/key-name . Path-style requests are not supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Available Local Zone for directory buckets in the Amazon S3 User Guide.

    Permissions
    • General purpose bucket permissions - For information about permissions required to use the multipart upload, see Multipart Upload and Permissions in the Amazon S3 User Guide.

    • Directory bucket permissions - To grant access to this API operation on a directory bucket, we recommend that you use the CreateSession API operation for session-based authorization. Specifically, you grant the s3express:CreateSession permission to the directory bucket in a bucket policy or an IAM identity-based policy. Then, you make the CreateSession API call on the bucket to obtain a session token. With the session token in your request header, you can make API requests to this operation. After the session token expires, you make another CreateSession API call to generate a new session token for use. Amazon Web Services CLI or SDKs create session and refresh the session token automatically to avoid service interruptions when a session expires. For more information about authorization, see CreateSession .

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is Bucket-name.s3express-zone-id.region-code.amazonaws.com.

    The following operations are related to AbortMultipartUpload:

    " }, "CompleteMultipartUpload":{ "name":"CompleteMultipartUpload", @@ -39,7 +39,7 @@ "input":{"shape":"CompleteMultipartUploadRequest"}, "output":{"shape":"CompleteMultipartUploadOutput"}, "documentationUrl":"http://docs.amazonwebservices.com/AmazonS3/latest/API/mpUploadComplete.html", - "documentation":"

    Completes a multipart upload by assembling previously uploaded parts.

    You first initiate the multipart upload and then upload all parts using the UploadPart operation or the UploadPartCopy operation. After successfully uploading all relevant parts of an upload, you call this CompleteMultipartUpload operation to complete the upload. Upon receiving this request, Amazon S3 concatenates all the parts in ascending order by part number to create a new object. In the CompleteMultipartUpload request, you must provide the parts list and ensure that the parts list is complete. The CompleteMultipartUpload API operation concatenates the parts that you provide in the list. For each part in the list, you must provide the PartNumber value and the ETag value that are returned after that part was uploaded.

    The processing of a CompleteMultipartUpload request could take several minutes to finalize. After Amazon S3 begins processing the request, it sends an HTTP response header that specifies a 200 OK response. While processing is in progress, Amazon S3 periodically sends white space characters to keep the connection from timing out. A request could fail after the initial 200 OK response has been sent. This means that a 200 OK response can contain either a success or an error. The error response might be embedded in the 200 OK response. If you call this API operation directly, make sure to design your application to parse the contents of the response and handle it appropriately. If you use Amazon Web Services SDKs, SDKs handle this condition. The SDKs detect the embedded error and apply error handling per your configuration settings (including automatically retrying the request as appropriate). If the condition persists, the SDKs throw an exception (or, for the SDKs that don't use exceptions, they return an error).

    Note that if CompleteMultipartUpload fails, applications should be prepared to retry any failed requests (including 500 error responses). For more information, see Amazon S3 Error Best Practices.

    You can't use Content-Type: application/x-www-form-urlencoded for the CompleteMultipartUpload requests. Also, if you don't provide a Content-Type header, CompleteMultipartUpload can still return a 200 OK response.

    For more information about multipart uploads, see Uploading Objects Using Multipart Upload in the Amazon S3 User Guide.

    Directory buckets - For directory buckets, you must make requests for this API operation to the Zonal endpoint. These endpoints support virtual-hosted-style requests in the format https://bucket-name.s3express-zone-id.region-code.amazonaws.com/key-name . Path-style requests are not supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Concepts for directory buckets in Local Zones in the Amazon S3 User Guide.

    Permissions
    • General purpose bucket permissions - For information about permissions required to use the multipart upload API, see Multipart Upload and Permissions in the Amazon S3 User Guide.

      If you provide an additional checksum value in your MultipartUpload requests and the object is encrypted with Key Management Service, you must have permission to use the kms:Decrypt action for the CompleteMultipartUpload request to succeed.

    • Directory bucket permissions - To grant access to this API operation on a directory bucket, we recommend that you use the CreateSession API operation for session-based authorization. Specifically, you grant the s3express:CreateSession permission to the directory bucket in a bucket policy or an IAM identity-based policy. Then, you make the CreateSession API call on the bucket to obtain a session token. With the session token in your request header, you can make API requests to this operation. After the session token expires, you make another CreateSession API call to generate a new session token for use. Amazon Web Services CLI or SDKs create session and refresh the session token automatically to avoid service interruptions when a session expires. For more information about authorization, see CreateSession .

      If the object is encrypted with SSE-KMS, you must also have the kms:GenerateDataKey and kms:Decrypt permissions in IAM identity-based policies and KMS key policies for the KMS key.

    Special errors
    • Error Code: EntityTooSmall

      • Description: Your proposed upload is smaller than the minimum allowed object size. Each part must be at least 5 MB in size, except the last part.

      • HTTP Status Code: 400 Bad Request

    • Error Code: InvalidPart

      • Description: One or more of the specified parts could not be found. The part might not have been uploaded, or the specified ETag might not have matched the uploaded part's ETag.

      • HTTP Status Code: 400 Bad Request

    • Error Code: InvalidPartOrder

      • Description: The list of parts was not in ascending order. The parts list must be specified in order by part number.

      • HTTP Status Code: 400 Bad Request

    • Error Code: NoSuchUpload

      • Description: The specified multipart upload does not exist. The upload ID might be invalid, or the multipart upload might have been aborted or completed.

      • HTTP Status Code: 404 Not Found

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is Bucket-name.s3express-zone-id.region-code.amazonaws.com.

    The following operations are related to CompleteMultipartUpload:

    " + "documentation":"

    Completes a multipart upload by assembling previously uploaded parts.

    You first initiate the multipart upload and then upload all parts using the UploadPart operation or the UploadPartCopy operation. After successfully uploading all relevant parts of an upload, you call this CompleteMultipartUpload operation to complete the upload. Upon receiving this request, Amazon S3 concatenates all the parts in ascending order by part number to create a new object. In the CompleteMultipartUpload request, you must provide the parts list and ensure that the parts list is complete. The CompleteMultipartUpload API operation concatenates the parts that you provide in the list. For each part in the list, you must provide the PartNumber value and the ETag value that are returned after that part was uploaded.

    The processing of a CompleteMultipartUpload request could take several minutes to finalize. After Amazon S3 begins processing the request, it sends an HTTP response header that specifies a 200 OK response. While processing is in progress, Amazon S3 periodically sends white space characters to keep the connection from timing out. A request could fail after the initial 200 OK response has been sent. This means that a 200 OK response can contain either a success or an error. The error response might be embedded in the 200 OK response. If you call this API operation directly, make sure to design your application to parse the contents of the response and handle it appropriately. If you use Amazon Web Services SDKs, SDKs handle this condition. The SDKs detect the embedded error and apply error handling per your configuration settings (including automatically retrying the request as appropriate). If the condition persists, the SDKs throw an exception (or, for the SDKs that don't use exceptions, they return an error).

    Note that if CompleteMultipartUpload fails, applications should be prepared to retry any failed requests (including 500 error responses). For more information, see Amazon S3 Error Best Practices.

    You can't use Content-Type: application/x-www-form-urlencoded for the CompleteMultipartUpload requests. Also, if you don't provide a Content-Type header, CompleteMultipartUpload can still return a 200 OK response.

    For more information about multipart uploads, see Uploading Objects Using Multipart Upload in the Amazon S3 User Guide.

    Directory buckets - For directory buckets, you must make requests for this API operation to the Zonal endpoint. These endpoints support virtual-hosted-style requests in the format https://bucket-name.s3express-zone-id.region-code.amazonaws.com/key-name . Path-style requests are not supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Available Local Zone for directory buckets in the Amazon S3 User Guide.

    Permissions
    • General purpose bucket permissions - For information about permissions required to use the multipart upload API, see Multipart Upload and Permissions in the Amazon S3 User Guide.

      If you provide an additional checksum value in your MultipartUpload requests and the object is encrypted with Key Management Service, you must have permission to use the kms:Decrypt action for the CompleteMultipartUpload request to succeed.

    • Directory bucket permissions - To grant access to this API operation on a directory bucket, we recommend that you use the CreateSession API operation for session-based authorization. Specifically, you grant the s3express:CreateSession permission to the directory bucket in a bucket policy or an IAM identity-based policy. Then, you make the CreateSession API call on the bucket to obtain a session token. With the session token in your request header, you can make API requests to this operation. After the session token expires, you make another CreateSession API call to generate a new session token for use. Amazon Web Services CLI or SDKs create session and refresh the session token automatically to avoid service interruptions when a session expires. For more information about authorization, see CreateSession .

      If the object is encrypted with SSE-KMS, you must also have the kms:GenerateDataKey and kms:Decrypt permissions in IAM identity-based policies and KMS key policies for the KMS key.

    Special errors
    • Error Code: EntityTooSmall

      • Description: Your proposed upload is smaller than the minimum allowed object size. Each part must be at least 5 MB in size, except the last part.

      • HTTP Status Code: 400 Bad Request

    • Error Code: InvalidPart

      • Description: One or more of the specified parts could not be found. The part might not have been uploaded, or the specified ETag might not have matched the uploaded part's ETag.

      • HTTP Status Code: 400 Bad Request

    • Error Code: InvalidPartOrder

      • Description: The list of parts was not in ascending order. The parts list must be specified in order by part number.

      • HTTP Status Code: 400 Bad Request

    • Error Code: NoSuchUpload

      • Description: The specified multipart upload does not exist. The upload ID might be invalid, or the multipart upload might have been aborted or completed.

      • HTTP Status Code: 404 Not Found

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is Bucket-name.s3express-zone-id.region-code.amazonaws.com.

    The following operations are related to CompleteMultipartUpload:

    " }, "CopyObject":{ "name":"CopyObject", @@ -53,7 +53,7 @@ {"shape":"ObjectNotInActiveTierError"} ], "documentationUrl":"http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTObjectCOPY.html", - "documentation":"

    Creates a copy of an object that is already stored in Amazon S3.

    You can store individual objects of up to 5 TB in Amazon S3. You create a copy of your object up to 5 GB in size in a single atomic action using this API. However, to copy an object greater than 5 GB, you must use the multipart upload Upload Part - Copy (UploadPartCopy) API. For more information, see Copy Object Using the REST Multipart Upload API.

    You can copy individual objects between general purpose buckets, between directory buckets, and between general purpose buckets and directory buckets.

    • Amazon S3 supports copy operations using Multi-Region Access Points only as a destination when using the Multi-Region Access Point ARN.

    • Directory buckets - For directory buckets, you must make requests for this API operation to the Zonal endpoint. These endpoints support virtual-hosted-style requests in the format https://bucket-name.s3express-zone-id.region-code.amazonaws.com/key-name . Path-style requests are not supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Concepts for directory buckets in Local Zones in the Amazon S3 User Guide.

    • VPC endpoints don't support cross-Region requests (including copies). If you're using VPC endpoints, your source and destination buckets should be in the same Amazon Web Services Region as your VPC endpoint.

    Both the Region that you want to copy the object from and the Region that you want to copy the object to must be enabled for your account. For more information about how to enable a Region for your account, see Enable or disable a Region for standalone accounts in the Amazon Web Services Account Management Guide.

    Amazon S3 transfer acceleration does not support cross-Region copies. If you request a cross-Region copy using a transfer acceleration endpoint, you get a 400 Bad Request error. For more information, see Transfer Acceleration.

    Authentication and authorization

    All CopyObject requests must be authenticated and signed by using IAM credentials (access key ID and secret access key for the IAM identities). All headers with the x-amz- prefix, including x-amz-copy-source, must be signed. For more information, see REST Authentication.

    Directory buckets - You must use the IAM credentials to authenticate and authorize your access to the CopyObject API operation, instead of using the temporary security credentials through the CreateSession API operation.

    Amazon Web Services CLI or SDKs handles authentication and authorization on your behalf.

    Permissions

    You must have read access to the source object and write access to the destination bucket.

    • General purpose bucket permissions - You must have permissions in an IAM policy based on the source and destination bucket types in a CopyObject operation.

      • If the source object is in a general purpose bucket, you must have s3:GetObject permission to read the source object that is being copied.

      • If the destination bucket is a general purpose bucket, you must have s3:PutObject permission to write the object copy to the destination bucket.

    • Directory bucket permissions - You must have permissions in a bucket policy or an IAM identity-based policy based on the source and destination bucket types in a CopyObject operation.

      • If the source object that you want to copy is in a directory bucket, you must have the s3express:CreateSession permission in the Action element of a policy to read the object. By default, the session is in the ReadWrite mode. If you want to restrict the access, you can explicitly set the s3express:SessionMode condition key to ReadOnly on the copy source bucket.

      • If the copy destination is a directory bucket, you must have the s3express:CreateSession permission in the Action element of a policy to write the object to the destination. The s3express:SessionMode condition key can't be set to ReadOnly on the copy destination bucket.

      If the object is encrypted with SSE-KMS, you must also have the kms:GenerateDataKey and kms:Decrypt permissions in IAM identity-based policies and KMS key policies for the KMS key.

      For example policies, see Example bucket policies for S3 Express One Zone and Amazon Web Services Identity and Access Management (IAM) identity-based policies for S3 Express One Zone in the Amazon S3 User Guide.

    Response and special errors

    When the request is an HTTP 1.1 request, the response is chunk encoded. When the request is not an HTTP 1.1 request, the response would not contain the Content-Length. You always need to read the entire response body to check if the copy succeeds.

    • If the copy is successful, you receive a response with information about the copied object.

    • A copy request might return an error when Amazon S3 receives the copy request or while Amazon S3 is copying the files. A 200 OK response can contain either a success or an error.

      • If the error occurs before the copy action starts, you receive a standard Amazon S3 error.

      • If the error occurs during the copy operation, the error response is embedded in the 200 OK response. For example, in a cross-region copy, you may encounter throttling and receive a 200 OK response. For more information, see Resolve the Error 200 response when copying objects to Amazon S3. The 200 OK status code means the copy was accepted, but it doesn't mean the copy is complete. Another example is when you disconnect from Amazon S3 before the copy is complete, Amazon S3 might cancel the copy and you may receive a 200 OK response. You must stay connected to Amazon S3 until the entire response is successfully received and processed.

        If you call this API operation directly, make sure to design your application to parse the content of the response and handle it appropriately. If you use Amazon Web Services SDKs, SDKs handle this condition. The SDKs detect the embedded error and apply error handling per your configuration settings (including automatically retrying the request as appropriate). If the condition persists, the SDKs throw an exception (or, for the SDKs that don't use exceptions, they return an error).

    Charge

    The copy request charge is based on the storage class and Region that you specify for the destination object. The request can also result in a data retrieval charge for the source if the source storage class bills for data retrieval. If the copy source is in a different region, the data transfer is billed to the copy source account. For pricing information, see Amazon S3 pricing.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is Bucket-name.s3express-zone-id.region-code.amazonaws.com.

    The following operations are related to CopyObject:

    ", + "documentation":"

    Creates a copy of an object that is already stored in Amazon S3.

    You can store individual objects of up to 5 TB in Amazon S3. You create a copy of your object up to 5 GB in size in a single atomic action using this API. However, to copy an object greater than 5 GB, you must use the multipart upload Upload Part - Copy (UploadPartCopy) API. For more information, see Copy Object Using the REST Multipart Upload API.

    You can copy individual objects between general purpose buckets, between directory buckets, and between general purpose buckets and directory buckets.

    • Amazon S3 supports copy operations using Multi-Region Access Points only as a destination when using the Multi-Region Access Point ARN.

    • Directory buckets - For directory buckets, you must make requests for this API operation to the Zonal endpoint. These endpoints support virtual-hosted-style requests in the format https://bucket-name.s3express-zone-id.region-code.amazonaws.com/key-name . Path-style requests are not supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Available Local Zone for directory buckets in the Amazon S3 User Guide.

    • VPC endpoints don't support cross-Region requests (including copies). If you're using VPC endpoints, your source and destination buckets should be in the same Amazon Web Services Region as your VPC endpoint.

    Both the Region that you want to copy the object from and the Region that you want to copy the object to must be enabled for your account. For more information about how to enable a Region for your account, see Enable or disable a Region for standalone accounts in the Amazon Web Services Account Management Guide.

    Amazon S3 transfer acceleration does not support cross-Region copies. If you request a cross-Region copy using a transfer acceleration endpoint, you get a 400 Bad Request error. For more information, see Transfer Acceleration.

    Authentication and authorization

    All CopyObject requests must be authenticated and signed by using IAM credentials (access key ID and secret access key for the IAM identities). All headers with the x-amz- prefix, including x-amz-copy-source, must be signed. For more information, see REST Authentication.

    Directory buckets - You must use the IAM credentials to authenticate and authorize your access to the CopyObject API operation, instead of using the temporary security credentials through the CreateSession API operation.

    Amazon Web Services CLI or SDKs handles authentication and authorization on your behalf.

    Permissions

    You must have read access to the source object and write access to the destination bucket.

    • General purpose bucket permissions - You must have permissions in an IAM policy based on the source and destination bucket types in a CopyObject operation.

      • If the source object is in a general purpose bucket, you must have s3:GetObject permission to read the source object that is being copied.

      • If the destination bucket is a general purpose bucket, you must have s3:PutObject permission to write the object copy to the destination bucket.

    • Directory bucket permissions - You must have permissions in a bucket policy or an IAM identity-based policy based on the source and destination bucket types in a CopyObject operation.

      • If the source object that you want to copy is in a directory bucket, you must have the s3express:CreateSession permission in the Action element of a policy to read the object. By default, the session is in the ReadWrite mode. If you want to restrict the access, you can explicitly set the s3express:SessionMode condition key to ReadOnly on the copy source bucket.

      • If the copy destination is a directory bucket, you must have the s3express:CreateSession permission in the Action element of a policy to write the object to the destination. The s3express:SessionMode condition key can't be set to ReadOnly on the copy destination bucket.

      If the object is encrypted with SSE-KMS, you must also have the kms:GenerateDataKey and kms:Decrypt permissions in IAM identity-based policies and KMS key policies for the KMS key.

      For example policies, see Example bucket policies for S3 Express One Zone and Amazon Web Services Identity and Access Management (IAM) identity-based policies for S3 Express One Zone in the Amazon S3 User Guide.

    Response and special errors

    When the request is an HTTP 1.1 request, the response is chunk encoded. When the request is not an HTTP 1.1 request, the response would not contain the Content-Length. You always need to read the entire response body to check if the copy succeeds.

    • If the copy is successful, you receive a response with information about the copied object.

    • A copy request might return an error when Amazon S3 receives the copy request or while Amazon S3 is copying the files. A 200 OK response can contain either a success or an error.

      • If the error occurs before the copy action starts, you receive a standard Amazon S3 error.

      • If the error occurs during the copy operation, the error response is embedded in the 200 OK response. For example, in a cross-region copy, you may encounter throttling and receive a 200 OK response. For more information, see Resolve the Error 200 response when copying objects to Amazon S3. The 200 OK status code means the copy was accepted, but it doesn't mean the copy is complete. Another example is when you disconnect from Amazon S3 before the copy is complete, Amazon S3 might cancel the copy and you may receive a 200 OK response. You must stay connected to Amazon S3 until the entire response is successfully received and processed.

        If you call this API operation directly, make sure to design your application to parse the content of the response and handle it appropriately. If you use Amazon Web Services SDKs, SDKs handle this condition. The SDKs detect the embedded error and apply error handling per your configuration settings (including automatically retrying the request as appropriate). If the condition persists, the SDKs throw an exception (or, for the SDKs that don't use exceptions, they return an error).

    Charge

    The copy request charge is based on the storage class and Region that you specify for the destination object. The request can also result in a data retrieval charge for the source if the source storage class bills for data retrieval. If the copy source is in a different region, the data transfer is billed to the copy source account. For pricing information, see Amazon S3 pricing.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is Bucket-name.s3express-zone-id.region-code.amazonaws.com.

    The following operations are related to CopyObject:

    ", "alias":"PutObjectCopy", "staticContextParams":{ "DisableS3ExpressSessionAuth":{"value":true} @@ -72,7 +72,7 @@ {"shape":"BucketAlreadyOwnedByYou"} ], "documentationUrl":"http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketPUT.html", - "documentation":"

    This action creates an Amazon S3 bucket. To create an Amazon S3 on Outposts bucket, see CreateBucket .

    Creates a new S3 bucket. To create a bucket, you must set up Amazon S3 and have a valid Amazon Web Services Access Key ID to authenticate requests. Anonymous requests are never allowed to create buckets. By creating the bucket, you become the bucket owner.

    There are two types of buckets: general purpose buckets and directory buckets. For more information about these bucket types, see Creating, configuring, and working with Amazon S3 buckets in the Amazon S3 User Guide.

    • General purpose buckets - If you send your CreateBucket request to the s3.amazonaws.com global endpoint, the request goes to the us-east-1 Region. So the signature calculations in Signature Version 4 must use us-east-1 as the Region, even if the location constraint in the request specifies another Region where the bucket is to be created. If you create a bucket in a Region other than US East (N. Virginia), your application must be able to handle 307 redirect. For more information, see Virtual hosting of buckets in the Amazon S3 User Guide.

    • Directory buckets - For directory buckets, you must make requests for this API operation to the Regional endpoint. These endpoints support path-style requests in the format https://s3express-control.region-code.amazonaws.com/bucket-name . Virtual-hosted-style requests aren't supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Concepts for directory buckets in Local Zones in the Amazon S3 User Guide.

    Permissions
    • General purpose bucket permissions - In addition to the s3:CreateBucket permission, the following permissions are required in a policy when your CreateBucket request includes specific headers:

      • Access control lists (ACLs) - In your CreateBucket request, if you specify an access control list (ACL) and set it to public-read, public-read-write, authenticated-read, or if you explicitly specify any other custom ACLs, both s3:CreateBucket and s3:PutBucketAcl permissions are required. In your CreateBucket request, if you set the ACL to private, or if you don't specify any ACLs, only the s3:CreateBucket permission is required.

      • Object Lock - In your CreateBucket request, if you set x-amz-bucket-object-lock-enabled to true, the s3:PutBucketObjectLockConfiguration and s3:PutBucketVersioning permissions are required.

      • S3 Object Ownership - If your CreateBucket request includes the x-amz-object-ownership header, then the s3:PutBucketOwnershipControls permission is required.

        To set an ACL on a bucket as part of a CreateBucket request, you must explicitly set S3 Object Ownership for the bucket to a different value than the default, BucketOwnerEnforced. Additionally, if your desired bucket ACL grants public access, you must first create the bucket (without the bucket ACL) and then explicitly disable Block Public Access on the bucket before using PutBucketAcl to set the ACL. If you try to create a bucket with a public ACL, the request will fail.

        For the majority of modern use cases in S3, we recommend that you keep all Block Public Access settings enabled and keep ACLs disabled. If you would like to share data with users outside of your account, you can use bucket policies as needed. For more information, see Controlling ownership of objects and disabling ACLs for your bucket and Blocking public access to your Amazon S3 storage in the Amazon S3 User Guide.

      • S3 Block Public Access - If your specific use case requires granting public access to your S3 resources, you can disable Block Public Access. Specifically, you can create a new bucket with Block Public Access enabled, then separately call the DeletePublicAccessBlock API. To use this operation, you must have the s3:PutBucketPublicAccessBlock permission. For more information about S3 Block Public Access, see Blocking public access to your Amazon S3 storage in the Amazon S3 User Guide.

    • Directory bucket permissions - You must have the s3express:CreateBucket permission in an IAM identity-based policy instead of a bucket policy. Cross-account access to this API operation isn't supported. This operation can only be performed by the Amazon Web Services account that owns the resource. For more information about directory bucket policies and permissions, see Amazon Web Services Identity and Access Management (IAM) for S3 Express One Zone in the Amazon S3 User Guide.

      The permissions for ACLs, Object Lock, S3 Object Ownership, and S3 Block Public Access are not supported for directory buckets. For directory buckets, all Block Public Access settings are enabled at the bucket level and S3 Object Ownership is set to Bucket owner enforced (ACLs disabled). These settings can't be modified.

      For more information about permissions for creating and working with directory buckets, see Directory buckets in the Amazon S3 User Guide. For more information about supported S3 features for directory buckets, see Features of S3 Express One Zone in the Amazon S3 User Guide.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is s3express-control.region-code.amazonaws.com.

    The following operations are related to CreateBucket:

    ", + "documentation":"

    This action creates an Amazon S3 bucket. To create an Amazon S3 on Outposts bucket, see CreateBucket .

    Creates a new S3 bucket. To create a bucket, you must set up Amazon S3 and have a valid Amazon Web Services Access Key ID to authenticate requests. Anonymous requests are never allowed to create buckets. By creating the bucket, you become the bucket owner.

    There are two types of buckets: general purpose buckets and directory buckets. For more information about these bucket types, see Creating, configuring, and working with Amazon S3 buckets in the Amazon S3 User Guide.

    • General purpose buckets - If you send your CreateBucket request to the s3.amazonaws.com global endpoint, the request goes to the us-east-1 Region. So the signature calculations in Signature Version 4 must use us-east-1 as the Region, even if the location constraint in the request specifies another Region where the bucket is to be created. If you create a bucket in a Region other than US East (N. Virginia), your application must be able to handle 307 redirect. For more information, see Virtual hosting of buckets in the Amazon S3 User Guide.

    • Directory buckets - For directory buckets, you must make requests for this API operation to the Regional endpoint. These endpoints support path-style requests in the format https://s3express-control.region-code.amazonaws.com/bucket-name . Virtual-hosted-style requests aren't supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Available Local Zone for directory buckets in the Amazon S3 User Guide.

    Permissions
    • General purpose bucket permissions - In addition to the s3:CreateBucket permission, the following permissions are required in a policy when your CreateBucket request includes specific headers:

      • Access control lists (ACLs) - In your CreateBucket request, if you specify an access control list (ACL) and set it to public-read, public-read-write, authenticated-read, or if you explicitly specify any other custom ACLs, both s3:CreateBucket and s3:PutBucketAcl permissions are required. In your CreateBucket request, if you set the ACL to private, or if you don't specify any ACLs, only the s3:CreateBucket permission is required.

      • Object Lock - In your CreateBucket request, if you set x-amz-bucket-object-lock-enabled to true, the s3:PutBucketObjectLockConfiguration and s3:PutBucketVersioning permissions are required.

      • S3 Object Ownership - If your CreateBucket request includes the x-amz-object-ownership header, then the s3:PutBucketOwnershipControls permission is required.

        To set an ACL on a bucket as part of a CreateBucket request, you must explicitly set S3 Object Ownership for the bucket to a different value than the default, BucketOwnerEnforced. Additionally, if your desired bucket ACL grants public access, you must first create the bucket (without the bucket ACL) and then explicitly disable Block Public Access on the bucket before using PutBucketAcl to set the ACL. If you try to create a bucket with a public ACL, the request will fail.

        For the majority of modern use cases in S3, we recommend that you keep all Block Public Access settings enabled and keep ACLs disabled. If you would like to share data with users outside of your account, you can use bucket policies as needed. For more information, see Controlling ownership of objects and disabling ACLs for your bucket and Blocking public access to your Amazon S3 storage in the Amazon S3 User Guide.

      • S3 Block Public Access - If your specific use case requires granting public access to your S3 resources, you can disable Block Public Access. Specifically, you can create a new bucket with Block Public Access enabled, then separately call the DeletePublicAccessBlock API. To use this operation, you must have the s3:PutBucketPublicAccessBlock permission. For more information about S3 Block Public Access, see Blocking public access to your Amazon S3 storage in the Amazon S3 User Guide.

    • Directory bucket permissions - You must have the s3express:CreateBucket permission in an IAM identity-based policy instead of a bucket policy. Cross-account access to this API operation isn't supported. This operation can only be performed by the Amazon Web Services account that owns the resource. For more information about directory bucket policies and permissions, see Amazon Web Services Identity and Access Management (IAM) for S3 Express One Zone in the Amazon S3 User Guide.

      The permissions for ACLs, Object Lock, S3 Object Ownership, and S3 Block Public Access are not supported for directory buckets. For directory buckets, all Block Public Access settings are enabled at the bucket level and S3 Object Ownership is set to Bucket owner enforced (ACLs disabled). These settings can't be modified.

      For more information about permissions for creating and working with directory buckets, see Directory buckets in the Amazon S3 User Guide. For more information about supported S3 features for directory buckets, see Features of S3 Express One Zone in the Amazon S3 User Guide.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is s3express-control.region-code.amazonaws.com.

    The following operations are related to CreateBucket:

    ", "alias":"PutBucket", "staticContextParams":{ "DisableAccessPoints":{"value":true}, @@ -104,7 +104,7 @@ "input":{"shape":"CreateMultipartUploadRequest"}, "output":{"shape":"CreateMultipartUploadOutput"}, "documentationUrl":"http://docs.amazonwebservices.com/AmazonS3/latest/API/mpUploadInitiate.html", - "documentation":"

    This action initiates a multipart upload and returns an upload ID. This upload ID is used to associate all of the parts in the specific multipart upload. You specify this upload ID in each of your subsequent upload part requests (see UploadPart). You also include this upload ID in the final request to either complete or abort the multipart upload request. For more information about multipart uploads, see Multipart Upload Overview in the Amazon S3 User Guide.

    After you initiate a multipart upload and upload one or more parts, to stop being charged for storing the uploaded parts, you must either complete or abort the multipart upload. Amazon S3 frees up the space used to store the parts and stops charging you for storing them only after you either complete or abort a multipart upload.

    If you have configured a lifecycle rule to abort incomplete multipart uploads, the created multipart upload must be completed within the number of days specified in the bucket lifecycle configuration. Otherwise, the incomplete multipart upload becomes eligible for an abort action and Amazon S3 aborts the multipart upload. For more information, see Aborting Incomplete Multipart Uploads Using a Bucket Lifecycle Configuration.

    • Directory buckets - S3 Lifecycle is not supported by directory buckets.

    • Directory buckets - For directory buckets, you must make requests for this API operation to the Zonal endpoint. These endpoints support virtual-hosted-style requests in the format https://bucket-name.s3express-zone-id.region-code.amazonaws.com/key-name . Path-style requests are not supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Concepts for directory buckets in Local Zones in the Amazon S3 User Guide.

    Request signing

    For request signing, multipart upload is just a series of regular requests. You initiate a multipart upload, send one or more requests to upload parts, and then complete the multipart upload process. You sign each request individually. There is nothing special about signing multipart upload requests. For more information about signing, see Authenticating Requests (Amazon Web Services Signature Version 4) in the Amazon S3 User Guide.

    Permissions
    • General purpose bucket permissions - To perform a multipart upload with encryption using an Key Management Service (KMS) KMS key, the requester must have permission to the kms:Decrypt and kms:GenerateDataKey actions on the key. The requester must also have permissions for the kms:GenerateDataKey action for the CreateMultipartUpload API. Then, the requester needs permissions for the kms:Decrypt action on the UploadPart and UploadPartCopy APIs. These permissions are required because Amazon S3 must decrypt and read data from the encrypted file parts before it completes the multipart upload. For more information, see Multipart upload API and permissions and Protecting data using server-side encryption with Amazon Web Services KMS in the Amazon S3 User Guide.

    • Directory bucket permissions - To grant access to this API operation on a directory bucket, we recommend that you use the CreateSession API operation for session-based authorization. Specifically, you grant the s3express:CreateSession permission to the directory bucket in a bucket policy or an IAM identity-based policy. Then, you make the CreateSession API call on the bucket to obtain a session token. With the session token in your request header, you can make API requests to this operation. After the session token expires, you make another CreateSession API call to generate a new session token for use. Amazon Web Services CLI or SDKs create session and refresh the session token automatically to avoid service interruptions when a session expires. For more information about authorization, see CreateSession .

    Encryption
    • General purpose buckets - Server-side encryption is for data encryption at rest. Amazon S3 encrypts your data as it writes it to disks in its data centers and decrypts it when you access it. Amazon S3 automatically encrypts all new objects that are uploaded to an S3 bucket. When doing a multipart upload, if you don't specify encryption information in your request, the encryption setting of the uploaded parts is set to the default encryption configuration of the destination bucket. By default, all buckets have a base level of encryption configuration that uses server-side encryption with Amazon S3 managed keys (SSE-S3). If the destination bucket has a default encryption configuration that uses server-side encryption with an Key Management Service (KMS) key (SSE-KMS), or a customer-provided encryption key (SSE-C), Amazon S3 uses the corresponding KMS key, or a customer-provided key to encrypt the uploaded parts. When you perform a CreateMultipartUpload operation, if you want to use a different type of encryption setting for the uploaded parts, you can request that Amazon S3 encrypts the object with a different encryption key (such as an Amazon S3 managed key, a KMS key, or a customer-provided key). When the encryption setting in your request is different from the default encryption configuration of the destination bucket, the encryption setting in your request takes precedence. If you choose to provide your own encryption key, the request headers you provide in UploadPart and UploadPartCopy requests must match the headers you used in the CreateMultipartUpload request.

      • Use KMS keys (SSE-KMS) that include the Amazon Web Services managed key (aws/s3) and KMS customer managed keys stored in Key Management Service (KMS) – If you want Amazon Web Services to manage the keys used to encrypt data, specify the following headers in the request.

        • x-amz-server-side-encryption

        • x-amz-server-side-encryption-aws-kms-key-id

        • x-amz-server-side-encryption-context

        • If you specify x-amz-server-side-encryption:aws:kms, but don't provide x-amz-server-side-encryption-aws-kms-key-id, Amazon S3 uses the Amazon Web Services managed key (aws/s3 key) in KMS to protect the data.

        • To perform a multipart upload with encryption by using an Amazon Web Services KMS key, the requester must have permission to the kms:Decrypt and kms:GenerateDataKey* actions on the key. These permissions are required because Amazon S3 must decrypt and read data from the encrypted file parts before it completes the multipart upload. For more information, see Multipart upload API and permissions and Protecting data using server-side encryption with Amazon Web Services KMS in the Amazon S3 User Guide.

        • If your Identity and Access Management (IAM) user or role is in the same Amazon Web Services account as the KMS key, then you must have these permissions on the key policy. If your IAM user or role is in a different account from the key, then you must have the permissions on both the key policy and your IAM user or role.

        • All GET and PUT requests for an object protected by KMS fail if you don't make them by using Secure Sockets Layer (SSL), Transport Layer Security (TLS), or Signature Version 4. For information about configuring any of the officially supported Amazon Web Services SDKs and Amazon Web Services CLI, see Specifying the Signature Version in Request Authentication in the Amazon S3 User Guide.

        For more information about server-side encryption with KMS keys (SSE-KMS), see Protecting Data Using Server-Side Encryption with KMS keys in the Amazon S3 User Guide.

      • Use customer-provided encryption keys (SSE-C) – If you want to manage your own encryption keys, provide all the following headers in the request.

        • x-amz-server-side-encryption-customer-algorithm

        • x-amz-server-side-encryption-customer-key

        • x-amz-server-side-encryption-customer-key-MD5

        For more information about server-side encryption with customer-provided encryption keys (SSE-C), see Protecting data using server-side encryption with customer-provided encryption keys (SSE-C) in the Amazon S3 User Guide.

    • Directory buckets - For directory buckets, there are only two supported options for server-side encryption: server-side encryption with Amazon S3 managed keys (SSE-S3) (AES256) and server-side encryption with KMS keys (SSE-KMS) (aws:kms). We recommend that the bucket's default encryption uses the desired encryption configuration and you don't override the bucket default encryption in your CreateSession requests or PUT object requests. Then, new objects are automatically encrypted with the desired encryption settings. For more information, see Protecting data with server-side encryption in the Amazon S3 User Guide. For more information about the encryption overriding behaviors in directory buckets, see Specifying server-side encryption with KMS for new object uploads.

      In the Zonal endpoint API calls (except CopyObject and UploadPartCopy) using the REST API, the encryption request headers must match the encryption settings that are specified in the CreateSession request. You can't override the values of the encryption settings (x-amz-server-side-encryption, x-amz-server-side-encryption-aws-kms-key-id, x-amz-server-side-encryption-context, and x-amz-server-side-encryption-bucket-key-enabled) that are specified in the CreateSession request. You don't need to explicitly specify these encryption settings values in Zonal endpoint API calls, and Amazon S3 will use the encryption settings values from the CreateSession request to protect new objects in the directory bucket.

      When you use the CLI or the Amazon Web Services SDKs, for CreateSession, the session token refreshes automatically to avoid service interruptions when a session expires. The CLI or the Amazon Web Services SDKs use the bucket's default encryption configuration for the CreateSession request. It's not supported to override the encryption settings values in the CreateSession request. So in the Zonal endpoint API calls (except CopyObject and UploadPartCopy), the encryption request headers must match the default encryption configuration of the directory bucket.

      For directory buckets, when you perform a CreateMultipartUpload operation and an UploadPartCopy operation, the request headers you provide in the CreateMultipartUpload request must match the default encryption configuration of the destination bucket.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is Bucket-name.s3express-zone-id.region-code.amazonaws.com.

    The following operations are related to CreateMultipartUpload:

    ", + "documentation":"

    This action initiates a multipart upload and returns an upload ID. This upload ID is used to associate all of the parts in the specific multipart upload. You specify this upload ID in each of your subsequent upload part requests (see UploadPart). You also include this upload ID in the final request to either complete or abort the multipart upload request. For more information about multipart uploads, see Multipart Upload Overview in the Amazon S3 User Guide.

    After you initiate a multipart upload and upload one or more parts, to stop being charged for storing the uploaded parts, you must either complete or abort the multipart upload. Amazon S3 frees up the space used to store the parts and stops charging you for storing them only after you either complete or abort a multipart upload.

    If you have configured a lifecycle rule to abort incomplete multipart uploads, the created multipart upload must be completed within the number of days specified in the bucket lifecycle configuration. Otherwise, the incomplete multipart upload becomes eligible for an abort action and Amazon S3 aborts the multipart upload. For more information, see Aborting Incomplete Multipart Uploads Using a Bucket Lifecycle Configuration.

    • Directory buckets - S3 Lifecycle is not supported by directory buckets.

    • Directory buckets - For directory buckets, you must make requests for this API operation to the Zonal endpoint. These endpoints support virtual-hosted-style requests in the format https://bucket-name.s3express-zone-id.region-code.amazonaws.com/key-name . Path-style requests are not supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Available Local Zone for directory buckets in the Amazon S3 User Guide.

    Request signing

    For request signing, multipart upload is just a series of regular requests. You initiate a multipart upload, send one or more requests to upload parts, and then complete the multipart upload process. You sign each request individually. There is nothing special about signing multipart upload requests. For more information about signing, see Authenticating Requests (Amazon Web Services Signature Version 4) in the Amazon S3 User Guide.

    Permissions
    • General purpose bucket permissions - To perform a multipart upload with encryption using an Key Management Service (KMS) KMS key, the requester must have permission to the kms:Decrypt and kms:GenerateDataKey actions on the key. The requester must also have permissions for the kms:GenerateDataKey action for the CreateMultipartUpload API. Then, the requester needs permissions for the kms:Decrypt action on the UploadPart and UploadPartCopy APIs. These permissions are required because Amazon S3 must decrypt and read data from the encrypted file parts before it completes the multipart upload. For more information, see Multipart upload API and permissions and Protecting data using server-side encryption with Amazon Web Services KMS in the Amazon S3 User Guide.

    • Directory bucket permissions - To grant access to this API operation on a directory bucket, we recommend that you use the CreateSession API operation for session-based authorization. Specifically, you grant the s3express:CreateSession permission to the directory bucket in a bucket policy or an IAM identity-based policy. Then, you make the CreateSession API call on the bucket to obtain a session token. With the session token in your request header, you can make API requests to this operation. After the session token expires, you make another CreateSession API call to generate a new session token for use. Amazon Web Services CLI or SDKs create session and refresh the session token automatically to avoid service interruptions when a session expires. For more information about authorization, see CreateSession .

    Encryption
    • General purpose buckets - Server-side encryption is for data encryption at rest. Amazon S3 encrypts your data as it writes it to disks in its data centers and decrypts it when you access it. Amazon S3 automatically encrypts all new objects that are uploaded to an S3 bucket. When doing a multipart upload, if you don't specify encryption information in your request, the encryption setting of the uploaded parts is set to the default encryption configuration of the destination bucket. By default, all buckets have a base level of encryption configuration that uses server-side encryption with Amazon S3 managed keys (SSE-S3). If the destination bucket has a default encryption configuration that uses server-side encryption with an Key Management Service (KMS) key (SSE-KMS), or a customer-provided encryption key (SSE-C), Amazon S3 uses the corresponding KMS key, or a customer-provided key to encrypt the uploaded parts. When you perform a CreateMultipartUpload operation, if you want to use a different type of encryption setting for the uploaded parts, you can request that Amazon S3 encrypts the object with a different encryption key (such as an Amazon S3 managed key, a KMS key, or a customer-provided key). When the encryption setting in your request is different from the default encryption configuration of the destination bucket, the encryption setting in your request takes precedence. If you choose to provide your own encryption key, the request headers you provide in UploadPart and UploadPartCopy requests must match the headers you used in the CreateMultipartUpload request.

      • Use KMS keys (SSE-KMS) that include the Amazon Web Services managed key (aws/s3) and KMS customer managed keys stored in Key Management Service (KMS) – If you want Amazon Web Services to manage the keys used to encrypt data, specify the following headers in the request.

        • x-amz-server-side-encryption

        • x-amz-server-side-encryption-aws-kms-key-id

        • x-amz-server-side-encryption-context

        • If you specify x-amz-server-side-encryption:aws:kms, but don't provide x-amz-server-side-encryption-aws-kms-key-id, Amazon S3 uses the Amazon Web Services managed key (aws/s3 key) in KMS to protect the data.

        • To perform a multipart upload with encryption by using an Amazon Web Services KMS key, the requester must have permission to the kms:Decrypt and kms:GenerateDataKey* actions on the key. These permissions are required because Amazon S3 must decrypt and read data from the encrypted file parts before it completes the multipart upload. For more information, see Multipart upload API and permissions and Protecting data using server-side encryption with Amazon Web Services KMS in the Amazon S3 User Guide.

        • If your Identity and Access Management (IAM) user or role is in the same Amazon Web Services account as the KMS key, then you must have these permissions on the key policy. If your IAM user or role is in a different account from the key, then you must have the permissions on both the key policy and your IAM user or role.

        • All GET and PUT requests for an object protected by KMS fail if you don't make them by using Secure Sockets Layer (SSL), Transport Layer Security (TLS), or Signature Version 4. For information about configuring any of the officially supported Amazon Web Services SDKs and Amazon Web Services CLI, see Specifying the Signature Version in Request Authentication in the Amazon S3 User Guide.

        For more information about server-side encryption with KMS keys (SSE-KMS), see Protecting Data Using Server-Side Encryption with KMS keys in the Amazon S3 User Guide.

      • Use customer-provided encryption keys (SSE-C) – If you want to manage your own encryption keys, provide all the following headers in the request.

        • x-amz-server-side-encryption-customer-algorithm

        • x-amz-server-side-encryption-customer-key

        • x-amz-server-side-encryption-customer-key-MD5

        For more information about server-side encryption with customer-provided encryption keys (SSE-C), see Protecting data using server-side encryption with customer-provided encryption keys (SSE-C) in the Amazon S3 User Guide.

    • Directory buckets - For directory buckets, there are only two supported options for server-side encryption: server-side encryption with Amazon S3 managed keys (SSE-S3) (AES256) and server-side encryption with KMS keys (SSE-KMS) (aws:kms). We recommend that the bucket's default encryption uses the desired encryption configuration and you don't override the bucket default encryption in your CreateSession requests or PUT object requests. Then, new objects are automatically encrypted with the desired encryption settings. For more information, see Protecting data with server-side encryption in the Amazon S3 User Guide. For more information about the encryption overriding behaviors in directory buckets, see Specifying server-side encryption with KMS for new object uploads.

      In the Zonal endpoint API calls (except CopyObject and UploadPartCopy) using the REST API, the encryption request headers must match the encryption settings that are specified in the CreateSession request. You can't override the values of the encryption settings (x-amz-server-side-encryption, x-amz-server-side-encryption-aws-kms-key-id, x-amz-server-side-encryption-context, and x-amz-server-side-encryption-bucket-key-enabled) that are specified in the CreateSession request. You don't need to explicitly specify these encryption settings values in Zonal endpoint API calls, and Amazon S3 will use the encryption settings values from the CreateSession request to protect new objects in the directory bucket.

      When you use the CLI or the Amazon Web Services SDKs, for CreateSession, the session token refreshes automatically to avoid service interruptions when a session expires. The CLI or the Amazon Web Services SDKs use the bucket's default encryption configuration for the CreateSession request. It's not supported to override the encryption settings values in the CreateSession request. So in the Zonal endpoint API calls (except CopyObject and UploadPartCopy), the encryption request headers must match the default encryption configuration of the directory bucket.

      For directory buckets, when you perform a CreateMultipartUpload operation and an UploadPartCopy operation, the request headers you provide in the CreateMultipartUpload request must match the default encryption configuration of the destination bucket.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is Bucket-name.s3express-zone-id.region-code.amazonaws.com.

    The following operations are related to CreateMultipartUpload:

    ", "alias":"InitiateMultipartUpload" }, "CreateSession":{ @@ -118,7 +118,7 @@ "errors":[ {"shape":"NoSuchBucket"} ], - "documentation":"

    Creates a session that establishes temporary security credentials to support fast authentication and authorization for the Zonal endpoint API operations on directory buckets. For more information about Zonal endpoint API operations that include the Availability Zone in the request endpoint, see S3 Express One Zone APIs in the Amazon S3 User Guide.

    To make Zonal endpoint API requests on a directory bucket, use the CreateSession API operation. Specifically, you grant s3express:CreateSession permission to a bucket in a bucket policy or an IAM identity-based policy. Then, you use IAM credentials to make the CreateSession API request on the bucket, which returns temporary security credentials that include the access key ID, secret access key, session token, and expiration. These credentials have associated permissions to access the Zonal endpoint API operations. After the session is created, you don’t need to use other policies to grant permissions to each Zonal endpoint API individually. Instead, in your Zonal endpoint API requests, you sign your requests by applying the temporary security credentials of the session to the request headers and following the SigV4 protocol for authentication. You also apply the session token to the x-amz-s3session-token request header for authorization. Temporary security credentials are scoped to the bucket and expire after 5 minutes. After the expiration time, any calls that you make with those credentials will fail. You must use IAM credentials again to make a CreateSession API request that generates a new set of temporary credentials for use. Temporary credentials cannot be extended or refreshed beyond the original specified interval.

    If you use Amazon Web Services SDKs, SDKs handle the session token refreshes automatically to avoid service interruptions when a session expires. We recommend that you use the Amazon Web Services SDKs to initiate and manage requests to the CreateSession API. For more information, see Performance guidelines and design patterns in the Amazon S3 User Guide.

    • You must make requests for this API operation to the Zonal endpoint. These endpoints support virtual-hosted-style requests in the format https://bucket-name.s3express-zone-id.region-code.amazonaws.com. Path-style requests are not supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Concepts for directory buckets in Local Zones in the Amazon S3 User Guide.

    • CopyObject API operation - Unlike other Zonal endpoint API operations, the CopyObject API operation doesn't use the temporary security credentials returned from the CreateSession API operation for authentication and authorization. For information about authentication and authorization of the CopyObject API operation on directory buckets, see CopyObject.

    • HeadBucket API operation - Unlike other Zonal endpoint API operations, the HeadBucket API operation doesn't use the temporary security credentials returned from the CreateSession API operation for authentication and authorization. For information about authentication and authorization of the HeadBucket API operation on directory buckets, see HeadBucket.

    Permissions

    To obtain temporary security credentials, you must create a bucket policy or an IAM identity-based policy that grants s3express:CreateSession permission to the bucket. In a policy, you can have the s3express:SessionMode condition key to control who can create a ReadWrite or ReadOnly session. For more information about ReadWrite or ReadOnly sessions, see x-amz-create-session-mode . For example policies, see Example bucket policies for S3 Express One Zone and Amazon Web Services Identity and Access Management (IAM) identity-based policies for S3 Express One Zone in the Amazon S3 User Guide.

    To grant cross-account access to Zonal endpoint API operations, the bucket policy should also grant both accounts the s3express:CreateSession permission.

    If you want to encrypt objects with SSE-KMS, you must also have the kms:GenerateDataKey and the kms:Decrypt permissions in IAM identity-based policies and KMS key policies for the target KMS key.

    Encryption

    For directory buckets, there are only two supported options for server-side encryption: server-side encryption with Amazon S3 managed keys (SSE-S3) (AES256) and server-side encryption with KMS keys (SSE-KMS) (aws:kms). We recommend that the bucket's default encryption uses the desired encryption configuration and you don't override the bucket default encryption in your CreateSession requests or PUT object requests. Then, new objects are automatically encrypted with the desired encryption settings. For more information, see Protecting data with server-side encryption in the Amazon S3 User Guide. For more information about the encryption overriding behaviors in directory buckets, see Specifying server-side encryption with KMS for new object uploads.

    For Zonal endpoint (object-level) API operations except CopyObject and UploadPartCopy, you authenticate and authorize requests through CreateSession for low latency. To encrypt new objects in a directory bucket with SSE-KMS, you must specify SSE-KMS as the directory bucket's default encryption configuration with a KMS key (specifically, a customer managed key). Then, when a session is created for Zonal endpoint API operations, new objects are automatically encrypted and decrypted with SSE-KMS and S3 Bucket Keys during the session.

    Only 1 customer managed key is supported per directory bucket for the lifetime of the bucket. The Amazon Web Services managed key (aws/s3) isn't supported. After you specify SSE-KMS as your bucket's default encryption configuration with a customer managed key, you can't change the customer managed key for the bucket's SSE-KMS configuration.

    In the Zonal endpoint API calls (except CopyObject and UploadPartCopy) using the REST API, you can't override the values of the encryption settings (x-amz-server-side-encryption, x-amz-server-side-encryption-aws-kms-key-id, x-amz-server-side-encryption-context, and x-amz-server-side-encryption-bucket-key-enabled) from the CreateSession request. You don't need to explicitly specify these encryption settings values in Zonal endpoint API calls, and Amazon S3 will use the encryption settings values from the CreateSession request to protect new objects in the directory bucket.

    When you use the CLI or the Amazon Web Services SDKs, for CreateSession, the session token refreshes automatically to avoid service interruptions when a session expires. The CLI or the Amazon Web Services SDKs use the bucket's default encryption configuration for the CreateSession request. It's not supported to override the encryption settings values in the CreateSession request. Also, in the Zonal endpoint API calls (except CopyObject and UploadPartCopy), it's not supported to override the values of the encryption settings from the CreateSession request.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is Bucket-name.s3express-zone-id.region-code.amazonaws.com.

    ", + "documentation":"

    Creates a session that establishes temporary security credentials to support fast authentication and authorization for the Zonal endpoint API operations on directory buckets. For more information about Zonal endpoint API operations that include the Availability Zone in the request endpoint, see S3 Express One Zone APIs in the Amazon S3 User Guide.

    To make Zonal endpoint API requests on a directory bucket, use the CreateSession API operation. Specifically, you grant s3express:CreateSession permission to a bucket in a bucket policy or an IAM identity-based policy. Then, you use IAM credentials to make the CreateSession API request on the bucket, which returns temporary security credentials that include the access key ID, secret access key, session token, and expiration. These credentials have associated permissions to access the Zonal endpoint API operations. After the session is created, you don’t need to use other policies to grant permissions to each Zonal endpoint API individually. Instead, in your Zonal endpoint API requests, you sign your requests by applying the temporary security credentials of the session to the request headers and following the SigV4 protocol for authentication. You also apply the session token to the x-amz-s3session-token request header for authorization. Temporary security credentials are scoped to the bucket and expire after 5 minutes. After the expiration time, any calls that you make with those credentials will fail. You must use IAM credentials again to make a CreateSession API request that generates a new set of temporary credentials for use. Temporary credentials cannot be extended or refreshed beyond the original specified interval.

    If you use Amazon Web Services SDKs, SDKs handle the session token refreshes automatically to avoid service interruptions when a session expires. We recommend that you use the Amazon Web Services SDKs to initiate and manage requests to the CreateSession API. For more information, see Performance guidelines and design patterns in the Amazon S3 User Guide.

    • You must make requests for this API operation to the Zonal endpoint. These endpoints support virtual-hosted-style requests in the format https://bucket-name.s3express-zone-id.region-code.amazonaws.com. Path-style requests are not supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Available Local Zone for directory buckets in the Amazon S3 User Guide.

    • CopyObject API operation - Unlike other Zonal endpoint API operations, the CopyObject API operation doesn't use the temporary security credentials returned from the CreateSession API operation for authentication and authorization. For information about authentication and authorization of the CopyObject API operation on directory buckets, see CopyObject.

    • HeadBucket API operation - Unlike other Zonal endpoint API operations, the HeadBucket API operation doesn't use the temporary security credentials returned from the CreateSession API operation for authentication and authorization. For information about authentication and authorization of the HeadBucket API operation on directory buckets, see HeadBucket.

    Permissions

    To obtain temporary security credentials, you must create a bucket policy or an IAM identity-based policy that grants s3express:CreateSession permission to the bucket. In a policy, you can have the s3express:SessionMode condition key to control who can create a ReadWrite or ReadOnly session. For more information about ReadWrite or ReadOnly sessions, see x-amz-create-session-mode . For example policies, see Example bucket policies for S3 Express One Zone and Amazon Web Services Identity and Access Management (IAM) identity-based policies for S3 Express One Zone in the Amazon S3 User Guide.

    To grant cross-account access to Zonal endpoint API operations, the bucket policy should also grant both accounts the s3express:CreateSession permission.

    If you want to encrypt objects with SSE-KMS, you must also have the kms:GenerateDataKey and the kms:Decrypt permissions in IAM identity-based policies and KMS key policies for the target KMS key.

    Encryption

    For directory buckets, there are only two supported options for server-side encryption: server-side encryption with Amazon S3 managed keys (SSE-S3) (AES256) and server-side encryption with KMS keys (SSE-KMS) (aws:kms). We recommend that the bucket's default encryption uses the desired encryption configuration and you don't override the bucket default encryption in your CreateSession requests or PUT object requests. Then, new objects are automatically encrypted with the desired encryption settings. For more information, see Protecting data with server-side encryption in the Amazon S3 User Guide. For more information about the encryption overriding behaviors in directory buckets, see Specifying server-side encryption with KMS for new object uploads.

    For Zonal endpoint (object-level) API operations except CopyObject and UploadPartCopy, you authenticate and authorize requests through CreateSession for low latency. To encrypt new objects in a directory bucket with SSE-KMS, you must specify SSE-KMS as the directory bucket's default encryption configuration with a KMS key (specifically, a customer managed key). Then, when a session is created for Zonal endpoint API operations, new objects are automatically encrypted and decrypted with SSE-KMS and S3 Bucket Keys during the session.

    Only 1 customer managed key is supported per directory bucket for the lifetime of the bucket. The Amazon Web Services managed key (aws/s3) isn't supported. After you specify SSE-KMS as your bucket's default encryption configuration with a customer managed key, you can't change the customer managed key for the bucket's SSE-KMS configuration.

    In the Zonal endpoint API calls (except CopyObject and UploadPartCopy) using the REST API, you can't override the values of the encryption settings (x-amz-server-side-encryption, x-amz-server-side-encryption-aws-kms-key-id, x-amz-server-side-encryption-context, and x-amz-server-side-encryption-bucket-key-enabled) from the CreateSession request. You don't need to explicitly specify these encryption settings values in Zonal endpoint API calls, and Amazon S3 will use the encryption settings values from the CreateSession request to protect new objects in the directory bucket.

    When you use the CLI or the Amazon Web Services SDKs, for CreateSession, the session token refreshes automatically to avoid service interruptions when a session expires. The CLI or the Amazon Web Services SDKs use the bucket's default encryption configuration for the CreateSession request. It's not supported to override the encryption settings values in the CreateSession request. Also, in the Zonal endpoint API calls (except CopyObject and UploadPartCopy), it's not supported to override the values of the encryption settings from the CreateSession request.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is Bucket-name.s3express-zone-id.region-code.amazonaws.com.

    ", "staticContextParams":{ "DisableS3ExpressSessionAuth":{"value":true} } @@ -132,7 +132,7 @@ }, "input":{"shape":"DeleteBucketRequest"}, "documentationUrl":"http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketDELETE.html", - "documentation":"

    Deletes the S3 bucket. All objects (including all object versions and delete markers) in the bucket must be deleted before the bucket itself can be deleted.

    • Directory buckets - If multipart uploads in a directory bucket are in progress, you can't delete the bucket until all the in-progress multipart uploads are aborted or completed.

    • Directory buckets - For directory buckets, you must make requests for this API operation to the Regional endpoint. These endpoints support path-style requests in the format https://s3express-control.region-code.amazonaws.com/bucket-name . Virtual-hosted-style requests aren't supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Concepts for directory buckets in Local Zones in the Amazon S3 User Guide.

    Permissions
    • General purpose bucket permissions - You must have the s3:DeleteBucket permission on the specified bucket in a policy.

    • Directory bucket permissions - You must have the s3express:DeleteBucket permission in an IAM identity-based policy instead of a bucket policy. Cross-account access to this API operation isn't supported. This operation can only be performed by the Amazon Web Services account that owns the resource. For more information about directory bucket policies and permissions, see Amazon Web Services Identity and Access Management (IAM) for S3 Express One Zone in the Amazon S3 User Guide.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is s3express-control.region-code.amazonaws.com.

    The following operations are related to DeleteBucket:

    ", + "documentation":"

    Deletes the S3 bucket. All objects (including all object versions and delete markers) in the bucket must be deleted before the bucket itself can be deleted.

    • Directory buckets - If multipart uploads in a directory bucket are in progress, you can't delete the bucket until all the in-progress multipart uploads are aborted or completed.

    • Directory buckets - For directory buckets, you must make requests for this API operation to the Regional endpoint. These endpoints support path-style requests in the format https://s3express-control.region-code.amazonaws.com/bucket-name . Virtual-hosted-style requests aren't supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Available Local Zone for directory buckets in the Amazon S3 User Guide.

    Permissions
    • General purpose bucket permissions - You must have the s3:DeleteBucket permission on the specified bucket in a policy.

    • Directory bucket permissions - You must have the s3express:DeleteBucket permission in an IAM identity-based policy instead of a bucket policy. Cross-account access to this API operation isn't supported. This operation can only be performed by the Amazon Web Services account that owns the resource. For more information about directory bucket policies and permissions, see Amazon Web Services Identity and Access Management (IAM) for S3 Express One Zone in the Amazon S3 User Guide.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is s3express-control.region-code.amazonaws.com.

    The following operations are related to DeleteBucket:

    ", "staticContextParams":{ "UseS3ExpressControlEndpoint":{"value":true} } @@ -212,7 +212,7 @@ }, "input":{"shape":"DeleteBucketLifecycleRequest"}, "documentationUrl":"http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketDELETElifecycle.html", - "documentation":"

    Deletes the lifecycle configuration from the specified bucket. Amazon S3 removes all the lifecycle configuration rules in the lifecycle subresource associated with the bucket. Your objects never expire, and Amazon S3 no longer automatically deletes any objects on the basis of rules contained in the deleted lifecycle configuration.

    Permissions
    • General purpose bucket permissions - By default, all Amazon S3 resources are private, including buckets, objects, and related subresources (for example, lifecycle configuration and website configuration). Only the resource owner (that is, the Amazon Web Services account that created it) can access the resource. The resource owner can optionally grant access permissions to others by writing an access policy. For this operation, a user must have the s3:PutLifecycleConfiguration permission.

      For more information about permissions, see Managing Access Permissions to Your Amazon S3 Resources.

    • Directory bucket permissions - You must have the s3express:PutLifecycleConfiguration permission in an IAM identity-based policy to use this operation. Cross-account access to this API operation isn't supported. The resource owner can optionally grant access permissions to others by creating a role or user for them as long as they are within the same account as the owner and resource.

      For more information about directory bucket policies and permissions, see Authorizing Regional endpoint APIs with IAM in the Amazon S3 User Guide.

      Directory buckets - For directory buckets, you must make requests for this API operation to the Regional endpoint. These endpoints support path-style requests in the format https://s3express-control.region-code.amazonaws.com/bucket-name . Virtual-hosted-style requests aren't supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Concepts for directory buckets in Local Zones in the Amazon S3 User Guide.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is s3express-control.region.amazonaws.com.

    For more information about the object expiration, see Elements to Describe Lifecycle Actions.

    Related actions include:

    ", + "documentation":"

    Deletes the lifecycle configuration from the specified bucket. Amazon S3 removes all the lifecycle configuration rules in the lifecycle subresource associated with the bucket. Your objects never expire, and Amazon S3 no longer automatically deletes any objects on the basis of rules contained in the deleted lifecycle configuration.

    Permissions
    • General purpose bucket permissions - By default, all Amazon S3 resources are private, including buckets, objects, and related subresources (for example, lifecycle configuration and website configuration). Only the resource owner (that is, the Amazon Web Services account that created it) can access the resource. The resource owner can optionally grant access permissions to others by writing an access policy. For this operation, a user must have the s3:PutLifecycleConfiguration permission.

      For more information about permissions, see Managing Access Permissions to Your Amazon S3 Resources.

    • Directory bucket permissions - You must have the s3express:PutLifecycleConfiguration permission in an IAM identity-based policy to use this operation. Cross-account access to this API operation isn't supported. The resource owner can optionally grant access permissions to others by creating a role or user for them as long as they are within the same account as the owner and resource.

      For more information about directory bucket policies and permissions, see Authorizing Regional endpoint APIs with IAM in the Amazon S3 User Guide.

      Directory buckets - For directory buckets, you must make requests for this API operation to the Regional endpoint. These endpoints support path-style requests in the format https://s3express-control.region-code.amazonaws.com/bucket-name . Virtual-hosted-style requests aren't supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Available Local Zone for directory buckets in the Amazon S3 User Guide.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is s3express-control.region.amazonaws.com.

    For more information about the object expiration, see Elements to Describe Lifecycle Actions.

    Related actions include:

    ", "staticContextParams":{ "UseS3ExpressControlEndpoint":{"value":true} } @@ -265,7 +265,7 @@ }, "input":{"shape":"DeleteBucketPolicyRequest"}, "documentationUrl":"http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketDELETEpolicy.html", - "documentation":"

    Deletes the policy of a specified bucket.

    Directory buckets - For directory buckets, you must make requests for this API operation to the Regional endpoint. These endpoints support path-style requests in the format https://s3express-control.region-code.amazonaws.com/bucket-name . Virtual-hosted-style requests aren't supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Concepts for directory buckets in Local Zones in the Amazon S3 User Guide.

    Permissions

    If you are using an identity other than the root user of the Amazon Web Services account that owns the bucket, the calling identity must both have the DeleteBucketPolicy permissions on the specified bucket and belong to the bucket owner's account in order to use this operation.

    If you don't have DeleteBucketPolicy permissions, Amazon S3 returns a 403 Access Denied error. If you have the correct permissions, but you're not using an identity that belongs to the bucket owner's account, Amazon S3 returns a 405 Method Not Allowed error.

    To ensure that bucket owners don't inadvertently lock themselves out of their own buckets, the root principal in a bucket owner's Amazon Web Services account can perform the GetBucketPolicy, PutBucketPolicy, and DeleteBucketPolicy API actions, even if their bucket policy explicitly denies the root principal's access. Bucket owner root principals can only be blocked from performing these API actions by VPC endpoint policies and Amazon Web Services Organizations policies.

    • General purpose bucket permissions - The s3:DeleteBucketPolicy permission is required in a policy. For more information about general purpose buckets bucket policies, see Using Bucket Policies and User Policies in the Amazon S3 User Guide.

    • Directory bucket permissions - To grant access to this API operation, you must have the s3express:DeleteBucketPolicy permission in an IAM identity-based policy instead of a bucket policy. Cross-account access to this API operation isn't supported. This operation can only be performed by the Amazon Web Services account that owns the resource. For more information about directory bucket policies and permissions, see Amazon Web Services Identity and Access Management (IAM) for S3 Express One Zone in the Amazon S3 User Guide.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is s3express-control.region-code.amazonaws.com.

    The following operations are related to DeleteBucketPolicy

    ", + "documentation":"

    Deletes the policy of a specified bucket.

    Directory buckets - For directory buckets, you must make requests for this API operation to the Regional endpoint. These endpoints support path-style requests in the format https://s3express-control.region-code.amazonaws.com/bucket-name . Virtual-hosted-style requests aren't supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Available Local Zone for directory buckets in the Amazon S3 User Guide.

    Permissions

    If you are using an identity other than the root user of the Amazon Web Services account that owns the bucket, the calling identity must both have the DeleteBucketPolicy permissions on the specified bucket and belong to the bucket owner's account in order to use this operation.

    If you don't have DeleteBucketPolicy permissions, Amazon S3 returns a 403 Access Denied error. If you have the correct permissions, but you're not using an identity that belongs to the bucket owner's account, Amazon S3 returns a 405 Method Not Allowed error.

    To ensure that bucket owners don't inadvertently lock themselves out of their own buckets, the root principal in a bucket owner's Amazon Web Services account can perform the GetBucketPolicy, PutBucketPolicy, and DeleteBucketPolicy API actions, even if their bucket policy explicitly denies the root principal's access. Bucket owner root principals can only be blocked from performing these API actions by VPC endpoint policies and Amazon Web Services Organizations policies.

    • General purpose bucket permissions - The s3:DeleteBucketPolicy permission is required in a policy. For more information about general purpose buckets bucket policies, see Using Bucket Policies and User Policies in the Amazon S3 User Guide.

    • Directory bucket permissions - To grant access to this API operation, you must have the s3express:DeleteBucketPolicy permission in an IAM identity-based policy instead of a bucket policy. Cross-account access to this API operation isn't supported. This operation can only be performed by the Amazon Web Services account that owns the resource. For more information about directory bucket policies and permissions, see Amazon Web Services Identity and Access Management (IAM) for S3 Express One Zone in the Amazon S3 User Guide.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is s3express-control.region-code.amazonaws.com.

    The following operations are related to DeleteBucketPolicy

    ", "staticContextParams":{ "UseS3ExpressControlEndpoint":{"value":true} } @@ -321,7 +321,7 @@ "input":{"shape":"DeleteObjectRequest"}, "output":{"shape":"DeleteObjectOutput"}, "documentationUrl":"http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTObjectDELETE.html", - "documentation":"

    Removes an object from a bucket. The behavior depends on the bucket's versioning state:

    • If bucket versioning is not enabled, the operation permanently deletes the object.

    • If bucket versioning is enabled, the operation inserts a delete marker, which becomes the current version of the object. To permanently delete an object in a versioned bucket, you must include the object’s versionId in the request. For more information about versioning-enabled buckets, see Deleting object versions from a versioning-enabled bucket.

    • If bucket versioning is suspended, the operation removes the object that has a null versionId, if there is one, and inserts a delete marker that becomes the current version of the object. If there isn't an object with a null versionId, and all versions of the object have a versionId, Amazon S3 does not remove the object and only inserts a delete marker. To permanently delete an object that has a versionId, you must include the object’s versionId in the request. For more information about versioning-suspended buckets, see Deleting objects from versioning-suspended buckets.

    • Directory buckets - S3 Versioning isn't enabled and supported for directory buckets. For this API operation, only the null value of the version ID is supported by directory buckets. You can only specify null to the versionId query parameter in the request.

    • Directory buckets - For directory buckets, you must make requests for this API operation to the Zonal endpoint. These endpoints support virtual-hosted-style requests in the format https://bucket-name.s3express-zone-id.region-code.amazonaws.com/key-name . Path-style requests are not supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Concepts for directory buckets in Local Zones in the Amazon S3 User Guide.

    To remove a specific version, you must use the versionId query parameter. Using this query parameter permanently deletes the version. If the object deleted is a delete marker, Amazon S3 sets the response header x-amz-delete-marker to true.

    If the object you want to delete is in a bucket where the bucket versioning configuration is MFA Delete enabled, you must include the x-amz-mfa request header in the DELETE versionId request. Requests that include x-amz-mfa must use HTTPS. For more information about MFA Delete, see Using MFA Delete in the Amazon S3 User Guide. To see sample requests that use versioning, see Sample Request.

    Directory buckets - MFA delete is not supported by directory buckets.

    You can delete objects by explicitly calling DELETE Object or calling (PutBucketLifecycle) to enable Amazon S3 to remove them for you. If you want to block users or accounts from removing or deleting objects from your bucket, you must deny them the s3:DeleteObject, s3:DeleteObjectVersion, and s3:PutLifeCycleConfiguration actions.

    Directory buckets - S3 Lifecycle is not supported by directory buckets.

    Permissions
    • General purpose bucket permissions - The following permissions are required in your policies when your DeleteObjects request includes specific headers.

      • s3:DeleteObject - To delete an object from a bucket, you must always have the s3:DeleteObject permission.

      • s3:DeleteObjectVersion - To delete a specific version of an object from a versioning-enabled bucket, you must have the s3:DeleteObjectVersion permission.

    • Directory bucket permissions - To grant access to this API operation on a directory bucket, we recommend that you use the CreateSession API operation for session-based authorization. Specifically, you grant the s3express:CreateSession permission to the directory bucket in a bucket policy or an IAM identity-based policy. Then, you make the CreateSession API call on the bucket to obtain a session token. With the session token in your request header, you can make API requests to this operation. After the session token expires, you make another CreateSession API call to generate a new session token for use. Amazon Web Services CLI or SDKs create session and refresh the session token automatically to avoid service interruptions when a session expires. For more information about authorization, see CreateSession .

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is Bucket-name.s3express-zone-id.region-code.amazonaws.com.

    The following action is related to DeleteObject:

    " + "documentation":"

    Removes an object from a bucket. The behavior depends on the bucket's versioning state:

    • If bucket versioning is not enabled, the operation permanently deletes the object.

    • If bucket versioning is enabled, the operation inserts a delete marker, which becomes the current version of the object. To permanently delete an object in a versioned bucket, you must include the object’s versionId in the request. For more information about versioning-enabled buckets, see Deleting object versions from a versioning-enabled bucket.

    • If bucket versioning is suspended, the operation removes the object that has a null versionId, if there is one, and inserts a delete marker that becomes the current version of the object. If there isn't an object with a null versionId, and all versions of the object have a versionId, Amazon S3 does not remove the object and only inserts a delete marker. To permanently delete an object that has a versionId, you must include the object’s versionId in the request. For more information about versioning-suspended buckets, see Deleting objects from versioning-suspended buckets.

    • Directory buckets - S3 Versioning isn't enabled and supported for directory buckets. For this API operation, only the null value of the version ID is supported by directory buckets. You can only specify null to the versionId query parameter in the request.

    • Directory buckets - For directory buckets, you must make requests for this API operation to the Zonal endpoint. These endpoints support virtual-hosted-style requests in the format https://bucket-name.s3express-zone-id.region-code.amazonaws.com/key-name . Path-style requests are not supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Available Local Zone for directory buckets in the Amazon S3 User Guide.

    To remove a specific version, you must use the versionId query parameter. Using this query parameter permanently deletes the version. If the object deleted is a delete marker, Amazon S3 sets the response header x-amz-delete-marker to true.

    If the object you want to delete is in a bucket where the bucket versioning configuration is MFA Delete enabled, you must include the x-amz-mfa request header in the DELETE versionId request. Requests that include x-amz-mfa must use HTTPS. For more information about MFA Delete, see Using MFA Delete in the Amazon S3 User Guide. To see sample requests that use versioning, see Sample Request.

    Directory buckets - MFA delete is not supported by directory buckets.

    You can delete objects by explicitly calling DELETE Object or calling (PutBucketLifecycle) to enable Amazon S3 to remove them for you. If you want to block users or accounts from removing or deleting objects from your bucket, you must deny them the s3:DeleteObject, s3:DeleteObjectVersion, and s3:PutLifeCycleConfiguration actions.

    Directory buckets - S3 Lifecycle is not supported by directory buckets.

    Permissions
    • General purpose bucket permissions - The following permissions are required in your policies when your DeleteObjects request includes specific headers.

      • s3:DeleteObject - To delete an object from a bucket, you must always have the s3:DeleteObject permission.

      • s3:DeleteObjectVersion - To delete a specific version of an object from a versioning-enabled bucket, you must have the s3:DeleteObjectVersion permission.

    • Directory bucket permissions - To grant access to this API operation on a directory bucket, we recommend that you use the CreateSession API operation for session-based authorization. Specifically, you grant the s3express:CreateSession permission to the directory bucket in a bucket policy or an IAM identity-based policy. Then, you make the CreateSession API call on the bucket to obtain a session token. With the session token in your request header, you can make API requests to this operation. After the session token expires, you make another CreateSession API call to generate a new session token for use. Amazon Web Services CLI or SDKs create session and refresh the session token automatically to avoid service interruptions when a session expires. For more information about authorization, see CreateSession .

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is Bucket-name.s3express-zone-id.region-code.amazonaws.com.

    The following action is related to DeleteObject:

    " }, "DeleteObjectTagging":{ "name":"DeleteObjectTagging", @@ -343,7 +343,7 @@ "input":{"shape":"DeleteObjectsRequest"}, "output":{"shape":"DeleteObjectsOutput"}, "documentationUrl":"http://docs.amazonwebservices.com/AmazonS3/latest/API/multiobjectdeleteapi.html", - "documentation":"

    This operation enables you to delete multiple objects from a bucket using a single HTTP request. If you know the object keys that you want to delete, then this operation provides a suitable alternative to sending individual delete requests, reducing per-request overhead.

    The request can contain a list of up to 1000 keys that you want to delete. In the XML, you provide the object key names, and optionally, version IDs if you want to delete a specific version of the object from a versioning-enabled bucket. For each key, Amazon S3 performs a delete operation and returns the result of that delete, success or failure, in the response. Note that if the object specified in the request is not found, Amazon S3 returns the result as deleted.

    • Directory buckets - S3 Versioning isn't enabled and supported for directory buckets.

    • Directory buckets - For directory buckets, you must make requests for this API operation to the Zonal endpoint. These endpoints support virtual-hosted-style requests in the format https://bucket-name.s3express-zone-id.region-code.amazonaws.com/key-name . Path-style requests are not supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Concepts for directory buckets in Local Zones in the Amazon S3 User Guide.

    The operation supports two modes for the response: verbose and quiet. By default, the operation uses verbose mode in which the response includes the result of deletion of each key in your request. In quiet mode the response includes only keys where the delete operation encountered an error. For a successful deletion in a quiet mode, the operation does not return any information about the delete in the response body.

    When performing this action on an MFA Delete enabled bucket, that attempts to delete any versioned objects, you must include an MFA token. If you do not provide one, the entire request will fail, even if there are non-versioned objects you are trying to delete. If you provide an invalid token, whether there are versioned keys in the request or not, the entire Multi-Object Delete request will fail. For information about MFA Delete, see MFA Delete in the Amazon S3 User Guide.

    Directory buckets - MFA delete is not supported by directory buckets.

    Permissions
    • General purpose bucket permissions - The following permissions are required in your policies when your DeleteObjects request includes specific headers.

      • s3:DeleteObject - To delete an object from a bucket, you must always specify the s3:DeleteObject permission.

      • s3:DeleteObjectVersion - To delete a specific version of an object from a versioning-enabled bucket, you must specify the s3:DeleteObjectVersion permission.

    • Directory bucket permissions - To grant access to this API operation on a directory bucket, we recommend that you use the CreateSession API operation for session-based authorization. Specifically, you grant the s3express:CreateSession permission to the directory bucket in a bucket policy or an IAM identity-based policy. Then, you make the CreateSession API call on the bucket to obtain a session token. With the session token in your request header, you can make API requests to this operation. After the session token expires, you make another CreateSession API call to generate a new session token for use. Amazon Web Services CLI or SDKs create session and refresh the session token automatically to avoid service interruptions when a session expires. For more information about authorization, see CreateSession .

    Content-MD5 request header
    • General purpose bucket - The Content-MD5 request header is required for all Multi-Object Delete requests. Amazon S3 uses the header value to ensure that your request body has not been altered in transit.

    • Directory bucket - The Content-MD5 request header or a additional checksum request header (including x-amz-checksum-crc32, x-amz-checksum-crc32c, x-amz-checksum-sha1, or x-amz-checksum-sha256) is required for all Multi-Object Delete requests.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is Bucket-name.s3express-zone-id.region-code.amazonaws.com.

    The following operations are related to DeleteObjects:

    ", + "documentation":"

    This operation enables you to delete multiple objects from a bucket using a single HTTP request. If you know the object keys that you want to delete, then this operation provides a suitable alternative to sending individual delete requests, reducing per-request overhead.

    The request can contain a list of up to 1000 keys that you want to delete. In the XML, you provide the object key names, and optionally, version IDs if you want to delete a specific version of the object from a versioning-enabled bucket. For each key, Amazon S3 performs a delete operation and returns the result of that delete, success or failure, in the response. Note that if the object specified in the request is not found, Amazon S3 returns the result as deleted.

    • Directory buckets - S3 Versioning isn't enabled and supported for directory buckets.

    • Directory buckets - For directory buckets, you must make requests for this API operation to the Zonal endpoint. These endpoints support virtual-hosted-style requests in the format https://bucket-name.s3express-zone-id.region-code.amazonaws.com/key-name . Path-style requests are not supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Available Local Zone for directory buckets in the Amazon S3 User Guide.

    The operation supports two modes for the response: verbose and quiet. By default, the operation uses verbose mode in which the response includes the result of deletion of each key in your request. In quiet mode the response includes only keys where the delete operation encountered an error. For a successful deletion in a quiet mode, the operation does not return any information about the delete in the response body.

    When performing this action on an MFA Delete enabled bucket, that attempts to delete any versioned objects, you must include an MFA token. If you do not provide one, the entire request will fail, even if there are non-versioned objects you are trying to delete. If you provide an invalid token, whether there are versioned keys in the request or not, the entire Multi-Object Delete request will fail. For information about MFA Delete, see MFA Delete in the Amazon S3 User Guide.

    Directory buckets - MFA delete is not supported by directory buckets.

    Permissions
    • General purpose bucket permissions - The following permissions are required in your policies when your DeleteObjects request includes specific headers.

      • s3:DeleteObject - To delete an object from a bucket, you must always specify the s3:DeleteObject permission.

      • s3:DeleteObjectVersion - To delete a specific version of an object from a versioning-enabled bucket, you must specify the s3:DeleteObjectVersion permission.

    • Directory bucket permissions - To grant access to this API operation on a directory bucket, we recommend that you use the CreateSession API operation for session-based authorization. Specifically, you grant the s3express:CreateSession permission to the directory bucket in a bucket policy or an IAM identity-based policy. Then, you make the CreateSession API call on the bucket to obtain a session token. With the session token in your request header, you can make API requests to this operation. After the session token expires, you make another CreateSession API call to generate a new session token for use. Amazon Web Services CLI or SDKs create session and refresh the session token automatically to avoid service interruptions when a session expires. For more information about authorization, see CreateSession .

    Content-MD5 request header
    • General purpose bucket - The Content-MD5 request header is required for all Multi-Object Delete requests. Amazon S3 uses the header value to ensure that your request body has not been altered in transit.

    • Directory bucket - The Content-MD5 request header or a additional checksum request header (including x-amz-checksum-crc32, x-amz-checksum-crc32c, x-amz-checksum-sha1, or x-amz-checksum-sha256) is required for all Multi-Object Delete requests.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is Bucket-name.s3express-zone-id.region-code.amazonaws.com.

    The following operations are related to DeleteObjects:

    ", "alias":"DeleteMultipleObjects", "httpChecksum":{ "requestAlgorithmMember":"ChecksumAlgorithm", @@ -479,7 +479,7 @@ }, "input":{"shape":"GetBucketLifecycleConfigurationRequest"}, "output":{"shape":"GetBucketLifecycleConfigurationOutput"}, - "documentation":"

    Returns the lifecycle configuration information set on the bucket. For information about lifecycle configuration, see Object Lifecycle Management.

    Bucket lifecycle configuration now supports specifying a lifecycle rule using an object key name prefix, one or more object tags, object size, or any combination of these. Accordingly, this section describes the latest API, which is compatible with the new functionality. The previous version of the API supported filtering based only on an object key name prefix, which is supported for general purpose buckets for backward compatibility. For the related API description, see GetBucketLifecycle.

    Lifecyle configurations for directory buckets only support expiring objects and cancelling multipart uploads. Expiring of versioned objects, transitions and tag filters are not supported.

    Permissions
    • General purpose bucket permissions - By default, all Amazon S3 resources are private, including buckets, objects, and related subresources (for example, lifecycle configuration and website configuration). Only the resource owner (that is, the Amazon Web Services account that created it) can access the resource. The resource owner can optionally grant access permissions to others by writing an access policy. For this operation, a user must have the s3:GetLifecycleConfiguration permission.

      For more information about permissions, see Managing Access Permissions to Your Amazon S3 Resources.

    • Directory bucket permissions - You must have the s3express:GetLifecycleConfiguration permission in an IAM identity-based policy to use this operation. Cross-account access to this API operation isn't supported. The resource owner can optionally grant access permissions to others by creating a role or user for them as long as they are within the same account as the owner and resource.

      For more information about directory bucket policies and permissions, see Authorizing Regional endpoint APIs with IAM in the Amazon S3 User Guide.

      Directory buckets - For directory buckets, you must make requests for this API operation to the Regional endpoint. These endpoints support path-style requests in the format https://s3express-control.region-code.amazonaws.com/bucket-name . Virtual-hosted-style requests aren't supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Concepts for directory buckets in Local Zones in the Amazon S3 User Guide.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is s3express-control.region.amazonaws.com.

    GetBucketLifecycleConfiguration has the following special error:

    • Error code: NoSuchLifecycleConfiguration

      • Description: The lifecycle configuration does not exist.

      • HTTP Status Code: 404 Not Found

      • SOAP Fault Code Prefix: Client

    The following operations are related to GetBucketLifecycleConfiguration:

    ", + "documentation":"

    Returns the lifecycle configuration information set on the bucket. For information about lifecycle configuration, see Object Lifecycle Management.

    Bucket lifecycle configuration now supports specifying a lifecycle rule using an object key name prefix, one or more object tags, object size, or any combination of these. Accordingly, this section describes the latest API, which is compatible with the new functionality. The previous version of the API supported filtering based only on an object key name prefix, which is supported for general purpose buckets for backward compatibility. For the related API description, see GetBucketLifecycle.

    Lifecyle configurations for directory buckets only support expiring objects and cancelling multipart uploads. Expiring of versioned objects, transitions and tag filters are not supported.

    Permissions
    • General purpose bucket permissions - By default, all Amazon S3 resources are private, including buckets, objects, and related subresources (for example, lifecycle configuration and website configuration). Only the resource owner (that is, the Amazon Web Services account that created it) can access the resource. The resource owner can optionally grant access permissions to others by writing an access policy. For this operation, a user must have the s3:GetLifecycleConfiguration permission.

      For more information about permissions, see Managing Access Permissions to Your Amazon S3 Resources.

    • Directory bucket permissions - You must have the s3express:GetLifecycleConfiguration permission in an IAM identity-based policy to use this operation. Cross-account access to this API operation isn't supported. The resource owner can optionally grant access permissions to others by creating a role or user for them as long as they are within the same account as the owner and resource.

      For more information about directory bucket policies and permissions, see Authorizing Regional endpoint APIs with IAM in the Amazon S3 User Guide.

      Directory buckets - For directory buckets, you must make requests for this API operation to the Regional endpoint. These endpoints support path-style requests in the format https://s3express-control.region-code.amazonaws.com/bucket-name . Virtual-hosted-style requests aren't supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Available Local Zone for directory buckets in the Amazon S3 User Guide.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is s3express-control.region.amazonaws.com.

    GetBucketLifecycleConfiguration has the following special error:

    • Error code: NoSuchLifecycleConfiguration

      • Description: The lifecycle configuration does not exist.

      • HTTP Status Code: 404 Not Found

      • SOAP Fault Code Prefix: Client

    The following operations are related to GetBucketLifecycleConfiguration:

    ", "staticContextParams":{ "UseS3ExpressControlEndpoint":{"value":true} } @@ -588,7 +588,7 @@ "input":{"shape":"GetBucketPolicyRequest"}, "output":{"shape":"GetBucketPolicyOutput"}, "documentationUrl":"http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketGETpolicy.html", - "documentation":"

    Returns the policy of a specified bucket.

    Directory buckets - For directory buckets, you must make requests for this API operation to the Regional endpoint. These endpoints support path-style requests in the format https://s3express-control.region-code.amazonaws.com/bucket-name . Virtual-hosted-style requests aren't supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Concepts for directory buckets in Local Zones in the Amazon S3 User Guide.

    Permissions

    If you are using an identity other than the root user of the Amazon Web Services account that owns the bucket, the calling identity must both have the GetBucketPolicy permissions on the specified bucket and belong to the bucket owner's account in order to use this operation.

    If you don't have GetBucketPolicy permissions, Amazon S3 returns a 403 Access Denied error. If you have the correct permissions, but you're not using an identity that belongs to the bucket owner's account, Amazon S3 returns a 405 Method Not Allowed error.

    To ensure that bucket owners don't inadvertently lock themselves out of their own buckets, the root principal in a bucket owner's Amazon Web Services account can perform the GetBucketPolicy, PutBucketPolicy, and DeleteBucketPolicy API actions, even if their bucket policy explicitly denies the root principal's access. Bucket owner root principals can only be blocked from performing these API actions by VPC endpoint policies and Amazon Web Services Organizations policies.

    • General purpose bucket permissions - The s3:GetBucketPolicy permission is required in a policy. For more information about general purpose buckets bucket policies, see Using Bucket Policies and User Policies in the Amazon S3 User Guide.

    • Directory bucket permissions - To grant access to this API operation, you must have the s3express:GetBucketPolicy permission in an IAM identity-based policy instead of a bucket policy. Cross-account access to this API operation isn't supported. This operation can only be performed by the Amazon Web Services account that owns the resource. For more information about directory bucket policies and permissions, see Amazon Web Services Identity and Access Management (IAM) for S3 Express One Zone in the Amazon S3 User Guide.

    Example bucket policies

    General purpose buckets example bucket policies - See Bucket policy examples in the Amazon S3 User Guide.

    Directory bucket example bucket policies - See Example bucket policies for S3 Express One Zone in the Amazon S3 User Guide.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is s3express-control.region-code.amazonaws.com.

    The following action is related to GetBucketPolicy:

    ", + "documentation":"

    Returns the policy of a specified bucket.

    Directory buckets - For directory buckets, you must make requests for this API operation to the Regional endpoint. These endpoints support path-style requests in the format https://s3express-control.region-code.amazonaws.com/bucket-name . Virtual-hosted-style requests aren't supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Available Local Zone for directory buckets in the Amazon S3 User Guide.

    Permissions

    If you are using an identity other than the root user of the Amazon Web Services account that owns the bucket, the calling identity must both have the GetBucketPolicy permissions on the specified bucket and belong to the bucket owner's account in order to use this operation.

    If you don't have GetBucketPolicy permissions, Amazon S3 returns a 403 Access Denied error. If you have the correct permissions, but you're not using an identity that belongs to the bucket owner's account, Amazon S3 returns a 405 Method Not Allowed error.

    To ensure that bucket owners don't inadvertently lock themselves out of their own buckets, the root principal in a bucket owner's Amazon Web Services account can perform the GetBucketPolicy, PutBucketPolicy, and DeleteBucketPolicy API actions, even if their bucket policy explicitly denies the root principal's access. Bucket owner root principals can only be blocked from performing these API actions by VPC endpoint policies and Amazon Web Services Organizations policies.

    • General purpose bucket permissions - The s3:GetBucketPolicy permission is required in a policy. For more information about general purpose buckets bucket policies, see Using Bucket Policies and User Policies in the Amazon S3 User Guide.

    • Directory bucket permissions - To grant access to this API operation, you must have the s3express:GetBucketPolicy permission in an IAM identity-based policy instead of a bucket policy. Cross-account access to this API operation isn't supported. This operation can only be performed by the Amazon Web Services account that owns the resource. For more information about directory bucket policies and permissions, see Amazon Web Services Identity and Access Management (IAM) for S3 Express One Zone in the Amazon S3 User Guide.

    Example bucket policies

    General purpose buckets example bucket policies - See Bucket policy examples in the Amazon S3 User Guide.

    Directory bucket example bucket policies - See Example bucket policies for S3 Express One Zone in the Amazon S3 User Guide.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is s3express-control.region-code.amazonaws.com.

    The following action is related to GetBucketPolicy:

    ", "staticContextParams":{ "UseS3ExpressControlEndpoint":{"value":true} } @@ -688,10 +688,11 @@ {"shape":"InvalidObjectState"} ], "documentationUrl":"http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTObjectGET.html", - "documentation":"

    Retrieves an object from Amazon S3.

    In the GetObject request, specify the full key name for the object.

    General purpose buckets - Both the virtual-hosted-style requests and the path-style requests are supported. For a virtual hosted-style request example, if you have the object photos/2006/February/sample.jpg, specify the object key name as /photos/2006/February/sample.jpg. For a path-style request example, if you have the object photos/2006/February/sample.jpg in the bucket named examplebucket, specify the object key name as /examplebucket/photos/2006/February/sample.jpg. For more information about request types, see HTTP Host Header Bucket Specification in the Amazon S3 User Guide.

    Directory buckets - Only virtual-hosted-style requests are supported. For a virtual hosted-style request example, if you have the object photos/2006/February/sample.jpg in the bucket named examplebucket--use1-az5--x-s3, specify the object key name as /photos/2006/February/sample.jpg. Also, when you make requests to this API operation, your requests are sent to the Zonal endpoint. These endpoints support virtual-hosted-style requests in the format https://bucket-name.s3express-zone-id.region-code.amazonaws.com/key-name . Path-style requests are not supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Concepts for directory buckets in Local Zones in the Amazon S3 User Guide.

    Permissions
    • General purpose bucket permissions - You must have the required permissions in a policy. To use GetObject, you must have the READ access to the object (or version). If you grant READ access to the anonymous user, the GetObject operation returns the object without using an authorization header. For more information, see Specifying permissions in a policy in the Amazon S3 User Guide.

      If you include a versionId in your request header, you must have the s3:GetObjectVersion permission to access a specific version of an object. The s3:GetObject permission is not required in this scenario.

      If you request the current version of an object without a specific versionId in the request header, only the s3:GetObject permission is required. The s3:GetObjectVersion permission is not required in this scenario.

      If the object that you request doesn’t exist, the error that Amazon S3 returns depends on whether you also have the s3:ListBucket permission.

      • If you have the s3:ListBucket permission on the bucket, Amazon S3 returns an HTTP status code 404 Not Found error.

      • If you don’t have the s3:ListBucket permission, Amazon S3 returns an HTTP status code 403 Access Denied error.

    • Directory bucket permissions - To grant access to this API operation on a directory bucket, we recommend that you use the CreateSession API operation for session-based authorization. Specifically, you grant the s3express:CreateSession permission to the directory bucket in a bucket policy or an IAM identity-based policy. Then, you make the CreateSession API call on the bucket to obtain a session token. With the session token in your request header, you can make API requests to this operation. After the session token expires, you make another CreateSession API call to generate a new session token for use. Amazon Web Services CLI or SDKs create session and refresh the session token automatically to avoid service interruptions when a session expires. For more information about authorization, see CreateSession .

      If the object is encrypted using SSE-KMS, you must also have the kms:GenerateDataKey and kms:Decrypt permissions in IAM identity-based policies and KMS key policies for the KMS key.

    Storage classes

    If the object you are retrieving is stored in the S3 Glacier Flexible Retrieval storage class, the S3 Glacier Deep Archive storage class, the S3 Intelligent-Tiering Archive Access tier, or the S3 Intelligent-Tiering Deep Archive Access tier, before you can retrieve the object you must first restore a copy using RestoreObject. Otherwise, this operation returns an InvalidObjectState error. For information about restoring archived objects, see Restoring Archived Objects in the Amazon S3 User Guide.

    Directory buckets - For directory buckets, only the S3 Express One Zone storage class is supported to store newly created objects. Unsupported storage class values won't write a destination object and will respond with the HTTP status code 400 Bad Request.

    Encryption

    Encryption request headers, like x-amz-server-side-encryption, should not be sent for the GetObject requests, if your object uses server-side encryption with Amazon S3 managed encryption keys (SSE-S3), server-side encryption with Key Management Service (KMS) keys (SSE-KMS), or dual-layer server-side encryption with Amazon Web Services KMS keys (DSSE-KMS). If you include the header in your GetObject requests for the object that uses these types of keys, you’ll get an HTTP 400 Bad Request error.

    Directory buckets - For directory buckets, there are only two supported options for server-side encryption: SSE-S3 and SSE-KMS. SSE-C isn't supported. For more information, see Protecting data with server-side encryption in the Amazon S3 User Guide.

    Overriding response header values through the request

    There are times when you want to override certain response header values of a GetObject response. For example, you might override the Content-Disposition response header value through your GetObject request.

    You can override values for a set of response headers. These modified response header values are included only in a successful response, that is, when the HTTP status code 200 OK is returned. The headers you can override using the following query parameters in the request are a subset of the headers that Amazon S3 accepts when you create an object.

    The response headers that you can override for the GetObject response are Cache-Control, Content-Disposition, Content-Encoding, Content-Language, Content-Type, and Expires.

    To override values for a set of response headers in the GetObject response, you can use the following query parameters in the request.

    • response-cache-control

    • response-content-disposition

    • response-content-encoding

    • response-content-language

    • response-content-type

    • response-expires

    When you use these parameters, you must sign the request by using either an Authorization header or a presigned URL. These parameters cannot be used with an unsigned (anonymous) request.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is Bucket-name.s3express-zone-id.region-code.amazonaws.com.

    The following operations are related to GetObject:

    ", + "documentation":"

    Retrieves an object from Amazon S3.

    In the GetObject request, specify the full key name for the object.

    General purpose buckets - Both the virtual-hosted-style requests and the path-style requests are supported. For a virtual hosted-style request example, if you have the object photos/2006/February/sample.jpg, specify the object key name as /photos/2006/February/sample.jpg. For a path-style request example, if you have the object photos/2006/February/sample.jpg in the bucket named examplebucket, specify the object key name as /examplebucket/photos/2006/February/sample.jpg. For more information about request types, see HTTP Host Header Bucket Specification in the Amazon S3 User Guide.

    Directory buckets - Only virtual-hosted-style requests are supported. For a virtual hosted-style request example, if you have the object photos/2006/February/sample.jpg in the bucket named examplebucket--use1-az5--x-s3, specify the object key name as /photos/2006/February/sample.jpg. Also, when you make requests to this API operation, your requests are sent to the Zonal endpoint. These endpoints support virtual-hosted-style requests in the format https://bucket-name.s3express-zone-id.region-code.amazonaws.com/key-name . Path-style requests are not supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Available Local Zone for directory buckets in the Amazon S3 User Guide.

    Permissions
    • General purpose bucket permissions - You must have the required permissions in a policy. To use GetObject, you must have the READ access to the object (or version). If you grant READ access to the anonymous user, the GetObject operation returns the object without using an authorization header. For more information, see Specifying permissions in a policy in the Amazon S3 User Guide.

      If you include a versionId in your request header, you must have the s3:GetObjectVersion permission to access a specific version of an object. The s3:GetObject permission is not required in this scenario.

      If you request the current version of an object without a specific versionId in the request header, only the s3:GetObject permission is required. The s3:GetObjectVersion permission is not required in this scenario.

      If the object that you request doesn’t exist, the error that Amazon S3 returns depends on whether you also have the s3:ListBucket permission.

      • If you have the s3:ListBucket permission on the bucket, Amazon S3 returns an HTTP status code 404 Not Found error.

      • If you don’t have the s3:ListBucket permission, Amazon S3 returns an HTTP status code 403 Access Denied error.

    • Directory bucket permissions - To grant access to this API operation on a directory bucket, we recommend that you use the CreateSession API operation for session-based authorization. Specifically, you grant the s3express:CreateSession permission to the directory bucket in a bucket policy or an IAM identity-based policy. Then, you make the CreateSession API call on the bucket to obtain a session token. With the session token in your request header, you can make API requests to this operation. After the session token expires, you make another CreateSession API call to generate a new session token for use. Amazon Web Services CLI or SDKs create session and refresh the session token automatically to avoid service interruptions when a session expires. For more information about authorization, see CreateSession .

      If the object is encrypted using SSE-KMS, you must also have the kms:GenerateDataKey and kms:Decrypt permissions in IAM identity-based policies and KMS key policies for the KMS key.

    Storage classes

    If the object you are retrieving is stored in the S3 Glacier Flexible Retrieval storage class, the S3 Glacier Deep Archive storage class, the S3 Intelligent-Tiering Archive Access tier, or the S3 Intelligent-Tiering Deep Archive Access tier, before you can retrieve the object you must first restore a copy using RestoreObject. Otherwise, this operation returns an InvalidObjectState error. For information about restoring archived objects, see Restoring Archived Objects in the Amazon S3 User Guide.

    Directory buckets - For directory buckets, only the S3 Express One Zone storage class is supported to store newly created objects. Unsupported storage class values won't write a destination object and will respond with the HTTP status code 400 Bad Request.

    Encryption

    Encryption request headers, like x-amz-server-side-encryption, should not be sent for the GetObject requests, if your object uses server-side encryption with Amazon S3 managed encryption keys (SSE-S3), server-side encryption with Key Management Service (KMS) keys (SSE-KMS), or dual-layer server-side encryption with Amazon Web Services KMS keys (DSSE-KMS). If you include the header in your GetObject requests for the object that uses these types of keys, you’ll get an HTTP 400 Bad Request error.

    Directory buckets - For directory buckets, there are only two supported options for server-side encryption: SSE-S3 and SSE-KMS. SSE-C isn't supported. For more information, see Protecting data with server-side encryption in the Amazon S3 User Guide.

    Overriding response header values through the request

    There are times when you want to override certain response header values of a GetObject response. For example, you might override the Content-Disposition response header value through your GetObject request.

    You can override values for a set of response headers. These modified response header values are included only in a successful response, that is, when the HTTP status code 200 OK is returned. The headers you can override using the following query parameters in the request are a subset of the headers that Amazon S3 accepts when you create an object.

    The response headers that you can override for the GetObject response are Cache-Control, Content-Disposition, Content-Encoding, Content-Language, Content-Type, and Expires.

    To override values for a set of response headers in the GetObject response, you can use the following query parameters in the request.

    • response-cache-control

    • response-content-disposition

    • response-content-encoding

    • response-content-language

    • response-content-type

    • response-expires

    When you use these parameters, you must sign the request by using either an Authorization header or a presigned URL. These parameters cannot be used with an unsigned (anonymous) request.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is Bucket-name.s3express-zone-id.region-code.amazonaws.com.

    The following operations are related to GetObject:

    ", "httpChecksum":{ "requestValidationModeMember":"ChecksumMode", "responseAlgorithms":[ + "CRC64NVME", "CRC32", "CRC32C", "SHA256", @@ -724,7 +725,7 @@ "errors":[ {"shape":"NoSuchKey"} ], - "documentation":"

    Retrieves all the metadata from an object without returning the object itself. This operation is useful if you're interested only in an object's metadata.

    GetObjectAttributes combines the functionality of HeadObject and ListParts. All of the data returned with each of those individual calls can be returned with a single call to GetObjectAttributes.

    Directory buckets - For directory buckets, you must make requests for this API operation to the Zonal endpoint. These endpoints support virtual-hosted-style requests in the format https://bucket-name.s3express-zone-id.region-code.amazonaws.com/key-name . Path-style requests are not supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Concepts for directory buckets in Local Zones in the Amazon S3 User Guide.

    Permissions
    • General purpose bucket permissions - To use GetObjectAttributes, you must have READ access to the object. The permissions that you need to use this operation depend on whether the bucket is versioned. If the bucket is versioned, you need both the s3:GetObjectVersion and s3:GetObjectVersionAttributes permissions for this operation. If the bucket is not versioned, you need the s3:GetObject and s3:GetObjectAttributes permissions. For more information, see Specifying Permissions in a Policy in the Amazon S3 User Guide. If the object that you request does not exist, the error Amazon S3 returns depends on whether you also have the s3:ListBucket permission.

      • If you have the s3:ListBucket permission on the bucket, Amazon S3 returns an HTTP status code 404 Not Found (\"no such key\") error.

      • If you don't have the s3:ListBucket permission, Amazon S3 returns an HTTP status code 403 Forbidden (\"access denied\") error.

    • Directory bucket permissions - To grant access to this API operation on a directory bucket, we recommend that you use the CreateSession API operation for session-based authorization. Specifically, you grant the s3express:CreateSession permission to the directory bucket in a bucket policy or an IAM identity-based policy. Then, you make the CreateSession API call on the bucket to obtain a session token. With the session token in your request header, you can make API requests to this operation. After the session token expires, you make another CreateSession API call to generate a new session token for use. Amazon Web Services CLI or SDKs create session and refresh the session token automatically to avoid service interruptions when a session expires. For more information about authorization, see CreateSession .

      If the object is encrypted with SSE-KMS, you must also have the kms:GenerateDataKey and kms:Decrypt permissions in IAM identity-based policies and KMS key policies for the KMS key.

    Encryption

    Encryption request headers, like x-amz-server-side-encryption, should not be sent for HEAD requests if your object uses server-side encryption with Key Management Service (KMS) keys (SSE-KMS), dual-layer server-side encryption with Amazon Web Services KMS keys (DSSE-KMS), or server-side encryption with Amazon S3 managed encryption keys (SSE-S3). The x-amz-server-side-encryption header is used when you PUT an object to S3 and want to specify the encryption method. If you include this header in a GET request for an object that uses these types of keys, you’ll get an HTTP 400 Bad Request error. It's because the encryption method can't be changed when you retrieve the object.

    If you encrypt an object by using server-side encryption with customer-provided encryption keys (SSE-C) when you store the object in Amazon S3, then when you retrieve the metadata from the object, you must use the following headers to provide the encryption key for the server to be able to retrieve the object's metadata. The headers are:

    • x-amz-server-side-encryption-customer-algorithm

    • x-amz-server-side-encryption-customer-key

    • x-amz-server-side-encryption-customer-key-MD5

    For more information about SSE-C, see Server-Side Encryption (Using Customer-Provided Encryption Keys) in the Amazon S3 User Guide.

    Directory bucket permissions - For directory buckets, there are only two supported options for server-side encryption: server-side encryption with Amazon S3 managed keys (SSE-S3) (AES256) and server-side encryption with KMS keys (SSE-KMS) (aws:kms). We recommend that the bucket's default encryption uses the desired encryption configuration and you don't override the bucket default encryption in your CreateSession requests or PUT object requests. Then, new objects are automatically encrypted with the desired encryption settings. For more information, see Protecting data with server-side encryption in the Amazon S3 User Guide. For more information about the encryption overriding behaviors in directory buckets, see Specifying server-side encryption with KMS for new object uploads.

    Versioning

    Directory buckets - S3 Versioning isn't enabled and supported for directory buckets. For this API operation, only the null value of the version ID is supported by directory buckets. You can only specify null to the versionId query parameter in the request.

    Conditional request headers

    Consider the following when using request headers:

    • If both of the If-Match and If-Unmodified-Since headers are present in the request as follows, then Amazon S3 returns the HTTP status code 200 OK and the data requested:

      • If-Match condition evaluates to true.

      • If-Unmodified-Since condition evaluates to false.

      For more information about conditional requests, see RFC 7232.

    • If both of the If-None-Match and If-Modified-Since headers are present in the request as follows, then Amazon S3 returns the HTTP status code 304 Not Modified:

      • If-None-Match condition evaluates to false.

      • If-Modified-Since condition evaluates to true.

      For more information about conditional requests, see RFC 7232.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is Bucket-name.s3express-zone-id.region-code.amazonaws.com.

    The following actions are related to GetObjectAttributes:

    " + "documentation":"

    Retrieves all the metadata from an object without returning the object itself. This operation is useful if you're interested only in an object's metadata.

    GetObjectAttributes combines the functionality of HeadObject and ListParts. All of the data returned with each of those individual calls can be returned with a single call to GetObjectAttributes.

    Directory buckets - For directory buckets, you must make requests for this API operation to the Zonal endpoint. These endpoints support virtual-hosted-style requests in the format https://bucket-name.s3express-zone-id.region-code.amazonaws.com/key-name . Path-style requests are not supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Available Local Zone for directory buckets in the Amazon S3 User Guide.

    Permissions
    • General purpose bucket permissions - To use GetObjectAttributes, you must have READ access to the object. The permissions that you need to use this operation depend on whether the bucket is versioned. If the bucket is versioned, you need both the s3:GetObjectVersion and s3:GetObjectVersionAttributes permissions for this operation. If the bucket is not versioned, you need the s3:GetObject and s3:GetObjectAttributes permissions. For more information, see Specifying Permissions in a Policy in the Amazon S3 User Guide. If the object that you request does not exist, the error Amazon S3 returns depends on whether you also have the s3:ListBucket permission.

      • If you have the s3:ListBucket permission on the bucket, Amazon S3 returns an HTTP status code 404 Not Found (\"no such key\") error.

      • If you don't have the s3:ListBucket permission, Amazon S3 returns an HTTP status code 403 Forbidden (\"access denied\") error.

    • Directory bucket permissions - To grant access to this API operation on a directory bucket, we recommend that you use the CreateSession API operation for session-based authorization. Specifically, you grant the s3express:CreateSession permission to the directory bucket in a bucket policy or an IAM identity-based policy. Then, you make the CreateSession API call on the bucket to obtain a session token. With the session token in your request header, you can make API requests to this operation. After the session token expires, you make another CreateSession API call to generate a new session token for use. Amazon Web Services CLI or SDKs create session and refresh the session token automatically to avoid service interruptions when a session expires. For more information about authorization, see CreateSession .

      If the object is encrypted with SSE-KMS, you must also have the kms:GenerateDataKey and kms:Decrypt permissions in IAM identity-based policies and KMS key policies for the KMS key.

    Encryption

    Encryption request headers, like x-amz-server-side-encryption, should not be sent for HEAD requests if your object uses server-side encryption with Key Management Service (KMS) keys (SSE-KMS), dual-layer server-side encryption with Amazon Web Services KMS keys (DSSE-KMS), or server-side encryption with Amazon S3 managed encryption keys (SSE-S3). The x-amz-server-side-encryption header is used when you PUT an object to S3 and want to specify the encryption method. If you include this header in a GET request for an object that uses these types of keys, you’ll get an HTTP 400 Bad Request error. It's because the encryption method can't be changed when you retrieve the object.

    If you encrypt an object by using server-side encryption with customer-provided encryption keys (SSE-C) when you store the object in Amazon S3, then when you retrieve the metadata from the object, you must use the following headers to provide the encryption key for the server to be able to retrieve the object's metadata. The headers are:

    • x-amz-server-side-encryption-customer-algorithm

    • x-amz-server-side-encryption-customer-key

    • x-amz-server-side-encryption-customer-key-MD5

    For more information about SSE-C, see Server-Side Encryption (Using Customer-Provided Encryption Keys) in the Amazon S3 User Guide.

    Directory bucket permissions - For directory buckets, there are only two supported options for server-side encryption: server-side encryption with Amazon S3 managed keys (SSE-S3) (AES256) and server-side encryption with KMS keys (SSE-KMS) (aws:kms). We recommend that the bucket's default encryption uses the desired encryption configuration and you don't override the bucket default encryption in your CreateSession requests or PUT object requests. Then, new objects are automatically encrypted with the desired encryption settings. For more information, see Protecting data with server-side encryption in the Amazon S3 User Guide. For more information about the encryption overriding behaviors in directory buckets, see Specifying server-side encryption with KMS for new object uploads.

    Versioning

    Directory buckets - S3 Versioning isn't enabled and supported for directory buckets. For this API operation, only the null value of the version ID is supported by directory buckets. You can only specify null to the versionId query parameter in the request.

    Conditional request headers

    Consider the following when using request headers:

    • If both of the If-Match and If-Unmodified-Since headers are present in the request as follows, then Amazon S3 returns the HTTP status code 200 OK and the data requested:

      • If-Match condition evaluates to true.

      • If-Unmodified-Since condition evaluates to false.

      For more information about conditional requests, see RFC 7232.

    • If both of the If-None-Match and If-Modified-Since headers are present in the request as follows, then Amazon S3 returns the HTTP status code 304 Not Modified:

      • If-None-Match condition evaluates to false.

      • If-Modified-Since condition evaluates to true.

      For more information about conditional requests, see RFC 7232.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is Bucket-name.s3express-zone-id.region-code.amazonaws.com.

    The following actions are related to GetObjectAttributes:

    " }, "GetObjectLegalHold":{ "name":"GetObjectLegalHold", @@ -802,7 +803,7 @@ {"shape":"NoSuchBucket"} ], "documentationUrl":"http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketHEAD.html", - "documentation":"

    You can use this operation to determine if a bucket exists and if you have permission to access it. The action returns a 200 OK if the bucket exists and you have permission to access it.

    If the bucket does not exist or you do not have permission to access it, the HEAD request returns a generic 400 Bad Request, 403 Forbidden or 404 Not Found code. A message body is not included, so you cannot determine the exception beyond these HTTP response codes.

    Authentication and authorization

    General purpose buckets - Request to public buckets that grant the s3:ListBucket permission publicly do not need to be signed. All other HeadBucket requests must be authenticated and signed by using IAM credentials (access key ID and secret access key for the IAM identities). All headers with the x-amz- prefix, including x-amz-copy-source, must be signed. For more information, see REST Authentication.

    Directory buckets - You must use IAM credentials to authenticate and authorize your access to the HeadBucket API operation, instead of using the temporary security credentials through the CreateSession API operation.

    Amazon Web Services CLI or SDKs handles authentication and authorization on your behalf.

    Permissions

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is Bucket-name.s3express-zone-id.region-code.amazonaws.com.

    You must make requests for this API operation to the Zonal endpoint. These endpoints support virtual-hosted-style requests in the format https://bucket-name.s3express-zone-id.region-code.amazonaws.com. Path-style requests are not supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Concepts for directory buckets in Local Zones in the Amazon S3 User Guide.

    " + "documentation":"

    You can use this operation to determine if a bucket exists and if you have permission to access it. The action returns a 200 OK if the bucket exists and you have permission to access it.

    If the bucket does not exist or you do not have permission to access it, the HEAD request returns a generic 400 Bad Request, 403 Forbidden or 404 Not Found code. A message body is not included, so you cannot determine the exception beyond these HTTP response codes.

    Authentication and authorization

    General purpose buckets - Request to public buckets that grant the s3:ListBucket permission publicly do not need to be signed. All other HeadBucket requests must be authenticated and signed by using IAM credentials (access key ID and secret access key for the IAM identities). All headers with the x-amz- prefix, including x-amz-copy-source, must be signed. For more information, see REST Authentication.

    Directory buckets - You must use IAM credentials to authenticate and authorize your access to the HeadBucket API operation, instead of using the temporary security credentials through the CreateSession API operation.

    Amazon Web Services CLI or SDKs handles authentication and authorization on your behalf.

    Permissions

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is Bucket-name.s3express-zone-id.region-code.amazonaws.com.

    You must make requests for this API operation to the Zonal endpoint. These endpoints support virtual-hosted-style requests in the format https://bucket-name.s3express-zone-id.region-code.amazonaws.com. Path-style requests are not supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Available Local Zone for directory buckets in the Amazon S3 User Guide.

    " }, "HeadObject":{ "name":"HeadObject", @@ -816,7 +817,7 @@ {"shape":"NoSuchKey"} ], "documentationUrl":"http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTObjectHEAD.html", - "documentation":"

    The HEAD operation retrieves metadata from an object without returning the object itself. This operation is useful if you're interested only in an object's metadata.

    A HEAD request has the same options as a GET operation on an object. The response is identical to the GET response except that there is no response body. Because of this, if the HEAD request generates an error, it returns a generic code, such as 400 Bad Request, 403 Forbidden, 404 Not Found, 405 Method Not Allowed, 412 Precondition Failed, or 304 Not Modified. It's not possible to retrieve the exact exception of these error codes.

    Request headers are limited to 8 KB in size. For more information, see Common Request Headers.

    Permissions

    • General purpose bucket permissions - To use HEAD, you must have the s3:GetObject permission. You need the relevant read object (or version) permission for this operation. For more information, see Actions, resources, and condition keys for Amazon S3 in the Amazon S3 User Guide. For more information about the permissions to S3 API operations by S3 resource types, see Required permissions for Amazon S3 API operations in the Amazon S3 User Guide.

      If the object you request doesn't exist, the error that Amazon S3 returns depends on whether you also have the s3:ListBucket permission.

      • If you have the s3:ListBucket permission on the bucket, Amazon S3 returns an HTTP status code 404 Not Found error.

      • If you don’t have the s3:ListBucket permission, Amazon S3 returns an HTTP status code 403 Forbidden error.

    • Directory bucket permissions - To grant access to this API operation on a directory bucket, we recommend that you use the CreateSession API operation for session-based authorization. Specifically, you grant the s3express:CreateSession permission to the directory bucket in a bucket policy or an IAM identity-based policy. Then, you make the CreateSession API call on the bucket to obtain a session token. With the session token in your request header, you can make API requests to this operation. After the session token expires, you make another CreateSession API call to generate a new session token for use. Amazon Web Services CLI or SDKs create session and refresh the session token automatically to avoid service interruptions when a session expires. For more information about authorization, see CreateSession .

      If you enable x-amz-checksum-mode in the request and the object is encrypted with Amazon Web Services Key Management Service (Amazon Web Services KMS), you must also have the kms:GenerateDataKey and kms:Decrypt permissions in IAM identity-based policies and KMS key policies for the KMS key to retrieve the checksum of the object.

    Encryption

    Encryption request headers, like x-amz-server-side-encryption, should not be sent for HEAD requests if your object uses server-side encryption with Key Management Service (KMS) keys (SSE-KMS), dual-layer server-side encryption with Amazon Web Services KMS keys (DSSE-KMS), or server-side encryption with Amazon S3 managed encryption keys (SSE-S3). The x-amz-server-side-encryption header is used when you PUT an object to S3 and want to specify the encryption method. If you include this header in a HEAD request for an object that uses these types of keys, you’ll get an HTTP 400 Bad Request error. It's because the encryption method can't be changed when you retrieve the object.

    If you encrypt an object by using server-side encryption with customer-provided encryption keys (SSE-C) when you store the object in Amazon S3, then when you retrieve the metadata from the object, you must use the following headers to provide the encryption key for the server to be able to retrieve the object's metadata. The headers are:

    • x-amz-server-side-encryption-customer-algorithm

    • x-amz-server-side-encryption-customer-key

    • x-amz-server-side-encryption-customer-key-MD5

    For more information about SSE-C, see Server-Side Encryption (Using Customer-Provided Encryption Keys) in the Amazon S3 User Guide.

    Directory bucket - For directory buckets, there are only two supported options for server-side encryption: SSE-S3 and SSE-KMS. SSE-C isn't supported. For more information, see Protecting data with server-side encryption in the Amazon S3 User Guide.

    Versioning
    • If the current version of the object is a delete marker, Amazon S3 behaves as if the object was deleted and includes x-amz-delete-marker: true in the response.

    • If the specified version is a delete marker, the response returns a 405 Method Not Allowed error and the Last-Modified: timestamp response header.

    • Directory buckets - Delete marker is not supported for directory buckets.

    • Directory buckets - S3 Versioning isn't enabled and supported for directory buckets. For this API operation, only the null value of the version ID is supported by directory buckets. You can only specify null to the versionId query parameter in the request.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is Bucket-name.s3express-zone-id.region-code.amazonaws.com.

    For directory buckets, you must make requests for this API operation to the Zonal endpoint. These endpoints support virtual-hosted-style requests in the format https://bucket-name.s3express-zone-id.region-code.amazonaws.com/key-name . Path-style requests are not supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Concepts for directory buckets in Local Zones in the Amazon S3 User Guide.

    The following actions are related to HeadObject:

    " + "documentation":"

    The HEAD operation retrieves metadata from an object without returning the object itself. This operation is useful if you're interested only in an object's metadata.

    A HEAD request has the same options as a GET operation on an object. The response is identical to the GET response except that there is no response body. Because of this, if the HEAD request generates an error, it returns a generic code, such as 400 Bad Request, 403 Forbidden, 404 Not Found, 405 Method Not Allowed, 412 Precondition Failed, or 304 Not Modified. It's not possible to retrieve the exact exception of these error codes.

    Request headers are limited to 8 KB in size. For more information, see Common Request Headers.

    Permissions

    • General purpose bucket permissions - To use HEAD, you must have the s3:GetObject permission. You need the relevant read object (or version) permission for this operation. For more information, see Actions, resources, and condition keys for Amazon S3 in the Amazon S3 User Guide. For more information about the permissions to S3 API operations by S3 resource types, see Required permissions for Amazon S3 API operations in the Amazon S3 User Guide.

      If the object you request doesn't exist, the error that Amazon S3 returns depends on whether you also have the s3:ListBucket permission.

      • If you have the s3:ListBucket permission on the bucket, Amazon S3 returns an HTTP status code 404 Not Found error.

      • If you don’t have the s3:ListBucket permission, Amazon S3 returns an HTTP status code 403 Forbidden error.

    • Directory bucket permissions - To grant access to this API operation on a directory bucket, we recommend that you use the CreateSession API operation for session-based authorization. Specifically, you grant the s3express:CreateSession permission to the directory bucket in a bucket policy or an IAM identity-based policy. Then, you make the CreateSession API call on the bucket to obtain a session token. With the session token in your request header, you can make API requests to this operation. After the session token expires, you make another CreateSession API call to generate a new session token for use. Amazon Web Services CLI or SDKs create session and refresh the session token automatically to avoid service interruptions when a session expires. For more information about authorization, see CreateSession .

      If you enable x-amz-checksum-mode in the request and the object is encrypted with Amazon Web Services Key Management Service (Amazon Web Services KMS), you must also have the kms:GenerateDataKey and kms:Decrypt permissions in IAM identity-based policies and KMS key policies for the KMS key to retrieve the checksum of the object.

    Encryption

    Encryption request headers, like x-amz-server-side-encryption, should not be sent for HEAD requests if your object uses server-side encryption with Key Management Service (KMS) keys (SSE-KMS), dual-layer server-side encryption with Amazon Web Services KMS keys (DSSE-KMS), or server-side encryption with Amazon S3 managed encryption keys (SSE-S3). The x-amz-server-side-encryption header is used when you PUT an object to S3 and want to specify the encryption method. If you include this header in a HEAD request for an object that uses these types of keys, you’ll get an HTTP 400 Bad Request error. It's because the encryption method can't be changed when you retrieve the object.

    If you encrypt an object by using server-side encryption with customer-provided encryption keys (SSE-C) when you store the object in Amazon S3, then when you retrieve the metadata from the object, you must use the following headers to provide the encryption key for the server to be able to retrieve the object's metadata. The headers are:

    • x-amz-server-side-encryption-customer-algorithm

    • x-amz-server-side-encryption-customer-key

    • x-amz-server-side-encryption-customer-key-MD5

    For more information about SSE-C, see Server-Side Encryption (Using Customer-Provided Encryption Keys) in the Amazon S3 User Guide.

    Directory bucket - For directory buckets, there are only two supported options for server-side encryption: SSE-S3 and SSE-KMS. SSE-C isn't supported. For more information, see Protecting data with server-side encryption in the Amazon S3 User Guide.

    Versioning
    • If the current version of the object is a delete marker, Amazon S3 behaves as if the object was deleted and includes x-amz-delete-marker: true in the response.

    • If the specified version is a delete marker, the response returns a 405 Method Not Allowed error and the Last-Modified: timestamp response header.

    • Directory buckets - Delete marker is not supported for directory buckets.

    • Directory buckets - S3 Versioning isn't enabled and supported for directory buckets. For this API operation, only the null value of the version ID is supported by directory buckets. You can only specify null to the versionId query parameter in the request.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is Bucket-name.s3express-zone-id.region-code.amazonaws.com.

    For directory buckets, you must make requests for this API operation to the Zonal endpoint. These endpoints support virtual-hosted-style requests in the format https://bucket-name.s3express-zone-id.region-code.amazonaws.com/key-name . Path-style requests are not supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Available Local Zone for directory buckets in the Amazon S3 User Guide.

    The following actions are related to HeadObject:

    " }, "ListBucketAnalyticsConfigurations":{ "name":"ListBucketAnalyticsConfigurations", @@ -887,7 +888,7 @@ }, "input":{"shape":"ListDirectoryBucketsRequest"}, "output":{"shape":"ListDirectoryBucketsOutput"}, - "documentation":"

    Returns a list of all Amazon S3 directory buckets owned by the authenticated sender of the request. For more information about directory buckets, see Directory buckets in the Amazon S3 User Guide.

    Directory buckets - For directory buckets, you must make requests for this API operation to the Regional endpoint. These endpoints support path-style requests in the format https://s3express-control.region-code.amazonaws.com/bucket-name . Virtual-hosted-style requests aren't supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Concepts for directory buckets in Local Zones in the Amazon S3 User Guide.

    Permissions

    You must have the s3express:ListAllMyDirectoryBuckets permission in an IAM identity-based policy instead of a bucket policy. Cross-account access to this API operation isn't supported. This operation can only be performed by the Amazon Web Services account that owns the resource. For more information about directory bucket policies and permissions, see Amazon Web Services Identity and Access Management (IAM) for S3 Express One Zone in the Amazon S3 User Guide.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is s3express-control.region.amazonaws.com.

    The BucketRegion response element is not part of the ListDirectoryBuckets Response Syntax.

    ", + "documentation":"

    Returns a list of all Amazon S3 directory buckets owned by the authenticated sender of the request. For more information about directory buckets, see Directory buckets in the Amazon S3 User Guide.

    Directory buckets - For directory buckets, you must make requests for this API operation to the Regional endpoint. These endpoints support path-style requests in the format https://s3express-control.region-code.amazonaws.com/bucket-name . Virtual-hosted-style requests aren't supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Available Local Zone for directory buckets in the Amazon S3 User Guide.

    Permissions

    You must have the s3express:ListAllMyDirectoryBuckets permission in an IAM identity-based policy instead of a bucket policy. Cross-account access to this API operation isn't supported. This operation can only be performed by the Amazon Web Services account that owns the resource. For more information about directory bucket policies and permissions, see Amazon Web Services Identity and Access Management (IAM) for S3 Express One Zone in the Amazon S3 User Guide.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is s3express-control.region.amazonaws.com.

    The BucketRegion response element is not part of the ListDirectoryBuckets Response Syntax.

    ", "staticContextParams":{ "UseS3ExpressControlEndpoint":{"value":true} } @@ -901,7 +902,7 @@ "input":{"shape":"ListMultipartUploadsRequest"}, "output":{"shape":"ListMultipartUploadsOutput"}, "documentationUrl":"http://docs.amazonwebservices.com/AmazonS3/latest/API/mpUploadListMPUpload.html", - "documentation":"

    This operation lists in-progress multipart uploads in a bucket. An in-progress multipart upload is a multipart upload that has been initiated by the CreateMultipartUpload request, but has not yet been completed or aborted.

    Directory buckets - If multipart uploads in a directory bucket are in progress, you can't delete the bucket until all the in-progress multipart uploads are aborted or completed. To delete these in-progress multipart uploads, use the ListMultipartUploads operation to list the in-progress multipart uploads in the bucket and use the AbortMultipartUpload operation to abort all the in-progress multipart uploads.

    The ListMultipartUploads operation returns a maximum of 1,000 multipart uploads in the response. The limit of 1,000 multipart uploads is also the default value. You can further limit the number of uploads in a response by specifying the max-uploads request parameter. If there are more than 1,000 multipart uploads that satisfy your ListMultipartUploads request, the response returns an IsTruncated element with the value of true, a NextKeyMarker element, and a NextUploadIdMarker element. To list the remaining multipart uploads, you need to make subsequent ListMultipartUploads requests. In these requests, include two query parameters: key-marker and upload-id-marker. Set the value of key-marker to the NextKeyMarker value from the previous response. Similarly, set the value of upload-id-marker to the NextUploadIdMarker value from the previous response.

    Directory buckets - The upload-id-marker element and the NextUploadIdMarker element aren't supported by directory buckets. To list the additional multipart uploads, you only need to set the value of key-marker to the NextKeyMarker value from the previous response.

    For more information about multipart uploads, see Uploading Objects Using Multipart Upload in the Amazon S3 User Guide.

    Directory buckets - For directory buckets, you must make requests for this API operation to the Zonal endpoint. These endpoints support virtual-hosted-style requests in the format https://bucket-name.s3express-zone-id.region-code.amazonaws.com/key-name . Path-style requests are not supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Concepts for directory buckets in Local Zones in the Amazon S3 User Guide.

    Permissions
    • General purpose bucket permissions - For information about permissions required to use the multipart upload API, see Multipart Upload and Permissions in the Amazon S3 User Guide.

    • Directory bucket permissions - To grant access to this API operation on a directory bucket, we recommend that you use the CreateSession API operation for session-based authorization. Specifically, you grant the s3express:CreateSession permission to the directory bucket in a bucket policy or an IAM identity-based policy. Then, you make the CreateSession API call on the bucket to obtain a session token. With the session token in your request header, you can make API requests to this operation. After the session token expires, you make another CreateSession API call to generate a new session token for use. Amazon Web Services CLI or SDKs create session and refresh the session token automatically to avoid service interruptions when a session expires. For more information about authorization, see CreateSession .

    Sorting of multipart uploads in response
    • General purpose bucket - In the ListMultipartUploads response, the multipart uploads are sorted based on two criteria:

      • Key-based sorting - Multipart uploads are initially sorted in ascending order based on their object keys.

      • Time-based sorting - For uploads that share the same object key, they are further sorted in ascending order based on the upload initiation time. Among uploads with the same key, the one that was initiated first will appear before the ones that were initiated later.

    • Directory bucket - In the ListMultipartUploads response, the multipart uploads aren't sorted lexicographically based on the object keys.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is Bucket-name.s3express-zone-id.region-code.amazonaws.com.

    The following operations are related to ListMultipartUploads:

    " + "documentation":"

    This operation lists in-progress multipart uploads in a bucket. An in-progress multipart upload is a multipart upload that has been initiated by the CreateMultipartUpload request, but has not yet been completed or aborted.

    Directory buckets - If multipart uploads in a directory bucket are in progress, you can't delete the bucket until all the in-progress multipart uploads are aborted or completed. To delete these in-progress multipart uploads, use the ListMultipartUploads operation to list the in-progress multipart uploads in the bucket and use the AbortMultipartUpload operation to abort all the in-progress multipart uploads.

    The ListMultipartUploads operation returns a maximum of 1,000 multipart uploads in the response. The limit of 1,000 multipart uploads is also the default value. You can further limit the number of uploads in a response by specifying the max-uploads request parameter. If there are more than 1,000 multipart uploads that satisfy your ListMultipartUploads request, the response returns an IsTruncated element with the value of true, a NextKeyMarker element, and a NextUploadIdMarker element. To list the remaining multipart uploads, you need to make subsequent ListMultipartUploads requests. In these requests, include two query parameters: key-marker and upload-id-marker. Set the value of key-marker to the NextKeyMarker value from the previous response. Similarly, set the value of upload-id-marker to the NextUploadIdMarker value from the previous response.

    Directory buckets - The upload-id-marker element and the NextUploadIdMarker element aren't supported by directory buckets. To list the additional multipart uploads, you only need to set the value of key-marker to the NextKeyMarker value from the previous response.

    For more information about multipart uploads, see Uploading Objects Using Multipart Upload in the Amazon S3 User Guide.

    Directory buckets - For directory buckets, you must make requests for this API operation to the Zonal endpoint. These endpoints support virtual-hosted-style requests in the format https://bucket-name.s3express-zone-id.region-code.amazonaws.com/key-name . Path-style requests are not supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Available Local Zone for directory buckets in the Amazon S3 User Guide.

    Permissions
    • General purpose bucket permissions - For information about permissions required to use the multipart upload API, see Multipart Upload and Permissions in the Amazon S3 User Guide.

    • Directory bucket permissions - To grant access to this API operation on a directory bucket, we recommend that you use the CreateSession API operation for session-based authorization. Specifically, you grant the s3express:CreateSession permission to the directory bucket in a bucket policy or an IAM identity-based policy. Then, you make the CreateSession API call on the bucket to obtain a session token. With the session token in your request header, you can make API requests to this operation. After the session token expires, you make another CreateSession API call to generate a new session token for use. Amazon Web Services CLI or SDKs create session and refresh the session token automatically to avoid service interruptions when a session expires. For more information about authorization, see CreateSession .

    Sorting of multipart uploads in response
    • General purpose bucket - In the ListMultipartUploads response, the multipart uploads are sorted based on two criteria:

      • Key-based sorting - Multipart uploads are initially sorted in ascending order based on their object keys.

      • Time-based sorting - For uploads that share the same object key, they are further sorted in ascending order based on the upload initiation time. Among uploads with the same key, the one that was initiated first will appear before the ones that were initiated later.

    • Directory bucket - In the ListMultipartUploads response, the multipart uploads aren't sorted lexicographically based on the object keys.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is Bucket-name.s3express-zone-id.region-code.amazonaws.com.

    The following operations are related to ListMultipartUploads:

    " }, "ListObjectVersions":{ "name":"ListObjectVersions", @@ -941,7 +942,7 @@ "errors":[ {"shape":"NoSuchBucket"} ], - "documentation":"

    Returns some or all (up to 1,000) of the objects in a bucket with each request. You can use the request parameters as selection criteria to return a subset of the objects in a bucket. A 200 OK response can contain valid or invalid XML. Make sure to design your application to parse the contents of the response and handle it appropriately. For more information about listing objects, see Listing object keys programmatically in the Amazon S3 User Guide. To get a list of your buckets, see ListBuckets.

    • General purpose bucket - For general purpose buckets, ListObjectsV2 doesn't return prefixes that are related only to in-progress multipart uploads.

    • Directory buckets - For directory buckets, ListObjectsV2 response includes the prefixes that are related only to in-progress multipart uploads.

    • Directory buckets - For directory buckets, you must make requests for this API operation to the Zonal endpoint. These endpoints support virtual-hosted-style requests in the format https://bucket-name.s3express-zone-id.region-code.amazonaws.com/key-name . Path-style requests are not supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Concepts for directory buckets in Local Zones in the Amazon S3 User Guide.

    Permissions
    • General purpose bucket permissions - To use this operation, you must have READ access to the bucket. You must have permission to perform the s3:ListBucket action. The bucket owner has this permission by default and can grant this permission to others. For more information about permissions, see Permissions Related to Bucket Subresource Operations and Managing Access Permissions to Your Amazon S3 Resources in the Amazon S3 User Guide.

    • Directory bucket permissions - To grant access to this API operation on a directory bucket, we recommend that you use the CreateSession API operation for session-based authorization. Specifically, you grant the s3express:CreateSession permission to the directory bucket in a bucket policy or an IAM identity-based policy. Then, you make the CreateSession API call on the bucket to obtain a session token. With the session token in your request header, you can make API requests to this operation. After the session token expires, you make another CreateSession API call to generate a new session token for use. Amazon Web Services CLI or SDKs create session and refresh the session token automatically to avoid service interruptions when a session expires. For more information about authorization, see CreateSession .

    Sorting order of returned objects
    • General purpose bucket - For general purpose buckets, ListObjectsV2 returns objects in lexicographical order based on their key names.

    • Directory bucket - For directory buckets, ListObjectsV2 does not return objects in lexicographical order.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is Bucket-name.s3express-zone-id.region-code.amazonaws.com.

    This section describes the latest revision of this action. We recommend that you use this revised API operation for application development. For backward compatibility, Amazon S3 continues to support the prior version of this API operation, ListObjects.

    The following operations are related to ListObjectsV2:

    " + "documentation":"

    Returns some or all (up to 1,000) of the objects in a bucket with each request. You can use the request parameters as selection criteria to return a subset of the objects in a bucket. A 200 OK response can contain valid or invalid XML. Make sure to design your application to parse the contents of the response and handle it appropriately. For more information about listing objects, see Listing object keys programmatically in the Amazon S3 User Guide. To get a list of your buckets, see ListBuckets.

    • General purpose bucket - For general purpose buckets, ListObjectsV2 doesn't return prefixes that are related only to in-progress multipart uploads.

    • Directory buckets - For directory buckets, ListObjectsV2 response includes the prefixes that are related only to in-progress multipart uploads.

    • Directory buckets - For directory buckets, you must make requests for this API operation to the Zonal endpoint. These endpoints support virtual-hosted-style requests in the format https://bucket-name.s3express-zone-id.region-code.amazonaws.com/key-name . Path-style requests are not supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Available Local Zone for directory buckets in the Amazon S3 User Guide.

    Permissions
    • General purpose bucket permissions - To use this operation, you must have READ access to the bucket. You must have permission to perform the s3:ListBucket action. The bucket owner has this permission by default and can grant this permission to others. For more information about permissions, see Permissions Related to Bucket Subresource Operations and Managing Access Permissions to Your Amazon S3 Resources in the Amazon S3 User Guide.

    • Directory bucket permissions - To grant access to this API operation on a directory bucket, we recommend that you use the CreateSession API operation for session-based authorization. Specifically, you grant the s3express:CreateSession permission to the directory bucket in a bucket policy or an IAM identity-based policy. Then, you make the CreateSession API call on the bucket to obtain a session token. With the session token in your request header, you can make API requests to this operation. After the session token expires, you make another CreateSession API call to generate a new session token for use. Amazon Web Services CLI or SDKs create session and refresh the session token automatically to avoid service interruptions when a session expires. For more information about authorization, see CreateSession .

    Sorting order of returned objects
    • General purpose bucket - For general purpose buckets, ListObjectsV2 returns objects in lexicographical order based on their key names.

    • Directory bucket - For directory buckets, ListObjectsV2 does not return objects in lexicographical order.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is Bucket-name.s3express-zone-id.region-code.amazonaws.com.

    This section describes the latest revision of this action. We recommend that you use this revised API operation for application development. For backward compatibility, Amazon S3 continues to support the prior version of this API operation, ListObjects.

    The following operations are related to ListObjectsV2:

    " }, "ListParts":{ "name":"ListParts", @@ -952,7 +953,7 @@ "input":{"shape":"ListPartsRequest"}, "output":{"shape":"ListPartsOutput"}, "documentationUrl":"http://docs.amazonwebservices.com/AmazonS3/latest/API/mpUploadListParts.html", - "documentation":"

    Lists the parts that have been uploaded for a specific multipart upload.

    To use this operation, you must provide the upload ID in the request. You obtain this uploadID by sending the initiate multipart upload request through CreateMultipartUpload.

    The ListParts request returns a maximum of 1,000 uploaded parts. The limit of 1,000 parts is also the default value. You can restrict the number of parts in a response by specifying the max-parts request parameter. If your multipart upload consists of more than 1,000 parts, the response returns an IsTruncated field with the value of true, and a NextPartNumberMarker element. To list remaining uploaded parts, in subsequent ListParts requests, include the part-number-marker query string parameter and set its value to the NextPartNumberMarker field value from the previous response.

    For more information on multipart uploads, see Uploading Objects Using Multipart Upload in the Amazon S3 User Guide.

    Directory buckets - For directory buckets, you must make requests for this API operation to the Zonal endpoint. These endpoints support virtual-hosted-style requests in the format https://bucket-name.s3express-zone-id.region-code.amazonaws.com/key-name . Path-style requests are not supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Concepts for directory buckets in Local Zones in the Amazon S3 User Guide.

    Permissions
    • General purpose bucket permissions - For information about permissions required to use the multipart upload API, see Multipart Upload and Permissions in the Amazon S3 User Guide.

      If the upload was created using server-side encryption with Key Management Service (KMS) keys (SSE-KMS) or dual-layer server-side encryption with Amazon Web Services KMS keys (DSSE-KMS), you must have permission to the kms:Decrypt action for the ListParts request to succeed.

    • Directory bucket permissions - To grant access to this API operation on a directory bucket, we recommend that you use the CreateSession API operation for session-based authorization. Specifically, you grant the s3express:CreateSession permission to the directory bucket in a bucket policy or an IAM identity-based policy. Then, you make the CreateSession API call on the bucket to obtain a session token. With the session token in your request header, you can make API requests to this operation. After the session token expires, you make another CreateSession API call to generate a new session token for use. Amazon Web Services CLI or SDKs create session and refresh the session token automatically to avoid service interruptions when a session expires. For more information about authorization, see CreateSession .

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is Bucket-name.s3express-zone-id.region-code.amazonaws.com.

    The following operations are related to ListParts:

    " + "documentation":"

    Lists the parts that have been uploaded for a specific multipart upload.

    To use this operation, you must provide the upload ID in the request. You obtain this uploadID by sending the initiate multipart upload request through CreateMultipartUpload.

    The ListParts request returns a maximum of 1,000 uploaded parts. The limit of 1,000 parts is also the default value. You can restrict the number of parts in a response by specifying the max-parts request parameter. If your multipart upload consists of more than 1,000 parts, the response returns an IsTruncated field with the value of true, and a NextPartNumberMarker element. To list remaining uploaded parts, in subsequent ListParts requests, include the part-number-marker query string parameter and set its value to the NextPartNumberMarker field value from the previous response.

    For more information on multipart uploads, see Uploading Objects Using Multipart Upload in the Amazon S3 User Guide.

    Directory buckets - For directory buckets, you must make requests for this API operation to the Zonal endpoint. These endpoints support virtual-hosted-style requests in the format https://bucket-name.s3express-zone-id.region-code.amazonaws.com/key-name . Path-style requests are not supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Available Local Zone for directory buckets in the Amazon S3 User Guide.

    Permissions
    • General purpose bucket permissions - For information about permissions required to use the multipart upload API, see Multipart Upload and Permissions in the Amazon S3 User Guide.

      If the upload was created using server-side encryption with Key Management Service (KMS) keys (SSE-KMS) or dual-layer server-side encryption with Amazon Web Services KMS keys (DSSE-KMS), you must have permission to the kms:Decrypt action for the ListParts request to succeed.

    • Directory bucket permissions - To grant access to this API operation on a directory bucket, we recommend that you use the CreateSession API operation for session-based authorization. Specifically, you grant the s3express:CreateSession permission to the directory bucket in a bucket policy or an IAM identity-based policy. Then, you make the CreateSession API call on the bucket to obtain a session token. With the session token in your request header, you can make API requests to this operation. After the session token expires, you make another CreateSession API call to generate a new session token for use. Amazon Web Services CLI or SDKs create session and refresh the session token automatically to avoid service interruptions when a session expires. For more information about authorization, see CreateSession .

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is Bucket-name.s3express-zone-id.region-code.amazonaws.com.

    The following operations are related to ListParts:

    " }, "PutBucketAccelerateConfiguration":{ "name":"PutBucketAccelerateConfiguration", @@ -1023,7 +1024,7 @@ "requestUri":"/{Bucket}?encryption" }, "input":{"shape":"PutBucketEncryptionRequest"}, - "documentation":"

    This operation configures default encryption and Amazon S3 Bucket Keys for an existing bucket.

    Directory buckets - For directory buckets, you must make requests for this API operation to the Regional endpoint. These endpoints support path-style requests in the format https://s3express-control.region-code.amazonaws.com/bucket-name . Virtual-hosted-style requests aren't supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Concepts for directory buckets in Local Zones in the Amazon S3 User Guide.

    By default, all buckets have a default encryption configuration that uses server-side encryption with Amazon S3 managed keys (SSE-S3).

    • General purpose buckets

      • You can optionally configure default encryption for a bucket by using server-side encryption with Key Management Service (KMS) keys (SSE-KMS) or dual-layer server-side encryption with Amazon Web Services KMS keys (DSSE-KMS). If you specify default encryption by using SSE-KMS, you can also configure Amazon S3 Bucket Keys. For information about the bucket default encryption feature, see Amazon S3 Bucket Default Encryption in the Amazon S3 User Guide.

      • If you use PutBucketEncryption to set your default bucket encryption to SSE-KMS, you should verify that your KMS key ID is correct. Amazon S3 doesn't validate the KMS key ID provided in PutBucketEncryption requests.

    • Directory buckets - You can optionally configure default encryption for a bucket by using server-side encryption with Key Management Service (KMS) keys (SSE-KMS).

      • We recommend that the bucket's default encryption uses the desired encryption configuration and you don't override the bucket default encryption in your CreateSession requests or PUT object requests. Then, new objects are automatically encrypted with the desired encryption settings. For more information about the encryption overriding behaviors in directory buckets, see Specifying server-side encryption with KMS for new object uploads.

      • Your SSE-KMS configuration can only support 1 customer managed key per directory bucket for the lifetime of the bucket. The Amazon Web Services managed key (aws/s3) isn't supported.

      • S3 Bucket Keys are always enabled for GET and PUT operations in a directory bucket and can’t be disabled. S3 Bucket Keys aren't supported, when you copy SSE-KMS encrypted objects from general purpose buckets to directory buckets, from directory buckets to general purpose buckets, or between directory buckets, through CopyObject, UploadPartCopy, the Copy operation in Batch Operations, or the import jobs. In this case, Amazon S3 makes a call to KMS every time a copy request is made for a KMS-encrypted object.

      • When you specify an KMS customer managed key for encryption in your directory bucket, only use the key ID or key ARN. The key alias format of the KMS key isn't supported.

      • For directory buckets, if you use PutBucketEncryption to set your default bucket encryption to SSE-KMS, Amazon S3 validates the KMS key ID provided in PutBucketEncryption requests.

    If you're specifying a customer managed KMS key, we recommend using a fully qualified KMS key ARN. If you use a KMS key alias instead, then KMS resolves the key within the requester’s account. This behavior can result in data that's encrypted with a KMS key that belongs to the requester, and not the bucket owner.

    Also, this action requires Amazon Web Services Signature Version 4. For more information, see Authenticating Requests (Amazon Web Services Signature Version 4).

    Permissions
    • General purpose bucket permissions - The s3:PutEncryptionConfiguration permission is required in a policy. The bucket owner has this permission by default. The bucket owner can grant this permission to others. For more information about permissions, see Permissions Related to Bucket Operations and Managing Access Permissions to Your Amazon S3 Resources in the Amazon S3 User Guide.

    • Directory bucket permissions - To grant access to this API operation, you must have the s3express:PutEncryptionConfiguration permission in an IAM identity-based policy instead of a bucket policy. Cross-account access to this API operation isn't supported. This operation can only be performed by the Amazon Web Services account that owns the resource. For more information about directory bucket policies and permissions, see Amazon Web Services Identity and Access Management (IAM) for S3 Express One Zone in the Amazon S3 User Guide.

      To set a directory bucket default encryption with SSE-KMS, you must also have the kms:GenerateDataKey and the kms:Decrypt permissions in IAM identity-based policies and KMS key policies for the target KMS key.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is s3express-control.region-code.amazonaws.com.

    The following operations are related to PutBucketEncryption:

    ", + "documentation":"

    This operation configures default encryption and Amazon S3 Bucket Keys for an existing bucket.

    Directory buckets - For directory buckets, you must make requests for this API operation to the Regional endpoint. These endpoints support path-style requests in the format https://s3express-control.region-code.amazonaws.com/bucket-name . Virtual-hosted-style requests aren't supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Available Local Zone for directory buckets in the Amazon S3 User Guide.

    By default, all buckets have a default encryption configuration that uses server-side encryption with Amazon S3 managed keys (SSE-S3).

    • General purpose buckets

      • You can optionally configure default encryption for a bucket by using server-side encryption with Key Management Service (KMS) keys (SSE-KMS) or dual-layer server-side encryption with Amazon Web Services KMS keys (DSSE-KMS). If you specify default encryption by using SSE-KMS, you can also configure Amazon S3 Bucket Keys. For information about the bucket default encryption feature, see Amazon S3 Bucket Default Encryption in the Amazon S3 User Guide.

      • If you use PutBucketEncryption to set your default bucket encryption to SSE-KMS, you should verify that your KMS key ID is correct. Amazon S3 doesn't validate the KMS key ID provided in PutBucketEncryption requests.

    • Directory buckets - You can optionally configure default encryption for a bucket by using server-side encryption with Key Management Service (KMS) keys (SSE-KMS).

      • We recommend that the bucket's default encryption uses the desired encryption configuration and you don't override the bucket default encryption in your CreateSession requests or PUT object requests. Then, new objects are automatically encrypted with the desired encryption settings. For more information about the encryption overriding behaviors in directory buckets, see Specifying server-side encryption with KMS for new object uploads.

      • Your SSE-KMS configuration can only support 1 customer managed key per directory bucket for the lifetime of the bucket. The Amazon Web Services managed key (aws/s3) isn't supported.

      • S3 Bucket Keys are always enabled for GET and PUT operations in a directory bucket and can’t be disabled. S3 Bucket Keys aren't supported, when you copy SSE-KMS encrypted objects from general purpose buckets to directory buckets, from directory buckets to general purpose buckets, or between directory buckets, through CopyObject, UploadPartCopy, the Copy operation in Batch Operations, or the import jobs. In this case, Amazon S3 makes a call to KMS every time a copy request is made for a KMS-encrypted object.

      • When you specify an KMS customer managed key for encryption in your directory bucket, only use the key ID or key ARN. The key alias format of the KMS key isn't supported.

      • For directory buckets, if you use PutBucketEncryption to set your default bucket encryption to SSE-KMS, Amazon S3 validates the KMS key ID provided in PutBucketEncryption requests.

    If you're specifying a customer managed KMS key, we recommend using a fully qualified KMS key ARN. If you use a KMS key alias instead, then KMS resolves the key within the requester’s account. This behavior can result in data that's encrypted with a KMS key that belongs to the requester, and not the bucket owner.

    Also, this action requires Amazon Web Services Signature Version 4. For more information, see Authenticating Requests (Amazon Web Services Signature Version 4).

    Permissions
    • General purpose bucket permissions - The s3:PutEncryptionConfiguration permission is required in a policy. The bucket owner has this permission by default. The bucket owner can grant this permission to others. For more information about permissions, see Permissions Related to Bucket Operations and Managing Access Permissions to Your Amazon S3 Resources in the Amazon S3 User Guide.

    • Directory bucket permissions - To grant access to this API operation, you must have the s3express:PutEncryptionConfiguration permission in an IAM identity-based policy instead of a bucket policy. Cross-account access to this API operation isn't supported. This operation can only be performed by the Amazon Web Services account that owns the resource. For more information about directory bucket policies and permissions, see Amazon Web Services Identity and Access Management (IAM) for S3 Express One Zone in the Amazon S3 User Guide.

      To set a directory bucket default encryption with SSE-KMS, you must also have the kms:GenerateDataKey and the kms:Decrypt permissions in IAM identity-based policies and KMS key policies for the target KMS key.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is s3express-control.region-code.amazonaws.com.

    The following operations are related to PutBucketEncryption:

    ", "httpChecksum":{ "requestAlgorithmMember":"ChecksumAlgorithm", "requestChecksumRequired":true @@ -1064,7 +1065,7 @@ }, "input":{"shape":"PutBucketLifecycleRequest"}, "documentationUrl":"http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketPUTlifecycle.html", - "documentation":"

    For an updated version of this API, see PutBucketLifecycleConfiguration. This version has been deprecated. Existing lifecycle configurations will work. For new lifecycle configurations, use the updated API.

    This operation is not supported for directory buckets.

    Creates a new lifecycle configuration for the bucket or replaces an existing lifecycle configuration. For information about lifecycle configuration, see Object Lifecycle Management in the Amazon S3 User Guide.

    By default, all Amazon S3 resources, including buckets, objects, and related subresources (for example, lifecycle configuration and website configuration) are private. Only the resource owner, the Amazon Web Services account that created the resource, can access it. The resource owner can optionally grant access permissions to others by writing an access policy. For this operation, users must get the s3:PutLifecycleConfiguration permission.

    You can also explicitly deny permissions. Explicit denial also supersedes any other permissions. If you want to prevent users or accounts from removing or deleting objects from your bucket, you must deny them permissions for the following actions:

    • s3:DeleteObject

    • s3:DeleteObjectVersion

    • s3:PutLifecycleConfiguration

    For more information about permissions, see Managing Access Permissions to your Amazon S3 Resources in the Amazon S3 User Guide.

    For more examples of transitioning objects to storage classes such as STANDARD_IA or ONEZONE_IA, see Examples of Lifecycle Configuration.

    The following operations are related to PutBucketLifecycle:

    ", + "documentation":"

    This operation is not supported for directory buckets.

    For an updated version of this API, see PutBucketLifecycleConfiguration. This version has been deprecated. Existing lifecycle configurations will work. For new lifecycle configurations, use the updated API.

    This operation is not supported for directory buckets.

    Creates a new lifecycle configuration for the bucket or replaces an existing lifecycle configuration. For information about lifecycle configuration, see Object Lifecycle Management in the Amazon S3 User Guide.

    By default, all Amazon S3 resources, including buckets, objects, and related subresources (for example, lifecycle configuration and website configuration) are private. Only the resource owner, the Amazon Web Services account that created the resource, can access it. The resource owner can optionally grant access permissions to others by writing an access policy. For this operation, users must get the s3:PutLifecycleConfiguration permission.

    You can also explicitly deny permissions. Explicit denial also supersedes any other permissions. If you want to prevent users or accounts from removing or deleting objects from your bucket, you must deny them permissions for the following actions:

    • s3:DeleteObject

    • s3:DeleteObjectVersion

    • s3:PutLifecycleConfiguration

    For more information about permissions, see Managing Access Permissions to your Amazon S3 Resources in the Amazon S3 User Guide.

    For more examples of transitioning objects to storage classes such as STANDARD_IA or ONEZONE_IA, see Examples of Lifecycle Configuration.

    The following operations are related to PutBucketLifecycle:

    ", "deprecated":true, "httpChecksum":{ "requestAlgorithmMember":"ChecksumAlgorithm", @@ -1082,7 +1083,7 @@ }, "input":{"shape":"PutBucketLifecycleConfigurationRequest"}, "output":{"shape":"PutBucketLifecycleConfigurationOutput"}, - "documentation":"

    Creates a new lifecycle configuration for the bucket or replaces an existing lifecycle configuration. Keep in mind that this will overwrite an existing lifecycle configuration, so if you want to retain any configuration details, they must be included in the new lifecycle configuration. For information about lifecycle configuration, see Managing your storage lifecycle.

    Bucket lifecycle configuration now supports specifying a lifecycle rule using an object key name prefix, one or more object tags, object size, or any combination of these. Accordingly, this section describes the latest API. The previous version of the API supported filtering based only on an object key name prefix, which is supported for backward compatibility. For the related API description, see PutBucketLifecycle.

    Rules
    Permissions
    HTTP Host header syntax

    You specify the lifecycle configuration in your request body. The lifecycle configuration is specified as XML consisting of one or more rules. An Amazon S3 Lifecycle configuration can have up to 1,000 rules. This limit is not adjustable.

    Bucket lifecycle configuration supports specifying a lifecycle rule using an object key name prefix, one or more object tags, object size, or any combination of these. Accordingly, this section describes the latest API. The previous version of the API supported filtering based only on an object key name prefix, which is supported for backward compatibility for general purpose buckets. For the related API description, see PutBucketLifecycle.

    Lifecyle configurations for directory buckets only support expiring objects and cancelling multipart uploads. Expiring of versioned objects,transitions and tag filters are not supported.

    A lifecycle rule consists of the following:

    • A filter identifying a subset of objects to which the rule applies. The filter can be based on a key name prefix, object tags, object size, or any combination of these.

    • A status indicating whether the rule is in effect.

    • One or more lifecycle transition and expiration actions that you want Amazon S3 to perform on the objects identified by the filter. If the state of your bucket is versioning-enabled or versioning-suspended, you can have many versions of the same object (one current version and zero or more noncurrent versions). Amazon S3 provides predefined actions that you can specify for current and noncurrent object versions.

    For more information, see Object Lifecycle Management and Lifecycle Configuration Elements.

    • General purpose bucket permissions - By default, all Amazon S3 resources are private, including buckets, objects, and related subresources (for example, lifecycle configuration and website configuration). Only the resource owner (that is, the Amazon Web Services account that created it) can access the resource. The resource owner can optionally grant access permissions to others by writing an access policy. For this operation, a user must have the s3:PutLifecycleConfiguration permission.

      You can also explicitly deny permissions. An explicit deny also supersedes any other permissions. If you want to block users or accounts from removing or deleting objects from your bucket, you must deny them permissions for the following actions:

    • Directory bucket permissions - You must have the s3express:PutLifecycleConfiguration permission in an IAM identity-based policy to use this operation. Cross-account access to this API operation isn't supported. The resource owner can optionally grant access permissions to others by creating a role or user for them as long as they are within the same account as the owner and resource.

      For more information about directory bucket policies and permissions, see Authorizing Regional endpoint APIs with IAM in the Amazon S3 User Guide.

      Directory buckets - For directory buckets, you must make requests for this API operation to the Regional endpoint. These endpoints support path-style requests in the format https://s3express-control.region-code.amazonaws.com/bucket-name . Virtual-hosted-style requests aren't supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Concepts for directory buckets in Local Zones in the Amazon S3 User Guide.

    Directory buckets - The HTTP Host header syntax is s3express-control.region.amazonaws.com.

    The following operations are related to PutBucketLifecycleConfiguration:

    ", + "documentation":"

    Creates a new lifecycle configuration for the bucket or replaces an existing lifecycle configuration. Keep in mind that this will overwrite an existing lifecycle configuration, so if you want to retain any configuration details, they must be included in the new lifecycle configuration. For information about lifecycle configuration, see Managing your storage lifecycle.

    Bucket lifecycle configuration now supports specifying a lifecycle rule using an object key name prefix, one or more object tags, object size, or any combination of these. Accordingly, this section describes the latest API. The previous version of the API supported filtering based only on an object key name prefix, which is supported for backward compatibility. For the related API description, see PutBucketLifecycle.

    Rules
    Permissions
    HTTP Host header syntax

    You specify the lifecycle configuration in your request body. The lifecycle configuration is specified as XML consisting of one or more rules. An Amazon S3 Lifecycle configuration can have up to 1,000 rules. This limit is not adjustable.

    Bucket lifecycle configuration supports specifying a lifecycle rule using an object key name prefix, one or more object tags, object size, or any combination of these. Accordingly, this section describes the latest API. The previous version of the API supported filtering based only on an object key name prefix, which is supported for backward compatibility for general purpose buckets. For the related API description, see PutBucketLifecycle.

    Lifecyle configurations for directory buckets only support expiring objects and cancelling multipart uploads. Expiring of versioned objects,transitions and tag filters are not supported.

    A lifecycle rule consists of the following:

    • A filter identifying a subset of objects to which the rule applies. The filter can be based on a key name prefix, object tags, object size, or any combination of these.

    • A status indicating whether the rule is in effect.

    • One or more lifecycle transition and expiration actions that you want Amazon S3 to perform on the objects identified by the filter. If the state of your bucket is versioning-enabled or versioning-suspended, you can have many versions of the same object (one current version and zero or more noncurrent versions). Amazon S3 provides predefined actions that you can specify for current and noncurrent object versions.

    For more information, see Object Lifecycle Management and Lifecycle Configuration Elements.

    • General purpose bucket permissions - By default, all Amazon S3 resources are private, including buckets, objects, and related subresources (for example, lifecycle configuration and website configuration). Only the resource owner (that is, the Amazon Web Services account that created it) can access the resource. The resource owner can optionally grant access permissions to others by writing an access policy. For this operation, a user must have the s3:PutLifecycleConfiguration permission.

      You can also explicitly deny permissions. An explicit deny also supersedes any other permissions. If you want to block users or accounts from removing or deleting objects from your bucket, you must deny them permissions for the following actions:

    • Directory bucket permissions - You must have the s3express:PutLifecycleConfiguration permission in an IAM identity-based policy to use this operation. Cross-account access to this API operation isn't supported. The resource owner can optionally grant access permissions to others by creating a role or user for them as long as they are within the same account as the owner and resource.

      For more information about directory bucket policies and permissions, see Authorizing Regional endpoint APIs with IAM in the Amazon S3 User Guide.

      Directory buckets - For directory buckets, you must make requests for this API operation to the Regional endpoint. These endpoints support path-style requests in the format https://s3express-control.region-code.amazonaws.com/bucket-name . Virtual-hosted-style requests aren't supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Available Local Zone for directory buckets in the Amazon S3 User Guide.

    Directory buckets - The HTTP Host header syntax is s3express-control.region.amazonaws.com.

    The following operations are related to PutBucketLifecycleConfiguration:

    ", "httpChecksum":{ "requestAlgorithmMember":"ChecksumAlgorithm", "requestChecksumRequired":true @@ -1171,7 +1172,7 @@ }, "input":{"shape":"PutBucketPolicyRequest"}, "documentationUrl":"http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketPUTpolicy.html", - "documentation":"

    Applies an Amazon S3 bucket policy to an Amazon S3 bucket.

    Directory buckets - For directory buckets, you must make requests for this API operation to the Regional endpoint. These endpoints support path-style requests in the format https://s3express-control.region-code.amazonaws.com/bucket-name . Virtual-hosted-style requests aren't supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Concepts for directory buckets in Local Zones in the Amazon S3 User Guide.

    Permissions

    If you are using an identity other than the root user of the Amazon Web Services account that owns the bucket, the calling identity must both have the PutBucketPolicy permissions on the specified bucket and belong to the bucket owner's account in order to use this operation.

    If you don't have PutBucketPolicy permissions, Amazon S3 returns a 403 Access Denied error. If you have the correct permissions, but you're not using an identity that belongs to the bucket owner's account, Amazon S3 returns a 405 Method Not Allowed error.

    To ensure that bucket owners don't inadvertently lock themselves out of their own buckets, the root principal in a bucket owner's Amazon Web Services account can perform the GetBucketPolicy, PutBucketPolicy, and DeleteBucketPolicy API actions, even if their bucket policy explicitly denies the root principal's access. Bucket owner root principals can only be blocked from performing these API actions by VPC endpoint policies and Amazon Web Services Organizations policies.

    • General purpose bucket permissions - The s3:PutBucketPolicy permission is required in a policy. For more information about general purpose buckets bucket policies, see Using Bucket Policies and User Policies in the Amazon S3 User Guide.

    • Directory bucket permissions - To grant access to this API operation, you must have the s3express:PutBucketPolicy permission in an IAM identity-based policy instead of a bucket policy. Cross-account access to this API operation isn't supported. This operation can only be performed by the Amazon Web Services account that owns the resource. For more information about directory bucket policies and permissions, see Amazon Web Services Identity and Access Management (IAM) for S3 Express One Zone in the Amazon S3 User Guide.

    Example bucket policies

    General purpose buckets example bucket policies - See Bucket policy examples in the Amazon S3 User Guide.

    Directory bucket example bucket policies - See Example bucket policies for S3 Express One Zone in the Amazon S3 User Guide.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is s3express-control.region-code.amazonaws.com.

    The following operations are related to PutBucketPolicy:

    ", + "documentation":"

    Applies an Amazon S3 bucket policy to an Amazon S3 bucket.

    Directory buckets - For directory buckets, you must make requests for this API operation to the Regional endpoint. These endpoints support path-style requests in the format https://s3express-control.region-code.amazonaws.com/bucket-name . Virtual-hosted-style requests aren't supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Available Local Zone for directory buckets in the Amazon S3 User Guide.

    Permissions

    If you are using an identity other than the root user of the Amazon Web Services account that owns the bucket, the calling identity must both have the PutBucketPolicy permissions on the specified bucket and belong to the bucket owner's account in order to use this operation.

    If you don't have PutBucketPolicy permissions, Amazon S3 returns a 403 Access Denied error. If you have the correct permissions, but you're not using an identity that belongs to the bucket owner's account, Amazon S3 returns a 405 Method Not Allowed error.

    To ensure that bucket owners don't inadvertently lock themselves out of their own buckets, the root principal in a bucket owner's Amazon Web Services account can perform the GetBucketPolicy, PutBucketPolicy, and DeleteBucketPolicy API actions, even if their bucket policy explicitly denies the root principal's access. Bucket owner root principals can only be blocked from performing these API actions by VPC endpoint policies and Amazon Web Services Organizations policies.

    • General purpose bucket permissions - The s3:PutBucketPolicy permission is required in a policy. For more information about general purpose buckets bucket policies, see Using Bucket Policies and User Policies in the Amazon S3 User Guide.

    • Directory bucket permissions - To grant access to this API operation, you must have the s3express:PutBucketPolicy permission in an IAM identity-based policy instead of a bucket policy. Cross-account access to this API operation isn't supported. This operation can only be performed by the Amazon Web Services account that owns the resource. For more information about directory bucket policies and permissions, see Amazon Web Services Identity and Access Management (IAM) for S3 Express One Zone in the Amazon S3 User Guide.

    Example bucket policies

    General purpose buckets example bucket policies - See Bucket policy examples in the Amazon S3 User Guide.

    Directory bucket example bucket policies - See Example bucket policies for S3 Express One Zone in the Amazon S3 User Guide.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is s3express-control.region-code.amazonaws.com.

    The following operations are related to PutBucketPolicy:

    ", "httpChecksum":{ "requestAlgorithmMember":"ChecksumAlgorithm", "requestChecksumRequired":true @@ -1238,7 +1239,7 @@ }, "input":{"shape":"PutBucketVersioningRequest"}, "documentationUrl":"http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTBucketPUTVersioningStatus.html", - "documentation":"

    This operation is not supported for directory buckets.

    When you enable versioning on a bucket for the first time, it might take a short amount of time for the change to be fully propagated. While this change is propagating, you may encounter intermittent HTTP 404 NoSuchKey errors for requests to objects created or updated after enabling versioning. We recommend that you wait for 15 minutes after enabling versioning before issuing write operations (PUT or DELETE) on objects in the bucket.

    Sets the versioning state of an existing bucket.

    You can set the versioning state with one of the following values:

    Enabled—Enables versioning for the objects in the bucket. All objects added to the bucket receive a unique version ID.

    Suspended—Disables versioning for the objects in the bucket. All objects added to the bucket receive the version ID null.

    If the versioning state has never been set on a bucket, it has no versioning state; a GetBucketVersioning request does not return a versioning state value.

    In order to enable MFA Delete, you must be the bucket owner. If you are the bucket owner and want to enable MFA Delete in the bucket versioning configuration, you must include the x-amz-mfa request header and the Status and the MfaDelete request elements in a request to set the versioning state of the bucket.

    If you have an object expiration lifecycle configuration in your non-versioned bucket and you want to maintain the same permanent delete behavior when you enable versioning, you must add a noncurrent expiration policy. The noncurrent expiration lifecycle configuration will manage the deletes of the noncurrent object versions in the version-enabled bucket. (A version-enabled bucket maintains one current and zero or more noncurrent object versions.) For more information, see Lifecycle and Versioning.

    The following operations are related to PutBucketVersioning:

    ", + "documentation":"

    This operation is not supported for directory buckets.

    When you enable versioning on a bucket for the first time, it might take a short amount of time for the change to be fully propagated. While this change is propagating, you might encounter intermittent HTTP 404 NoSuchKey errors for requests to objects created or updated after enabling versioning. We recommend that you wait for 15 minutes after enabling versioning before issuing write operations (PUT or DELETE) on objects in the bucket.

    Sets the versioning state of an existing bucket.

    You can set the versioning state with one of the following values:

    Enabled—Enables versioning for the objects in the bucket. All objects added to the bucket receive a unique version ID.

    Suspended—Disables versioning for the objects in the bucket. All objects added to the bucket receive the version ID null.

    If the versioning state has never been set on a bucket, it has no versioning state; a GetBucketVersioning request does not return a versioning state value.

    In order to enable MFA Delete, you must be the bucket owner. If you are the bucket owner and want to enable MFA Delete in the bucket versioning configuration, you must include the x-amz-mfa request header and the Status and the MfaDelete request elements in a request to set the versioning state of the bucket.

    If you have an object expiration lifecycle configuration in your non-versioned bucket and you want to maintain the same permanent delete behavior when you enable versioning, you must add a noncurrent expiration policy. The noncurrent expiration lifecycle configuration will manage the deletes of the noncurrent object versions in the version-enabled bucket. (A version-enabled bucket maintains one current and zero or more noncurrent object versions.) For more information, see Lifecycle and Versioning.

    The following operations are related to PutBucketVersioning:

    ", "httpChecksum":{ "requestAlgorithmMember":"ChecksumAlgorithm", "requestChecksumRequired":true @@ -1279,7 +1280,7 @@ {"shape":"EncryptionTypeMismatch"} ], "documentationUrl":"http://docs.amazonwebservices.com/AmazonS3/latest/API/RESTObjectPUT.html", - "documentation":"

    Adds an object to a bucket.

    • Amazon S3 never adds partial objects; if you receive a success response, Amazon S3 added the entire object to the bucket. You cannot use PutObject to only update a single piece of metadata for an existing object. You must put the entire object with updated metadata if you want to update some values.

    • If your bucket uses the bucket owner enforced setting for Object Ownership, ACLs are disabled and no longer affect permissions. All objects written to the bucket by any account will be owned by the bucket owner.

    • Directory buckets - For directory buckets, you must make requests for this API operation to the Zonal endpoint. These endpoints support virtual-hosted-style requests in the format https://bucket-name.s3express-zone-id.region-code.amazonaws.com/key-name . Path-style requests are not supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Concepts for directory buckets in Local Zones in the Amazon S3 User Guide.

    Amazon S3 is a distributed system. If it receives multiple write requests for the same object simultaneously, it overwrites all but the last object written. However, Amazon S3 provides features that can modify this behavior:

    • S3 Object Lock - To prevent objects from being deleted or overwritten, you can use Amazon S3 Object Lock in the Amazon S3 User Guide.

      This functionality is not supported for directory buckets.

    • S3 Versioning - When you enable versioning for a bucket, if Amazon S3 receives multiple write requests for the same object simultaneously, it stores all versions of the objects. For each write request that is made to the same object, Amazon S3 automatically generates a unique version ID of that object being stored in Amazon S3. You can retrieve, replace, or delete any version of the object. For more information about versioning, see Adding Objects to Versioning-Enabled Buckets in the Amazon S3 User Guide. For information about returning the versioning state of a bucket, see GetBucketVersioning.

      This functionality is not supported for directory buckets.

    Permissions
    • General purpose bucket permissions - The following permissions are required in your policies when your PutObject request includes specific headers.

      • s3:PutObject - To successfully complete the PutObject request, you must always have the s3:PutObject permission on a bucket to add an object to it.

      • s3:PutObjectAcl - To successfully change the objects ACL of your PutObject request, you must have the s3:PutObjectAcl.

      • s3:PutObjectTagging - To successfully set the tag-set with your PutObject request, you must have the s3:PutObjectTagging.

    • Directory bucket permissions - To grant access to this API operation on a directory bucket, we recommend that you use the CreateSession API operation for session-based authorization. Specifically, you grant the s3express:CreateSession permission to the directory bucket in a bucket policy or an IAM identity-based policy. Then, you make the CreateSession API call on the bucket to obtain a session token. With the session token in your request header, you can make API requests to this operation. After the session token expires, you make another CreateSession API call to generate a new session token for use. Amazon Web Services CLI or SDKs create session and refresh the session token automatically to avoid service interruptions when a session expires. For more information about authorization, see CreateSession .

      If the object is encrypted with SSE-KMS, you must also have the kms:GenerateDataKey and kms:Decrypt permissions in IAM identity-based policies and KMS key policies for the KMS key.

    Data integrity with Content-MD5
    • General purpose bucket - To ensure that data is not corrupted traversing the network, use the Content-MD5 header. When you use this header, Amazon S3 checks the object against the provided MD5 value and, if they do not match, Amazon S3 returns an error. Alternatively, when the object's ETag is its MD5 digest, you can calculate the MD5 while putting the object to Amazon S3 and compare the returned ETag to the calculated MD5 value.

    • Directory bucket - This functionality is not supported for directory buckets.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is Bucket-name.s3express-zone-id.region-code.amazonaws.com.

    For more information about related Amazon S3 APIs, see the following:

    ", + "documentation":"

    Adds an object to a bucket.

    • Amazon S3 never adds partial objects; if you receive a success response, Amazon S3 added the entire object to the bucket. You cannot use PutObject to only update a single piece of metadata for an existing object. You must put the entire object with updated metadata if you want to update some values.

    • If your bucket uses the bucket owner enforced setting for Object Ownership, ACLs are disabled and no longer affect permissions. All objects written to the bucket by any account will be owned by the bucket owner.

    • Directory buckets - For directory buckets, you must make requests for this API operation to the Zonal endpoint. These endpoints support virtual-hosted-style requests in the format https://bucket-name.s3express-zone-id.region-code.amazonaws.com/key-name . Path-style requests are not supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Available Local Zone for directory buckets in the Amazon S3 User Guide.

    Amazon S3 is a distributed system. If it receives multiple write requests for the same object simultaneously, it overwrites all but the last object written. However, Amazon S3 provides features that can modify this behavior:

    • S3 Object Lock - To prevent objects from being deleted or overwritten, you can use Amazon S3 Object Lock in the Amazon S3 User Guide.

      This functionality is not supported for directory buckets.

    • S3 Versioning - When you enable versioning for a bucket, if Amazon S3 receives multiple write requests for the same object simultaneously, it stores all versions of the objects. For each write request that is made to the same object, Amazon S3 automatically generates a unique version ID of that object being stored in Amazon S3. You can retrieve, replace, or delete any version of the object. For more information about versioning, see Adding Objects to Versioning-Enabled Buckets in the Amazon S3 User Guide. For information about returning the versioning state of a bucket, see GetBucketVersioning.

      This functionality is not supported for directory buckets.

    Permissions
    • General purpose bucket permissions - The following permissions are required in your policies when your PutObject request includes specific headers.

      • s3:PutObject - To successfully complete the PutObject request, you must always have the s3:PutObject permission on a bucket to add an object to it.

      • s3:PutObjectAcl - To successfully change the objects ACL of your PutObject request, you must have the s3:PutObjectAcl.

      • s3:PutObjectTagging - To successfully set the tag-set with your PutObject request, you must have the s3:PutObjectTagging.

    • Directory bucket permissions - To grant access to this API operation on a directory bucket, we recommend that you use the CreateSession API operation for session-based authorization. Specifically, you grant the s3express:CreateSession permission to the directory bucket in a bucket policy or an IAM identity-based policy. Then, you make the CreateSession API call on the bucket to obtain a session token. With the session token in your request header, you can make API requests to this operation. After the session token expires, you make another CreateSession API call to generate a new session token for use. Amazon Web Services CLI or SDKs create session and refresh the session token automatically to avoid service interruptions when a session expires. For more information about authorization, see CreateSession .

      If the object is encrypted with SSE-KMS, you must also have the kms:GenerateDataKey and kms:Decrypt permissions in IAM identity-based policies and KMS key policies for the KMS key.

    Data integrity with Content-MD5
    • General purpose bucket - To ensure that data is not corrupted traversing the network, use the Content-MD5 header. When you use this header, Amazon S3 checks the object against the provided MD5 value and, if they do not match, Amazon S3 returns an error. Alternatively, when the object's ETag is its MD5 digest, you can calculate the MD5 while putting the object to Amazon S3 and compare the returned ETag to the calculated MD5 value.

    • Directory bucket - This functionality is not supported for directory buckets.

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is Bucket-name.s3express-zone-id.region-code.amazonaws.com.

    For more information about related Amazon S3 APIs, see the following:

    ", "httpChecksum":{ "requestAlgorithmMember":"ChecksumAlgorithm", "requestChecksumRequired":false @@ -1417,7 +1418,7 @@ "input":{"shape":"UploadPartRequest"}, "output":{"shape":"UploadPartOutput"}, "documentationUrl":"http://docs.amazonwebservices.com/AmazonS3/latest/API/mpUploadUploadPart.html", - "documentation":"

    Uploads a part in a multipart upload.

    In this operation, you provide new data as a part of an object in your request. However, you have an option to specify your existing Amazon S3 object as a data source for the part you are uploading. To upload a part from an existing object, you use the UploadPartCopy operation.

    You must initiate a multipart upload (see CreateMultipartUpload) before you can upload any part. In response to your initiate request, Amazon S3 returns an upload ID, a unique identifier that you must include in your upload part request.

    Part numbers can be any number from 1 to 10,000, inclusive. A part number uniquely identifies a part and also defines its position within the object being created. If you upload a new part using the same part number that was used with a previous part, the previously uploaded part is overwritten.

    For information about maximum and minimum part sizes and other multipart upload specifications, see Multipart upload limits in the Amazon S3 User Guide.

    After you initiate multipart upload and upload one or more parts, you must either complete or abort multipart upload in order to stop getting charged for storage of the uploaded parts. Only after you either complete or abort multipart upload, Amazon S3 frees up the parts storage and stops charging you for the parts storage.

    For more information on multipart uploads, go to Multipart Upload Overview in the Amazon S3 User Guide .

    Directory buckets - For directory buckets, you must make requests for this API operation to the Zonal endpoint. These endpoints support virtual-hosted-style requests in the format https://bucket-name.s3express-zone-id.region-code.amazonaws.com/key-name . Path-style requests are not supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Concepts for directory buckets in Local Zones in the Amazon S3 User Guide.

    Permissions
    • General purpose bucket permissions - To perform a multipart upload with encryption using an Key Management Service key, the requester must have permission to the kms:Decrypt and kms:GenerateDataKey actions on the key. The requester must also have permissions for the kms:GenerateDataKey action for the CreateMultipartUpload API. Then, the requester needs permissions for the kms:Decrypt action on the UploadPart and UploadPartCopy APIs.

      These permissions are required because Amazon S3 must decrypt and read data from the encrypted file parts before it completes the multipart upload. For more information about KMS permissions, see Protecting data using server-side encryption with KMS in the Amazon S3 User Guide. For information about the permissions required to use the multipart upload API, see Multipart upload and permissions and Multipart upload API and permissions in the Amazon S3 User Guide.

    • Directory bucket permissions - To grant access to this API operation on a directory bucket, we recommend that you use the CreateSession API operation for session-based authorization. Specifically, you grant the s3express:CreateSession permission to the directory bucket in a bucket policy or an IAM identity-based policy. Then, you make the CreateSession API call on the bucket to obtain a session token. With the session token in your request header, you can make API requests to this operation. After the session token expires, you make another CreateSession API call to generate a new session token for use. Amazon Web Services CLI or SDKs create session and refresh the session token automatically to avoid service interruptions when a session expires. For more information about authorization, see CreateSession .

      If the object is encrypted with SSE-KMS, you must also have the kms:GenerateDataKey and kms:Decrypt permissions in IAM identity-based policies and KMS key policies for the KMS key.

    Data integrity

    General purpose bucket - To ensure that data is not corrupted traversing the network, specify the Content-MD5 header in the upload part request. Amazon S3 checks the part data against the provided MD5 value. If they do not match, Amazon S3 returns an error. If the upload request is signed with Signature Version 4, then Amazon Web Services S3 uses the x-amz-content-sha256 header as a checksum instead of Content-MD5. For more information see Authenticating Requests: Using the Authorization Header (Amazon Web Services Signature Version 4).

    Directory buckets - MD5 is not supported by directory buckets. You can use checksum algorithms to check object integrity.

    Encryption
    • General purpose bucket - Server-side encryption is for data encryption at rest. Amazon S3 encrypts your data as it writes it to disks in its data centers and decrypts it when you access it. You have mutually exclusive options to protect data using server-side encryption in Amazon S3, depending on how you choose to manage the encryption keys. Specifically, the encryption key options are Amazon S3 managed keys (SSE-S3), Amazon Web Services KMS keys (SSE-KMS), and Customer-Provided Keys (SSE-C). Amazon S3 encrypts data with server-side encryption using Amazon S3 managed keys (SSE-S3) by default. You can optionally tell Amazon S3 to encrypt data at rest using server-side encryption with other key options. The option you use depends on whether you want to use KMS keys (SSE-KMS) or provide your own encryption key (SSE-C).

      Server-side encryption is supported by the S3 Multipart Upload operations. Unless you are using a customer-provided encryption key (SSE-C), you don't need to specify the encryption parameters in each UploadPart request. Instead, you only need to specify the server-side encryption parameters in the initial Initiate Multipart request. For more information, see CreateMultipartUpload.

      If you request server-side encryption using a customer-provided encryption key (SSE-C) in your initiate multipart upload request, you must provide identical encryption information in each part upload using the following request headers.

      • x-amz-server-side-encryption-customer-algorithm

      • x-amz-server-side-encryption-customer-key

      • x-amz-server-side-encryption-customer-key-MD5

      For more information, see Using Server-Side Encryption in the Amazon S3 User Guide.

    • Directory buckets - For directory buckets, there are only two supported options for server-side encryption: server-side encryption with Amazon S3 managed keys (SSE-S3) (AES256) and server-side encryption with KMS keys (SSE-KMS) (aws:kms).

    Special errors
    • Error Code: NoSuchUpload

      • Description: The specified multipart upload does not exist. The upload ID might be invalid, or the multipart upload might have been aborted or completed.

      • HTTP Status Code: 404 Not Found

      • SOAP Fault Code Prefix: Client

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is Bucket-name.s3express-zone-id.region-code.amazonaws.com.

    The following operations are related to UploadPart:

    ", + "documentation":"

    Uploads a part in a multipart upload.

    In this operation, you provide new data as a part of an object in your request. However, you have an option to specify your existing Amazon S3 object as a data source for the part you are uploading. To upload a part from an existing object, you use the UploadPartCopy operation.

    You must initiate a multipart upload (see CreateMultipartUpload) before you can upload any part. In response to your initiate request, Amazon S3 returns an upload ID, a unique identifier that you must include in your upload part request.

    Part numbers can be any number from 1 to 10,000, inclusive. A part number uniquely identifies a part and also defines its position within the object being created. If you upload a new part using the same part number that was used with a previous part, the previously uploaded part is overwritten.

    For information about maximum and minimum part sizes and other multipart upload specifications, see Multipart upload limits in the Amazon S3 User Guide.

    After you initiate multipart upload and upload one or more parts, you must either complete or abort multipart upload in order to stop getting charged for storage of the uploaded parts. Only after you either complete or abort multipart upload, Amazon S3 frees up the parts storage and stops charging you for the parts storage.

    For more information on multipart uploads, go to Multipart Upload Overview in the Amazon S3 User Guide .

    Directory buckets - For directory buckets, you must make requests for this API operation to the Zonal endpoint. These endpoints support virtual-hosted-style requests in the format https://bucket-name.s3express-zone-id.region-code.amazonaws.com/key-name . Path-style requests are not supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Available Local Zone for directory buckets in the Amazon S3 User Guide.

    Permissions
    • General purpose bucket permissions - To perform a multipart upload with encryption using an Key Management Service key, the requester must have permission to the kms:Decrypt and kms:GenerateDataKey actions on the key. The requester must also have permissions for the kms:GenerateDataKey action for the CreateMultipartUpload API. Then, the requester needs permissions for the kms:Decrypt action on the UploadPart and UploadPartCopy APIs.

      These permissions are required because Amazon S3 must decrypt and read data from the encrypted file parts before it completes the multipart upload. For more information about KMS permissions, see Protecting data using server-side encryption with KMS in the Amazon S3 User Guide. For information about the permissions required to use the multipart upload API, see Multipart upload and permissions and Multipart upload API and permissions in the Amazon S3 User Guide.

    • Directory bucket permissions - To grant access to this API operation on a directory bucket, we recommend that you use the CreateSession API operation for session-based authorization. Specifically, you grant the s3express:CreateSession permission to the directory bucket in a bucket policy or an IAM identity-based policy. Then, you make the CreateSession API call on the bucket to obtain a session token. With the session token in your request header, you can make API requests to this operation. After the session token expires, you make another CreateSession API call to generate a new session token for use. Amazon Web Services CLI or SDKs create session and refresh the session token automatically to avoid service interruptions when a session expires. For more information about authorization, see CreateSession .

      If the object is encrypted with SSE-KMS, you must also have the kms:GenerateDataKey and kms:Decrypt permissions in IAM identity-based policies and KMS key policies for the KMS key.

    Data integrity

    General purpose bucket - To ensure that data is not corrupted traversing the network, specify the Content-MD5 header in the upload part request. Amazon S3 checks the part data against the provided MD5 value. If they do not match, Amazon S3 returns an error. If the upload request is signed with Signature Version 4, then Amazon Web Services S3 uses the x-amz-content-sha256 header as a checksum instead of Content-MD5. For more information see Authenticating Requests: Using the Authorization Header (Amazon Web Services Signature Version 4).

    Directory buckets - MD5 is not supported by directory buckets. You can use checksum algorithms to check object integrity.

    Encryption
    • General purpose bucket - Server-side encryption is for data encryption at rest. Amazon S3 encrypts your data as it writes it to disks in its data centers and decrypts it when you access it. You have mutually exclusive options to protect data using server-side encryption in Amazon S3, depending on how you choose to manage the encryption keys. Specifically, the encryption key options are Amazon S3 managed keys (SSE-S3), Amazon Web Services KMS keys (SSE-KMS), and Customer-Provided Keys (SSE-C). Amazon S3 encrypts data with server-side encryption using Amazon S3 managed keys (SSE-S3) by default. You can optionally tell Amazon S3 to encrypt data at rest using server-side encryption with other key options. The option you use depends on whether you want to use KMS keys (SSE-KMS) or provide your own encryption key (SSE-C).

      Server-side encryption is supported by the S3 Multipart Upload operations. Unless you are using a customer-provided encryption key (SSE-C), you don't need to specify the encryption parameters in each UploadPart request. Instead, you only need to specify the server-side encryption parameters in the initial Initiate Multipart request. For more information, see CreateMultipartUpload.

      If you request server-side encryption using a customer-provided encryption key (SSE-C) in your initiate multipart upload request, you must provide identical encryption information in each part upload using the following request headers.

      • x-amz-server-side-encryption-customer-algorithm

      • x-amz-server-side-encryption-customer-key

      • x-amz-server-side-encryption-customer-key-MD5

      For more information, see Using Server-Side Encryption in the Amazon S3 User Guide.

    • Directory buckets - For directory buckets, there are only two supported options for server-side encryption: server-side encryption with Amazon S3 managed keys (SSE-S3) (AES256) and server-side encryption with KMS keys (SSE-KMS) (aws:kms).

    Special errors
    • Error Code: NoSuchUpload

      • Description: The specified multipart upload does not exist. The upload ID might be invalid, or the multipart upload might have been aborted or completed.

      • HTTP Status Code: 404 Not Found

      • SOAP Fault Code Prefix: Client

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is Bucket-name.s3express-zone-id.region-code.amazonaws.com.

    The following operations are related to UploadPart:

    ", "httpChecksum":{ "requestAlgorithmMember":"ChecksumAlgorithm", "requestChecksumRequired":false @@ -1432,7 +1433,7 @@ "input":{"shape":"UploadPartCopyRequest"}, "output":{"shape":"UploadPartCopyOutput"}, "documentationUrl":"http://docs.amazonwebservices.com/AmazonS3/latest/API/mpUploadUploadPartCopy.html", - "documentation":"

    Uploads a part by copying data from an existing object as data source. To specify the data source, you add the request header x-amz-copy-source in your request. To specify a byte range, you add the request header x-amz-copy-source-range in your request.

    For information about maximum and minimum part sizes and other multipart upload specifications, see Multipart upload limits in the Amazon S3 User Guide.

    Instead of copying data from an existing object as part data, you might use the UploadPart action to upload new data as a part of an object in your request.

    You must initiate a multipart upload before you can upload any part. In response to your initiate request, Amazon S3 returns the upload ID, a unique identifier that you must include in your upload part request.

    For conceptual information about multipart uploads, see Uploading Objects Using Multipart Upload in the Amazon S3 User Guide. For information about copying objects using a single atomic action vs. a multipart upload, see Operations on Objects in the Amazon S3 User Guide.

    Directory buckets - For directory buckets, you must make requests for this API operation to the Zonal endpoint. These endpoints support virtual-hosted-style requests in the format https://bucket-name.s3express-zone-id.region-code.amazonaws.com/key-name . Path-style requests are not supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Concepts for directory buckets in Local Zones in the Amazon S3 User Guide.

    Authentication and authorization

    All UploadPartCopy requests must be authenticated and signed by using IAM credentials (access key ID and secret access key for the IAM identities). All headers with the x-amz- prefix, including x-amz-copy-source, must be signed. For more information, see REST Authentication.

    Directory buckets - You must use IAM credentials to authenticate and authorize your access to the UploadPartCopy API operation, instead of using the temporary security credentials through the CreateSession API operation.

    Amazon Web Services CLI or SDKs handles authentication and authorization on your behalf.

    Permissions

    You must have READ access to the source object and WRITE access to the destination bucket.

    • General purpose bucket permissions - You must have the permissions in a policy based on the bucket types of your source bucket and destination bucket in an UploadPartCopy operation.

      • If the source object is in a general purpose bucket, you must have the s3:GetObject permission to read the source object that is being copied.

      • If the destination bucket is a general purpose bucket, you must have the s3:PutObject permission to write the object copy to the destination bucket.

      • To perform a multipart upload with encryption using an Key Management Service key, the requester must have permission to the kms:Decrypt and kms:GenerateDataKey actions on the key. The requester must also have permissions for the kms:GenerateDataKey action for the CreateMultipartUpload API. Then, the requester needs permissions for the kms:Decrypt action on the UploadPart and UploadPartCopy APIs. These permissions are required because Amazon S3 must decrypt and read data from the encrypted file parts before it completes the multipart upload. For more information about KMS permissions, see Protecting data using server-side encryption with KMS in the Amazon S3 User Guide. For information about the permissions required to use the multipart upload API, see Multipart upload and permissions and Multipart upload API and permissions in the Amazon S3 User Guide.

    • Directory bucket permissions - You must have permissions in a bucket policy or an IAM identity-based policy based on the source and destination bucket types in an UploadPartCopy operation.

      • If the source object that you want to copy is in a directory bucket, you must have the s3express:CreateSession permission in the Action element of a policy to read the object. By default, the session is in the ReadWrite mode. If you want to restrict the access, you can explicitly set the s3express:SessionMode condition key to ReadOnly on the copy source bucket.

      • If the copy destination is a directory bucket, you must have the s3express:CreateSession permission in the Action element of a policy to write the object to the destination. The s3express:SessionMode condition key cannot be set to ReadOnly on the copy destination.

      If the object is encrypted with SSE-KMS, you must also have the kms:GenerateDataKey and kms:Decrypt permissions in IAM identity-based policies and KMS key policies for the KMS key.

      For example policies, see Example bucket policies for S3 Express One Zone and Amazon Web Services Identity and Access Management (IAM) identity-based policies for S3 Express One Zone in the Amazon S3 User Guide.

    Encryption
    • General purpose buckets - For information about using server-side encryption with customer-provided encryption keys with the UploadPartCopy operation, see CopyObject and UploadPart.

    • Directory buckets - For directory buckets, there are only two supported options for server-side encryption: server-side encryption with Amazon S3 managed keys (SSE-S3) (AES256) and server-side encryption with KMS keys (SSE-KMS) (aws:kms). For more information, see Protecting data with server-side encryption in the Amazon S3 User Guide.

      For directory buckets, when you perform a CreateMultipartUpload operation and an UploadPartCopy operation, the request headers you provide in the CreateMultipartUpload request must match the default encryption configuration of the destination bucket.

      S3 Bucket Keys aren't supported, when you copy SSE-KMS encrypted objects from general purpose buckets to directory buckets, from directory buckets to general purpose buckets, or between directory buckets, through UploadPartCopy. In this case, Amazon S3 makes a call to KMS every time a copy request is made for a KMS-encrypted object.

    Special errors
    • Error Code: NoSuchUpload

      • Description: The specified multipart upload does not exist. The upload ID might be invalid, or the multipart upload might have been aborted or completed.

      • HTTP Status Code: 404 Not Found

    • Error Code: InvalidRequest

      • Description: The specified copy source is not supported as a byte-range copy source.

      • HTTP Status Code: 400 Bad Request

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is Bucket-name.s3express-zone-id.region-code.amazonaws.com.

    The following operations are related to UploadPartCopy:

    ", + "documentation":"

    Uploads a part by copying data from an existing object as data source. To specify the data source, you add the request header x-amz-copy-source in your request. To specify a byte range, you add the request header x-amz-copy-source-range in your request.

    For information about maximum and minimum part sizes and other multipart upload specifications, see Multipart upload limits in the Amazon S3 User Guide.

    Instead of copying data from an existing object as part data, you might use the UploadPart action to upload new data as a part of an object in your request.

    You must initiate a multipart upload before you can upload any part. In response to your initiate request, Amazon S3 returns the upload ID, a unique identifier that you must include in your upload part request.

    For conceptual information about multipart uploads, see Uploading Objects Using Multipart Upload in the Amazon S3 User Guide. For information about copying objects using a single atomic action vs. a multipart upload, see Operations on Objects in the Amazon S3 User Guide.

    Directory buckets - For directory buckets, you must make requests for this API operation to the Zonal endpoint. These endpoints support virtual-hosted-style requests in the format https://bucket-name.s3express-zone-id.region-code.amazonaws.com/key-name . Path-style requests are not supported. For more information about endpoints in Availability Zones, see Regional and Zonal endpoints for directory buckets in Availability Zones in the Amazon S3 User Guide. For more information about endpoints in Local Zones, see Available Local Zone for directory buckets in the Amazon S3 User Guide.

    Authentication and authorization

    All UploadPartCopy requests must be authenticated and signed by using IAM credentials (access key ID and secret access key for the IAM identities). All headers with the x-amz- prefix, including x-amz-copy-source, must be signed. For more information, see REST Authentication.

    Directory buckets - You must use IAM credentials to authenticate and authorize your access to the UploadPartCopy API operation, instead of using the temporary security credentials through the CreateSession API operation.

    Amazon Web Services CLI or SDKs handles authentication and authorization on your behalf.

    Permissions

    You must have READ access to the source object and WRITE access to the destination bucket.

    • General purpose bucket permissions - You must have the permissions in a policy based on the bucket types of your source bucket and destination bucket in an UploadPartCopy operation.

      • If the source object is in a general purpose bucket, you must have the s3:GetObject permission to read the source object that is being copied.

      • If the destination bucket is a general purpose bucket, you must have the s3:PutObject permission to write the object copy to the destination bucket.

      • To perform a multipart upload with encryption using an Key Management Service key, the requester must have permission to the kms:Decrypt and kms:GenerateDataKey actions on the key. The requester must also have permissions for the kms:GenerateDataKey action for the CreateMultipartUpload API. Then, the requester needs permissions for the kms:Decrypt action on the UploadPart and UploadPartCopy APIs. These permissions are required because Amazon S3 must decrypt and read data from the encrypted file parts before it completes the multipart upload. For more information about KMS permissions, see Protecting data using server-side encryption with KMS in the Amazon S3 User Guide. For information about the permissions required to use the multipart upload API, see Multipart upload and permissions and Multipart upload API and permissions in the Amazon S3 User Guide.

    • Directory bucket permissions - You must have permissions in a bucket policy or an IAM identity-based policy based on the source and destination bucket types in an UploadPartCopy operation.

      • If the source object that you want to copy is in a directory bucket, you must have the s3express:CreateSession permission in the Action element of a policy to read the object. By default, the session is in the ReadWrite mode. If you want to restrict the access, you can explicitly set the s3express:SessionMode condition key to ReadOnly on the copy source bucket.

      • If the copy destination is a directory bucket, you must have the s3express:CreateSession permission in the Action element of a policy to write the object to the destination. The s3express:SessionMode condition key cannot be set to ReadOnly on the copy destination.

      If the object is encrypted with SSE-KMS, you must also have the kms:GenerateDataKey and kms:Decrypt permissions in IAM identity-based policies and KMS key policies for the KMS key.

      For example policies, see Example bucket policies for S3 Express One Zone and Amazon Web Services Identity and Access Management (IAM) identity-based policies for S3 Express One Zone in the Amazon S3 User Guide.

    Encryption
    • General purpose buckets - For information about using server-side encryption with customer-provided encryption keys with the UploadPartCopy operation, see CopyObject and UploadPart.

    • Directory buckets - For directory buckets, there are only two supported options for server-side encryption: server-side encryption with Amazon S3 managed keys (SSE-S3) (AES256) and server-side encryption with KMS keys (SSE-KMS) (aws:kms). For more information, see Protecting data with server-side encryption in the Amazon S3 User Guide.

      For directory buckets, when you perform a CreateMultipartUpload operation and an UploadPartCopy operation, the request headers you provide in the CreateMultipartUpload request must match the default encryption configuration of the destination bucket.

      S3 Bucket Keys aren't supported, when you copy SSE-KMS encrypted objects from general purpose buckets to directory buckets, from directory buckets to general purpose buckets, or between directory buckets, through UploadPartCopy. In this case, Amazon S3 makes a call to KMS every time a copy request is made for a KMS-encrypted object.

    Special errors
    • Error Code: NoSuchUpload

      • Description: The specified multipart upload does not exist. The upload ID might be invalid, or the multipart upload might have been aborted or completed.

      • HTTP Status Code: 404 Not Found

    • Error Code: InvalidRequest

      • Description: The specified copy source is not supported as a byte-range copy source.

      • HTTP Status Code: 400 Bad Request

    HTTP Host header syntax

    Directory buckets - The HTTP Host header syntax is Bucket-name.s3express-zone-id.region-code.amazonaws.com.

    The following operations are related to UploadPartCopy:

    ", "staticContextParams":{ "DisableS3ExpressSessionAuth":{"value":true} } @@ -1988,19 +1989,27 @@ "members":{ "ChecksumCRC32":{ "shape":"ChecksumCRC32", - "documentation":"

    The base64-encoded, 32-bit CRC-32 checksum of the object. This will only be present if it was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    " + "documentation":"

    The Base64 encoded, 32-bit CRC-32 checksum of the object. This checksum is only be present if the checksum was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    " }, "ChecksumCRC32C":{ "shape":"ChecksumCRC32C", - "documentation":"

    The base64-encoded, 32-bit CRC-32C checksum of the object. This will only be present if it was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    " + "documentation":"

    The Base64 encoded, 32-bit CRC-32C checksum of the object. This checksum is only present if the checksum was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    " + }, + "ChecksumCRC64NVME":{ + "shape":"ChecksumCRC64NVME", + "documentation":"

    The Base64 encoded, 64-bit CRC-64NVME checksum of the object. This checksum is present if the object was uploaded with the CRC-64NVME checksum algorithm, or if the object was uploaded without a checksum (and Amazon S3 added the default checksum, CRC-64NVME, to the uploaded object). For more information, see Checking object integrity in the Amazon S3 User Guide.

    " }, "ChecksumSHA1":{ "shape":"ChecksumSHA1", - "documentation":"

    The base64-encoded, 160-bit SHA-1 digest of the object. This will only be present if it was uploaded with the object. When you use the API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    " + "documentation":"

    The Base64 encoded, 160-bit SHA-1 digest of the object. This will only be present if the object was uploaded with the object. When you use the API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    " }, "ChecksumSHA256":{ "shape":"ChecksumSHA256", - "documentation":"

    The base64-encoded, 256-bit SHA-256 digest of the object. This will only be present if it was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    " + "documentation":"

    The Base64 encoded, 256-bit SHA-256 digest of the object. This will only be present if the object was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    " + }, + "ChecksumType":{ + "shape":"ChecksumType", + "documentation":"

    The checksum type that is used to calculate the object’s checksum value. For more information, see Checking object integrity in the Amazon S3 User Guide.

    " } }, "documentation":"

    Contains all the possible checksum or digest values for an object.

    " @@ -2011,7 +2020,8 @@ "CRC32", "CRC32C", "SHA1", - "SHA256" + "SHA256", + "CRC64NVME" ] }, "ChecksumAlgorithmList":{ @@ -2021,12 +2031,20 @@ }, "ChecksumCRC32":{"type":"string"}, "ChecksumCRC32C":{"type":"string"}, + "ChecksumCRC64NVME":{"type":"string"}, "ChecksumMode":{ "type":"string", "enum":["ENABLED"] }, "ChecksumSHA1":{"type":"string"}, "ChecksumSHA256":{"type":"string"}, + "ChecksumType":{ + "type":"string", + "enum":[ + "COMPOSITE", + "FULL_OBJECT" + ] + }, "CloudFunction":{"type":"string"}, "CloudFunctionConfiguration":{ "type":"structure", @@ -2097,19 +2115,27 @@ }, "ChecksumCRC32":{ "shape":"ChecksumCRC32", - "documentation":"

    The base64-encoded, 32-bit CRC-32 checksum of the object. This will only be present if it was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    " + "documentation":"

    The Base64 encoded, 32-bit CRC-32 checksum of the object. This checksum is only be present if the checksum was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    " }, "ChecksumCRC32C":{ "shape":"ChecksumCRC32C", - "documentation":"

    The base64-encoded, 32-bit CRC-32C checksum of the object. This will only be present if it was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    " + "documentation":"

    The Base64 encoded, 32-bit CRC-32C checksum of the object. This checksum is only present if the checksum was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    " + }, + "ChecksumCRC64NVME":{ + "shape":"ChecksumCRC64NVME", + "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This header specifies the Base64 encoded, 64-bit CRC-64NVME checksum of the object. The CRC-64NVME checksum is always a full object checksum. For more information, see Checking object integrity in the Amazon S3 User Guide.

    " }, "ChecksumSHA1":{ "shape":"ChecksumSHA1", - "documentation":"

    The base64-encoded, 160-bit SHA-1 digest of the object. This will only be present if it was uploaded with the object. When you use the API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    " + "documentation":"

    The Base64 encoded, 160-bit SHA-1 digest of the object. This will only be present if the object was uploaded with the object. When you use the API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    " }, "ChecksumSHA256":{ "shape":"ChecksumSHA256", - "documentation":"

    The base64-encoded, 256-bit SHA-256 digest of the object. This will only be present if it was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    " + "documentation":"

    The Base64 encoded, 256-bit SHA-256 digest of the object. This will only be present if the object was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    " + }, + "ChecksumType":{ + "shape":"ChecksumType", + "documentation":"

    The checksum type, which determines how part-level checksums are combined to create an object-level checksum for multipart objects. You can use this header as a data integrity check to verify that the checksum type that is received is the same checksum type that was specified during the CreateMultipartUpload request. For more information, see Checking object integrity in the Amazon S3 User Guide.

    " }, "ServerSideEncryption":{ "shape":"ServerSideEncryption", @@ -2178,28 +2204,46 @@ }, "ChecksumCRC32":{ "shape":"ChecksumCRC32", - "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This header specifies the base64-encoded, 32-bit CRC-32 checksum of the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", + "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This header specifies the Base64 encoded, 32-bit CRC-32 checksum of the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", "location":"header", "locationName":"x-amz-checksum-crc32" }, "ChecksumCRC32C":{ "shape":"ChecksumCRC32C", - "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This header specifies the base64-encoded, 32-bit CRC-32C checksum of the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", + "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This header specifies the Base64 encoded, 32-bit CRC-32C checksum of the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", "location":"header", "locationName":"x-amz-checksum-crc32c" }, + "ChecksumCRC64NVME":{ + "shape":"ChecksumCRC64NVME", + "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This header specifies the Base64 encoded, 64-bit CRC-64NVME checksum of the object. The CRC-64NVME checksum is always a full object checksum. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", + "location":"header", + "locationName":"x-amz-checksum-crc64nvme" + }, "ChecksumSHA1":{ "shape":"ChecksumSHA1", - "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This header specifies the base64-encoded, 160-bit SHA-1 digest of the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", + "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This header specifies the Base64 encoded, 160-bit SHA-1 digest of the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", "location":"header", "locationName":"x-amz-checksum-sha1" }, "ChecksumSHA256":{ "shape":"ChecksumSHA256", - "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This header specifies the base64-encoded, 256-bit SHA-256 digest of the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", + "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This header specifies the Base64 encoded, 256-bit SHA-256 digest of the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", "location":"header", "locationName":"x-amz-checksum-sha256" }, + "ChecksumType":{ + "shape":"ChecksumType", + "documentation":"

    This header specifies the checksum type of the object, which determines how part-level checksums are combined to create an object-level checksum for multipart objects. You can use this header as a data integrity check to verify that the checksum type that is received is the same checksum that was specified. If the checksum type doesn’t match the checksum type that was specified for the object during the CreateMultipartUpload request, it’ll result in a BadDigest error. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", + "location":"header", + "locationName":"x-amz-checksum-type" + }, + "MpuObjectSize":{ + "shape":"MpuObjectSize", + "documentation":"

    The expected total object size of the multipart upload request. If there’s a mismatch between the specified object size value and the actual object size value, it results in an HTTP 400 InvalidRequest error.

    ", + "location":"header", + "locationName":"x-amz-mp-object-size" + }, "RequestPayer":{ "shape":"RequestPayer", "location":"header", @@ -2264,19 +2308,23 @@ }, "ChecksumCRC32":{ "shape":"ChecksumCRC32", - "documentation":"

    The base64-encoded, 32-bit CRC-32 checksum of the object. This will only be present if it was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    " + "documentation":"

    The Base64 encoded, 32-bit CRC-32 checksum of the part. This checksum is present if the multipart upload request was created with the CRC-32 checksum algorithm. For more information, see Checking object integrity in the Amazon S3 User Guide.

    " }, "ChecksumCRC32C":{ "shape":"ChecksumCRC32C", - "documentation":"

    The base64-encoded, 32-bit CRC-32C checksum of the object. This will only be present if it was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    " + "documentation":"

    The Base64 encoded, 32-bit CRC-32C checksum of the part. This checksum is present if the multipart upload request was created with the CRC-32C checksum algorithm. For more information, see Checking object integrity in the Amazon S3 User Guide.

    " + }, + "ChecksumCRC64NVME":{ + "shape":"ChecksumCRC64NVME", + "documentation":"

    The Base64 encoded, 64-bit CRC-64NVME checksum of the part. This checksum is present if the multipart upload request was created with the CRC-64NVME checksum algorithm to the uploaded object). For more information, see Checking object integrity in the Amazon S3 User Guide.

    " }, "ChecksumSHA1":{ "shape":"ChecksumSHA1", - "documentation":"

    The base64-encoded, 160-bit SHA-1 digest of the object. This will only be present if it was uploaded with the object. When you use the API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    " + "documentation":"

    The Base64 encoded, 160-bit SHA-1 checksum of the part. This checksum is present if the multipart upload request was created with the SHA-1 checksum algorithm. For more information, see Checking object integrity in the Amazon S3 User Guide.

    " }, "ChecksumSHA256":{ "shape":"ChecksumSHA256", - "documentation":"

    The base64-encoded, 256-bit SHA-256 digest of the object. This will only be present if it was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    " + "documentation":"

    The Base64 encoded, 256-bit SHA-256 checksum of the part. This checksum is present if the multipart upload request was created with the SHA-256 checksum algorithm. For more information, see Checking object integrity in the Amazon S3 User Guide.

    " }, "PartNumber":{ "shape":"PartNumber", @@ -2381,7 +2429,7 @@ }, "SSEKMSEncryptionContext":{ "shape":"SSEKMSEncryptionContext", - "documentation":"

    If present, indicates the Amazon Web Services KMS Encryption Context to use for object encryption. The value of this header is a base64-encoded UTF-8 string holding JSON with the encryption context key-value pairs.

    ", + "documentation":"

    If present, indicates the Amazon Web Services KMS Encryption Context to use for object encryption. The value of this header is a Base64 encoded UTF-8 string holding JSON with the encryption context key-value pairs.

    ", "location":"header", "locationName":"x-amz-server-side-encryption-context" }, @@ -2668,21 +2716,29 @@ "shape":"LastModified", "documentation":"

    Creation date of the object.

    " }, + "ChecksumType":{ + "shape":"ChecksumType", + "documentation":"

    The checksum type that is used to calculate the object’s checksum value. For more information, see Checking object integrity in the Amazon S3 User Guide.

    " + }, "ChecksumCRC32":{ "shape":"ChecksumCRC32", - "documentation":"

    The base64-encoded, 32-bit CRC-32 checksum of the object. This will only be present if it was uploaded with the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    " + "documentation":"

    The Base64 encoded, 32-bit CRC-32 checksum of the object. This checksum is only present if the object was uploaded with the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    " }, "ChecksumCRC32C":{ "shape":"ChecksumCRC32C", - "documentation":"

    The base64-encoded, 32-bit CRC-32C checksum of the object. This will only be present if it was uploaded with the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    " + "documentation":"

    The Base64 encoded, 32-bit CRC-32C checksum of the object. This will only be present if the object was uploaded with the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    " + }, + "ChecksumCRC64NVME":{ + "shape":"ChecksumCRC64NVME", + "documentation":"

    The Base64 encoded, 64-bit CRC-64NVME checksum of the object. This checksum is present if the object being copied was uploaded with the CRC-64NVME checksum algorithm, or if the object was uploaded without a checksum (and Amazon S3 added the default checksum, CRC-64NVME, to the uploaded object). For more information, see Checking object integrity in the Amazon S3 User Guide.

    " }, "ChecksumSHA1":{ "shape":"ChecksumSHA1", - "documentation":"

    The base64-encoded, 160-bit SHA-1 digest of the object. This will only be present if it was uploaded with the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    " + "documentation":"

    The Base64 encoded, 160-bit SHA-1 digest of the object. This will only be present if the object was uploaded with the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    " }, "ChecksumSHA256":{ "shape":"ChecksumSHA256", - "documentation":"

    The base64-encoded, 256-bit SHA-256 digest of the object. This will only be present if it was uploaded with the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    " + "documentation":"

    The Base64 encoded, 256-bit SHA-256 digest of the object. This will only be present if the object was uploaded with the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    " } }, "documentation":"

    Container for all response elements.

    " @@ -2700,19 +2756,23 @@ }, "ChecksumCRC32":{ "shape":"ChecksumCRC32", - "documentation":"

    The base64-encoded, 32-bit CRC-32 checksum of the object. This will only be present if it was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    " + "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This header specifies the Base64 encoded, 32-bit CRC-32 checksum of the part. For more information, see Checking object integrity in the Amazon S3 User Guide.

    " }, "ChecksumCRC32C":{ "shape":"ChecksumCRC32C", - "documentation":"

    The base64-encoded, 32-bit CRC-32C checksum of the object. This will only be present if it was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    " + "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This header specifies the Base64 encoded, 32-bit CRC-32C checksum of the part. For more information, see Checking object integrity in the Amazon S3 User Guide.

    " + }, + "ChecksumCRC64NVME":{ + "shape":"ChecksumCRC64NVME", + "documentation":"

    The Base64 encoded, 64-bit CRC-64NVME checksum of the part. This checksum is present if the multipart upload request was created with the CRC-64NVME checksum algorithm to the uploaded object). For more information, see Checking object integrity in the Amazon S3 User Guide.

    " }, "ChecksumSHA1":{ "shape":"ChecksumSHA1", - "documentation":"

    The base64-encoded, 160-bit SHA-1 digest of the object. This will only be present if it was uploaded with the object. When you use the API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    " + "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This header specifies the Base64 encoded, 160-bit SHA-1 checksum of the part. For more information, see Checking object integrity in the Amazon S3 User Guide.

    " }, "ChecksumSHA256":{ "shape":"ChecksumSHA256", - "documentation":"

    The base64-encoded, 256-bit SHA-256 digest of the object. This will only be present if it was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    " + "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This header specifies the Base64 encoded, 256-bit SHA-256 checksum of the part. For more information, see Checking object integrity in the Amazon S3 User Guide.

    " } }, "documentation":"

    Container for all response elements.

    " @@ -2738,11 +2798,11 @@ "members":{ "LocationConstraint":{ "shape":"BucketLocationConstraint", - "documentation":"

    Specifies the Region where the bucket will be created. You might choose a Region to optimize latency, minimize costs, or address regulatory requirements. For example, if you reside in Europe, you will probably find it advantageous to create buckets in the Europe (Ireland) Region.

    If you don't specify a Region, the bucket is created in the US East (N. Virginia) Region (us-east-1) by default.

    For a list of the valid values for all of the Amazon Web Services Regions, see Regions and Endpoints.

    This functionality is not supported for directory buckets.

    " + "documentation":"

    Specifies the Region where the bucket will be created. You might choose a Region to optimize latency, minimize costs, or address regulatory requirements. For example, if you reside in Europe, you will probably find it advantageous to create buckets in the Europe (Ireland) Region. For more information, see Accessing a bucket in the Amazon S3 User Guide.

    If you don't specify a Region, the bucket is created in the US East (N. Virginia) Region (us-east-1) by default.

    This functionality is not supported for directory buckets.

    " }, "Location":{ "shape":"LocationInfo", - "documentation":"

    Specifies the location where the bucket will be created.

    Directory buckets - The location type is Availability Zone or Local Zone. To use the Local Zone location type, your account must be enabled for Dedicated Local Zones. Otherwise, you get an HTTP 403 Forbidden error with the error code AccessDenied. To learn more, see Enable accounts for Dedicated Local Zones in the Amazon S3 User Guide.

    This functionality is only supported by directory buckets.

    " + "documentation":"

    Specifies the location where the bucket will be created.

    Directory buckets - The location type is Availability Zone or Local Zone. When the location type is Local Zone, your Local Zone must be in opt-in status. Otherwise, you get an HTTP 400 Bad Request error with the error code Access denied. To learn more about opt-in Local Zones, see Opt-in Dedicated Local Zonesin the Amazon S3 User Guide.

    This functionality is only supported by directory buckets.

    " }, "Bucket":{ "shape":"BucketInfo", @@ -2924,7 +2984,7 @@ }, "SSEKMSEncryptionContext":{ "shape":"SSEKMSEncryptionContext", - "documentation":"

    If present, indicates the Amazon Web Services KMS Encryption Context to use for object encryption. The value of this header is a Base64-encoded string of a UTF-8 encoded JSON, which contains the encryption context as key-value pairs.

    ", + "documentation":"

    If present, indicates the Amazon Web Services KMS Encryption Context to use for object encryption. The value of this header is a Base64 encoded string of a UTF-8 encoded JSON, which contains the encryption context as key-value pairs.

    ", "location":"header", "locationName":"x-amz-server-side-encryption-context" }, @@ -2944,6 +3004,12 @@ "documentation":"

    The algorithm that was used to create a checksum of the object.

    ", "location":"header", "locationName":"x-amz-checksum-algorithm" + }, + "ChecksumType":{ + "shape":"ChecksumType", + "documentation":"

    Indicates the checksum type that you want Amazon S3 to use to calculate the object’s checksum value. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", + "location":"header", + "locationName":"x-amz-checksum-type" } } }, @@ -3084,7 +3150,7 @@ }, "SSEKMSEncryptionContext":{ "shape":"SSEKMSEncryptionContext", - "documentation":"

    Specifies the Amazon Web Services KMS Encryption Context to use for object encryption. The value of this header is a Base64-encoded string of a UTF-8 encoded JSON, which contains the encryption context as key-value pairs.

    Directory buckets - You can optionally provide an explicit encryption context value. The value must match the default encryption context - the bucket Amazon Resource Name (ARN). An additional encryption context value is not supported.

    ", + "documentation":"

    Specifies the Amazon Web Services KMS Encryption Context to use for object encryption. The value of this header is a Base64 encoded string of a UTF-8 encoded JSON, which contains the encryption context as key-value pairs.

    Directory buckets - You can optionally provide an explicit encryption context value. The value must match the default encryption context - the bucket Amazon Resource Name (ARN). An additional encryption context value is not supported.

    ", "location":"header", "locationName":"x-amz-server-side-encryption-context" }, @@ -3134,6 +3200,12 @@ "documentation":"

    Indicates the algorithm that you want Amazon S3 to use to create the checksum for the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", "location":"header", "locationName":"x-amz-checksum-algorithm" + }, + "ChecksumType":{ + "shape":"ChecksumType", + "documentation":"

    Indicates the checksum type that you want Amazon S3 to use to calculate the object’s checksum value. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", + "location":"header", + "locationName":"x-amz-checksum-type" } } }, @@ -3155,7 +3227,7 @@ }, "SSEKMSEncryptionContext":{ "shape":"SSEKMSEncryptionContext", - "documentation":"

    If present, indicates the Amazon Web Services KMS Encryption Context to use for object encryption. The value of this header is a Base64-encoded string of a UTF-8 encoded JSON, which contains the encryption context as key-value pairs. This value is stored as object metadata and automatically gets passed on to Amazon Web Services KMS for future GetObject operations on this object.

    ", + "documentation":"

    If present, indicates the Amazon Web Services KMS Encryption Context to use for object encryption. The value of this header is a Base64 encoded string of a UTF-8 encoded JSON, which contains the encryption context as key-value pairs. This value is stored as object metadata and automatically gets passed on to Amazon Web Services KMS for future GetObject operations on this object.

    ", "location":"header", "locationName":"x-amz-server-side-encryption-context" }, @@ -3203,7 +3275,7 @@ }, "SSEKMSEncryptionContext":{ "shape":"SSEKMSEncryptionContext", - "documentation":"

    Specifies the Amazon Web Services KMS Encryption Context as an additional encryption context to use for object encryption. The value of this header is a Base64-encoded string of a UTF-8 encoded JSON, which contains the encryption context as key-value pairs. This value is stored as object metadata and automatically gets passed on to Amazon Web Services KMS for future GetObject operations on this object.

    General purpose buckets - This value must be explicitly added during CopyObject operations if you want an additional encryption context for your object. For more information, see Encryption context in the Amazon S3 User Guide.

    Directory buckets - You can optionally provide an explicit encryption context value. The value must match the default encryption context - the bucket Amazon Resource Name (ARN). An additional encryption context value is not supported.

    ", + "documentation":"

    Specifies the Amazon Web Services KMS Encryption Context as an additional encryption context to use for object encryption. The value of this header is a Base64 encoded string of a UTF-8 encoded JSON, which contains the encryption context as key-value pairs. This value is stored as object metadata and automatically gets passed on to Amazon Web Services KMS for future GetObject operations on this object.

    General purpose buckets - This value must be explicitly added during CopyObject operations if you want an additional encryption context for your object. For more information, see Encryption context in the Amazon S3 User Guide.

    Directory buckets - You can optionally provide an explicit encryption context value. The value must match the default encryption context - the bucket Amazon Resource Name (ARN). An additional encryption context value is not supported.

    ", "location":"header", "locationName":"x-amz-server-side-encryption-context" }, @@ -3816,7 +3888,7 @@ }, "ChecksumAlgorithm":{ "shape":"ChecksumAlgorithm", - "documentation":"

    Indicates the algorithm used to create the checksum for the object when you use the SDK. This header will not provide any additional functionality if you don't use the SDK. When you send this header, there must be a corresponding x-amz-checksum-algorithm or x-amz-trailer header sent. Otherwise, Amazon S3 fails the request with the HTTP status code 400 Bad Request.

    For the x-amz-checksum-algorithm header, replace algorithm with the supported algorithm from the following list:

    • CRC32

    • CRC32C

    • SHA1

    • SHA256

    For more information, see Checking object integrity in the Amazon S3 User Guide.

    If the individual checksum value you provide through x-amz-checksum-algorithm doesn't match the checksum algorithm you set through x-amz-sdk-checksum-algorithm, Amazon S3 ignores any provided ChecksumAlgorithm parameter and uses the checksum algorithm that matches the provided value in x-amz-checksum-algorithm .

    If you provide an individual checksum, Amazon S3 ignores any provided ChecksumAlgorithm parameter.

    ", + "documentation":"

    Indicates the algorithm used to create the checksum for the object when you use the SDK. This header will not provide any additional functionality if you don't use the SDK. When you send this header, there must be a corresponding x-amz-checksum-algorithm or x-amz-trailer header sent. Otherwise, Amazon S3 fails the request with the HTTP status code 400 Bad Request.

    For the x-amz-checksum-algorithm header, replace algorithm with the supported algorithm from the following list:

    • CRC-32

    • CRC-32C

    • CRC-64NVME

    • SHA-1

    • SHA-256

    For more information, see Checking object integrity in the Amazon S3 User Guide.

    If the individual checksum value you provide through x-amz-checksum-algorithm doesn't match the checksum algorithm you set through x-amz-sdk-checksum-algorithm, Amazon S3 fails the request with a BadDigest error.

    If you provide an individual checksum, Amazon S3 ignores any provided ChecksumAlgorithm parameter.

    ", "location":"header", "locationName":"x-amz-sdk-checksum-algorithm" } @@ -4396,7 +4468,7 @@ }, "TransitionDefaultMinimumObjectSize":{ "shape":"TransitionDefaultMinimumObjectSize", - "documentation":"

    Indicates which default minimum object size behavior is applied to the lifecycle configuration.

    This parameter applies to general purpose buckets only. It is not supported for directory bucket lifecycle configurations.

    • all_storage_classes_128K - Objects smaller than 128 KB will not transition to any storage class by default.

    • varies_by_storage_class - Objects smaller than 128 KB will transition to Glacier Flexible Retrieval or Glacier Deep Archive storage classes. By default, all other storage classes will prevent transitions smaller than 128 KB.

    To customize the minimum object size for any transition you can add a filter that specifies a custom ObjectSizeGreaterThan or ObjectSizeLessThan in the body of your transition rule. Custom filters always take precedence over the default transition behavior.

    ", + "documentation":"

    Indicates which default minimum object size behavior is applied to the lifecycle configuration.

    This parameter applies to general purpose buckets only. It isn't supported for directory bucket lifecycle configurations.

    • all_storage_classes_128K - Objects smaller than 128 KB will not transition to any storage class by default.

    • varies_by_storage_class - Objects smaller than 128 KB will transition to Glacier Flexible Retrieval or Glacier Deep Archive storage classes. By default, all other storage classes will prevent transitions smaller than 128 KB.

    To customize the minimum object size for any transition you can add a filter that specifies a custom ObjectSizeGreaterThan or ObjectSizeLessThan in the body of your transition rule. Custom filters always take precedence over the default transition behavior.

    ", "location":"header", "locationName":"x-amz-transition-default-minimum-object-size" } @@ -5200,28 +5272,40 @@ }, "ChecksumCRC32":{ "shape":"ChecksumCRC32", - "documentation":"

    The base64-encoded, 32-bit CRC-32 checksum of the object. This will only be present if it was uploaded with the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", + "documentation":"

    The Base64 encoded, 32-bit CRC-32 checksum of the object. This checksum is only present if the object was uploaded with the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", "location":"header", "locationName":"x-amz-checksum-crc32" }, "ChecksumCRC32C":{ "shape":"ChecksumCRC32C", - "documentation":"

    The base64-encoded, 32-bit CRC-32C checksum of the object. This will only be present if it was uploaded with the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", + "documentation":"

    The Base64 encoded, 32-bit CRC-32C checksum of the object. This will only be present if the object was uploaded with the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", "location":"header", "locationName":"x-amz-checksum-crc32c" }, + "ChecksumCRC64NVME":{ + "shape":"ChecksumCRC64NVME", + "documentation":"

    The Base64 encoded, 64-bit CRC-64NVME checksum of the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", + "location":"header", + "locationName":"x-amz-checksum-crc64nvme" + }, "ChecksumSHA1":{ "shape":"ChecksumSHA1", - "documentation":"

    The base64-encoded, 160-bit SHA-1 digest of the object. This will only be present if it was uploaded with the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", + "documentation":"

    The Base64 encoded, 160-bit SHA-1 digest of the object. This will only be present if the object was uploaded with the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", "location":"header", "locationName":"x-amz-checksum-sha1" }, "ChecksumSHA256":{ "shape":"ChecksumSHA256", - "documentation":"

    The base64-encoded, 256-bit SHA-256 digest of the object. This will only be present if it was uploaded with the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", + "documentation":"

    The Base64 encoded, 256-bit SHA-256 digest of the object. This will only be present if the object was uploaded with the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", "location":"header", "locationName":"x-amz-checksum-sha256" }, + "ChecksumType":{ + "shape":"ChecksumType", + "documentation":"

    The checksum type, which determines how part-level checksums are combined to create an object-level checksum for multipart objects. You can use this header response to verify that the checksum type that is received is the same checksum type that was specified in the CreateMultipartUpload request. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", + "location":"header", + "locationName":"x-amz-checksum-type" + }, "MissingMeta":{ "shape":"MissingMeta", "documentation":"

    This is set to the number of metadata entries not returned in the headers that are prefixed with x-amz-meta-. This can happen if you create metadata using an API like SOAP that supports more flexible metadata than the REST API. For example, using SOAP, you can create metadata whose values are not legal HTTP headers.

    This functionality is not supported for directory buckets.

    ", @@ -5856,28 +5940,40 @@ }, "ChecksumCRC32":{ "shape":"ChecksumCRC32", - "documentation":"

    The base64-encoded, 32-bit CRC-32 checksum of the object. This will only be present if it was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    ", + "documentation":"

    The Base64 encoded, 32-bit CRC-32 checksum of the object. This checksum is only be present if the checksum was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    ", "location":"header", "locationName":"x-amz-checksum-crc32" }, "ChecksumCRC32C":{ "shape":"ChecksumCRC32C", - "documentation":"

    The base64-encoded, 32-bit CRC-32C checksum of the object. This will only be present if it was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    ", + "documentation":"

    The Base64 encoded, 32-bit CRC-32C checksum of the object. This checksum is only present if the checksum was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    ", "location":"header", "locationName":"x-amz-checksum-crc32c" }, + "ChecksumCRC64NVME":{ + "shape":"ChecksumCRC64NVME", + "documentation":"

    The Base64 encoded, 64-bit CRC-64NVME checksum of the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", + "location":"header", + "locationName":"x-amz-checksum-crc64nvme" + }, "ChecksumSHA1":{ "shape":"ChecksumSHA1", - "documentation":"

    The base64-encoded, 160-bit SHA-1 digest of the object. This will only be present if it was uploaded with the object. When you use the API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    ", + "documentation":"

    The Base64 encoded, 160-bit SHA-1 digest of the object. This will only be present if the object was uploaded with the object. When you use the API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    ", "location":"header", "locationName":"x-amz-checksum-sha1" }, "ChecksumSHA256":{ "shape":"ChecksumSHA256", - "documentation":"

    The base64-encoded, 256-bit SHA-256 digest of the object. This will only be present if it was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    ", + "documentation":"

    The Base64 encoded, 256-bit SHA-256 digest of the object. This will only be present if the object was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    ", "location":"header", "locationName":"x-amz-checksum-sha256" }, + "ChecksumType":{ + "shape":"ChecksumType", + "documentation":"

    The checksum type, which determines how part-level checksums are combined to create an object-level checksum for multipart objects. You can use this header response to verify that the checksum type that is received is the same checksum type that was specified in CreateMultipartUpload request. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", + "location":"header", + "locationName":"x-amz-checksum-type" + }, "ETag":{ "shape":"ETag", "documentation":"

    An entity tag (ETag) is an opaque identifier assigned by a web server to a specific version of a resource found at a URL.

    ", @@ -7533,6 +7629,10 @@ "ChecksumAlgorithm":{ "shape":"ChecksumAlgorithm", "documentation":"

    The algorithm that was used to create a checksum of the object.

    " + }, + "ChecksumType":{ + "shape":"ChecksumType", + "documentation":"

    The checksum type, which determines how part-level checksums are combined to create an object-level checksum for multipart objects. You can use this header response to verify that the checksum type that is received is the same checksum type that was specified in CreateMultipartUpload request. For more information, see Checking object integrity in the Amazon S3 User Guide.

    " } } }, @@ -7620,7 +7720,7 @@ "documentation":"

    The name of the location where the bucket will be created.

    For directory buckets, the name of the location is the Zone ID of the Availability Zone (AZ) or Local Zone (LZ) where the bucket will be created. An example AZ ID value is usw2-az1.

    " } }, - "documentation":"

    Specifies the location where the bucket will be created.

    For directory buckets, the location type is Availability Zone or Local Zone. For more information about directory buckets, see Working with directory buckets in the Amazon S3 User Guide.

    This functionality is only supported by directory buckets.

    " + "documentation":"

    Specifies the location where the bucket will be created.

    For directory buckets, the location type is Availability Zone or Local Zone. For more information about directory buckets, see Directory buckets in the Amazon S3 User Guide.

    This functionality is only supported by directory buckets.

    " }, "LocationNameAsString":{"type":"string"}, "LocationPrefix":{"type":"string"}, @@ -7834,6 +7934,7 @@ "box":true }, "MissingMeta":{"type":"integer"}, + "MpuObjectSize":{"type":"integer"}, "MultipartUpload":{ "type":"structure", "members":{ @@ -7864,6 +7965,10 @@ "ChecksumAlgorithm":{ "shape":"ChecksumAlgorithm", "documentation":"

    The algorithm that was used to create a checksum of the object.

    " + }, + "ChecksumType":{ + "shape":"ChecksumType", + "documentation":"

    The checksum type that is used to calculate the object’s checksum value. For more information, see Checking object integrity in the Amazon S3 User Guide.

    " } }, "documentation":"

    Container for the MultipartUpload for the Amazon S3 object.

    " @@ -8019,6 +8124,10 @@ "shape":"ChecksumAlgorithmList", "documentation":"

    The algorithm that was used to create a checksum of the object.

    " }, + "ChecksumType":{ + "shape":"ChecksumType", + "documentation":"

    The checksum type that is used to calculate the object’s checksum value. For more information, see Checking object integrity in the Amazon S3 User Guide.

    " + }, "Size":{ "shape":"Size", "documentation":"

    Size in bytes of the object

    " @@ -8225,19 +8334,23 @@ }, "ChecksumCRC32":{ "shape":"ChecksumCRC32", - "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This header specifies the base64-encoded, 32-bit CRC-32 checksum of the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    " + "documentation":"

    The Base64 encoded, 32-bit CRC-32 checksum of the part. This checksum is present if the multipart upload request was created with the CRC-32 checksum algorithm. For more information, see Checking object integrity in the Amazon S3 User Guide.

    " }, "ChecksumCRC32C":{ "shape":"ChecksumCRC32C", - "documentation":"

    The base64-encoded, 32-bit CRC-32C checksum of the object. This will only be present if it was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    " + "documentation":"

    The Base64 encoded, 32-bit CRC-32C checksum of the part. This checksum is present if the multipart upload request was created with the CRC-32C checksum algorithm. For more information, see Checking object integrity in the Amazon S3 User Guide.

    " + }, + "ChecksumCRC64NVME":{ + "shape":"ChecksumCRC64NVME", + "documentation":"

    The Base64 encoded, 64-bit CRC-64NVME checksum of the part. This checksum is present if the multipart upload request was created with the CRC-64NVME checksum algorithm, or if the object was uploaded without a checksum (and Amazon S3 added the default checksum, CRC-64NVME, to the uploaded object). For more information, see Checking object integrity in the Amazon S3 User Guide.

    " }, "ChecksumSHA1":{ "shape":"ChecksumSHA1", - "documentation":"

    The base64-encoded, 160-bit SHA-1 digest of the object. This will only be present if it was uploaded with the object. When you use the API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    " + "documentation":"

    The Base64 encoded, 160-bit SHA-1 checksum of the part. This checksum is present if the multipart upload request was created with the SHA-1 checksum algorithm. For more information, see Checking object integrity in the Amazon S3 User Guide.

    " }, "ChecksumSHA256":{ "shape":"ChecksumSHA256", - "documentation":"

    The base64-encoded, 256-bit SHA-256 digest of the object. This will only be present if it was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    " + "documentation":"

    The Base64 encoded, 256-bit SHA-256 checksum of the part. This checksum is present if the multipart upload request was created with the SHA-256 checksum algorithm. For more information, see Checking object integrity in the Amazon S3 User Guide.

    " } }, "documentation":"

    A container for elements related to an individual part.

    " @@ -8281,6 +8394,10 @@ "shape":"ChecksumAlgorithmList", "documentation":"

    The algorithm that was used to create a checksum of the object.

    " }, + "ChecksumType":{ + "shape":"ChecksumType", + "documentation":"

    The checksum type that is used to calculate the object’s checksum value. For more information, see Checking object integrity in the Amazon S3 User Guide.

    " + }, "Size":{ "shape":"Size", "documentation":"

    Size in bytes of the object.

    " @@ -8428,19 +8545,23 @@ }, "ChecksumCRC32":{ "shape":"ChecksumCRC32", - "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This header specifies the base64-encoded, 32-bit CRC-32 checksum of the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    " + "documentation":"

    The Base64 encoded, 32-bit CRC-32 checksum of the part. This checksum is present if the object was uploaded with the CRC-32 checksum algorithm. For more information, see Checking object integrity in the Amazon S3 User Guide.

    " }, "ChecksumCRC32C":{ "shape":"ChecksumCRC32C", - "documentation":"

    The base64-encoded, 32-bit CRC-32C checksum of the object. This will only be present if it was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    " + "documentation":"

    The Base64 encoded, 32-bit CRC-32C checksum of the part. This checksum is present if the object was uploaded with the CRC-32C checksum algorithm. For more information, see Checking object integrity in the Amazon S3 User Guide.

    " + }, + "ChecksumCRC64NVME":{ + "shape":"ChecksumCRC64NVME", + "documentation":"

    The Base64 encoded, 64-bit CRC-64NVME checksum of the part. This checksum is present if the multipart upload request was created with the CRC-64NVME checksum algorithm, or if the object was uploaded without a checksum (and Amazon S3 added the default checksum, CRC-64NVME, to the uploaded object). For more information, see Checking object integrity in the Amazon S3 User Guide.

    " }, "ChecksumSHA1":{ "shape":"ChecksumSHA1", - "documentation":"

    The base64-encoded, 160-bit SHA-1 digest of the object. This will only be present if it was uploaded with the object. When you use the API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    " + "documentation":"

    The Base64 encoded, 160-bit SHA-1 checksum of the part. This checksum is present if the object was uploaded with the SHA-1 checksum algorithm. For more information, see Checking object integrity in the Amazon S3 User Guide.

    " }, "ChecksumSHA256":{ "shape":"ChecksumSHA256", - "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This header specifies the base64-encoded, 256-bit SHA-256 digest of the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    " + "documentation":"

    The Base64 encoded, 256-bit SHA-256 checksum of the part. This checksum is present if the object was uploaded with the SHA-256 checksum algorithm. For more information, see Checking object integrity in the Amazon S3 User Guide.

    " } }, "documentation":"

    Container for elements related to a part.

    " @@ -8636,7 +8757,7 @@ }, "ContentMD5":{ "shape":"ContentMD5", - "documentation":"

    The base64-encoded 128-bit MD5 digest of the data. This header must be used as a message integrity check to verify that the request body was not corrupted in transit. For more information, go to RFC 1864.

    For requests made using the Amazon Web Services Command Line Interface (CLI) or Amazon Web Services SDKs, this field is calculated automatically.

    ", + "documentation":"

    The Base64 encoded 128-bit MD5 digest of the data. This header must be used as a message integrity check to verify that the request body was not corrupted in transit. For more information, go to RFC 1864.

    For requests made using the Amazon Web Services Command Line Interface (CLI) or Amazon Web Services SDKs, this field is calculated automatically.

    ", "location":"header", "locationName":"Content-MD5" }, @@ -8743,7 +8864,7 @@ }, "ContentMD5":{ "shape":"ContentMD5", - "documentation":"

    The base64-encoded 128-bit MD5 digest of the data. This header must be used as a message integrity check to verify that the request body was not corrupted in transit. For more information, go to RFC 1864.

    For requests made using the Amazon Web Services Command Line Interface (CLI) or Amazon Web Services SDKs, this field is calculated automatically.

    ", + "documentation":"

    The Base64 encoded 128-bit MD5 digest of the data. This header must be used as a message integrity check to verify that the request body was not corrupted in transit. For more information, go to RFC 1864.

    For requests made using the Amazon Web Services Command Line Interface (CLI) or Amazon Web Services SDKs, this field is calculated automatically.

    ", "location":"header", "locationName":"Content-MD5" }, @@ -8778,7 +8899,7 @@ }, "ContentMD5":{ "shape":"ContentMD5", - "documentation":"

    The base64-encoded 128-bit MD5 digest of the server-side encryption configuration.

    For requests made using the Amazon Web Services Command Line Interface (CLI) or Amazon Web Services SDKs, this field is calculated automatically.

    This functionality is not supported for directory buckets.

    ", + "documentation":"

    The Base64 encoded 128-bit MD5 digest of the server-side encryption configuration.

    For requests made using the Amazon Web Services Command Line Interface (CLI) or Amazon Web Services SDKs, this field is calculated automatically.

    This functionality is not supported for directory buckets.

    ", "location":"header", "locationName":"Content-MD5" }, @@ -9164,7 +9285,7 @@ }, "ChecksumAlgorithm":{ "shape":"ChecksumAlgorithm", - "documentation":"

    Indicates the algorithm used to create the checksum for the object when you use the SDK. This header will not provide any additional functionality if you don't use the SDK. When you send this header, there must be a corresponding x-amz-checksum-algorithm or x-amz-trailer header sent. Otherwise, Amazon S3 fails the request with the HTTP status code 400 Bad Request.

    For the x-amz-checksum-algorithm header, replace algorithm with the supported algorithm from the following list:

    • CRC32

    • CRC32C

    • SHA1

    • SHA256

    For more information, see Checking object integrity in the Amazon S3 User Guide.

    If the individual checksum value you provide through x-amz-checksum-algorithm doesn't match the checksum algorithm you set through x-amz-sdk-checksum-algorithm, Amazon S3 ignores any provided ChecksumAlgorithm parameter and uses the checksum algorithm that matches the provided value in x-amz-checksum-algorithm .

    For directory buckets, when you use Amazon Web Services SDKs, CRC32 is the default checksum algorithm that's used for performance.

    ", + "documentation":"

    Indicates the algorithm used to create the checksum for the object when you use the SDK. This header will not provide any additional functionality if you don't use the SDK. When you send this header, there must be a corresponding x-amz-checksum-algorithm or x-amz-trailer header sent. Otherwise, Amazon S3 fails the request with the HTTP status code 400 Bad Request.

    For the x-amz-checksum-algorithm header, replace algorithm with the supported algorithm from the following list:

    • CRC-32

    • CRC-32C

    • CRC-64NVME

    • SHA-1

    • SHA-256

    For more information, see Checking object integrity in the Amazon S3 User Guide.

    If the individual checksum value you provide through x-amz-checksum-algorithm doesn't match the checksum algorithm you set through x-amz-sdk-checksum-algorithm, Amazon S3 fails the request with a BadDigest error.

    For directory buckets, when you use Amazon Web Services SDKs, CRC32 is the default checksum algorithm that's used for performance.

    ", "location":"header", "locationName":"x-amz-sdk-checksum-algorithm" }, @@ -9203,7 +9324,7 @@ }, "ContentMD5":{ "shape":"ContentMD5", - "documentation":"

    The base64-encoded 128-bit MD5 digest of the data. You must use this header as a message integrity check to verify that the request body was not corrupted in transit. For more information, see RFC 1864.

    For requests made using the Amazon Web Services Command Line Interface (CLI) or Amazon Web Services SDKs, this field is calculated automatically.

    ", + "documentation":"

    The Base64 encoded 128-bit MD5 digest of the data. You must use this header as a message integrity check to verify that the request body was not corrupted in transit. For more information, see RFC 1864.

    For requests made using the Amazon Web Services Command Line Interface (CLI) or Amazon Web Services SDKs, this field is calculated automatically.

    ", "location":"header", "locationName":"Content-MD5" }, @@ -9249,7 +9370,7 @@ }, "ContentMD5":{ "shape":"ContentMD5", - "documentation":"

    The base64-encoded 128-bit MD5 digest of the data. You must use this header as a message integrity check to verify that the request body was not corrupted in transit. For more information, see RFC 1864.

    For requests made using the Amazon Web Services Command Line Interface (CLI) or Amazon Web Services SDKs, this field is calculated automatically.

    ", + "documentation":"

    The Base64 encoded 128-bit MD5 digest of the data. You must use this header as a message integrity check to verify that the request body was not corrupted in transit. For more information, see RFC 1864.

    For requests made using the Amazon Web Services Command Line Interface (CLI) or Amazon Web Services SDKs, this field is calculated automatically.

    ", "location":"header", "locationName":"Content-MD5" }, @@ -9290,7 +9411,7 @@ }, "ContentMD5":{ "shape":"ContentMD5", - "documentation":"

    The base64-encoded 128-bit MD5 digest of the data. You must use this header as a message integrity check to verify that the request body was not corrupted in transit. For more information, see RFC 1864.

    For requests made using the Amazon Web Services Command Line Interface (CLI) or Amazon Web Services SDKs, this field is calculated automatically.

    ", + "documentation":"

    The Base64 encoded 128-bit MD5 digest of the data. You must use this header as a message integrity check to verify that the request body was not corrupted in transit. For more information, see RFC 1864.

    For requests made using the Amazon Web Services Command Line Interface (CLI) or Amazon Web Services SDKs, this field is calculated automatically.

    ", "location":"header", "locationName":"Content-MD5" }, @@ -9331,7 +9452,7 @@ }, "ContentMD5":{ "shape":"ContentMD5", - "documentation":"

    >The base64-encoded 128-bit MD5 digest of the data. You must use this header as a message integrity check to verify that the request body was not corrupted in transit. For more information, see RFC 1864.

    For requests made using the Amazon Web Services Command Line Interface (CLI) or Amazon Web Services SDKs, this field is calculated automatically.

    ", + "documentation":"

    >The Base64 encoded 128-bit MD5 digest of the data. You must use this header as a message integrity check to verify that the request body was not corrupted in transit. For more information, see RFC 1864.

    For requests made using the Amazon Web Services Command Line Interface (CLI) or Amazon Web Services SDKs, this field is calculated automatically.

    ", "location":"header", "locationName":"Content-MD5" }, @@ -9378,7 +9499,7 @@ }, "ContentMD5":{ "shape":"ContentMD5", - "documentation":"

    The base64-encoded 128-bit MD5 digest of the data. You must use this header as a message integrity check to verify that the request body was not corrupted in transit. For more information, see RFC 1864.

    For requests made using the Amazon Web Services Command Line Interface (CLI) or Amazon Web Services SDKs, this field is calculated automatically.

    ", + "documentation":"

    The Base64 encoded 128-bit MD5 digest of the data. You must use this header as a message integrity check to verify that the request body was not corrupted in transit. For more information, see RFC 1864.

    For requests made using the Amazon Web Services Command Line Interface (CLI) or Amazon Web Services SDKs, this field is calculated automatically.

    ", "location":"header", "locationName":"Content-MD5" }, @@ -9441,7 +9562,7 @@ }, "ContentMD5":{ "shape":"ContentMD5", - "documentation":"

    The base64-encoded 128-bit MD5 digest of the data. This header must be used as a message integrity check to verify that the request body was not corrupted in transit. For more information, go to RFC 1864.>

    For requests made using the Amazon Web Services Command Line Interface (CLI) or Amazon Web Services SDKs, this field is calculated automatically.

    ", + "documentation":"

    The Base64 encoded 128-bit MD5 digest of the data. This header must be used as a message integrity check to verify that the request body was not corrupted in transit. For more information, go to RFC 1864.>

    For requests made using the Amazon Web Services Command Line Interface (CLI) or Amazon Web Services SDKs, this field is calculated automatically.

    ", "location":"header", "locationName":"Content-MD5" }, @@ -9652,28 +9773,40 @@ }, "ChecksumCRC32":{ "shape":"ChecksumCRC32", - "documentation":"

    The base64-encoded, 32-bit CRC-32 checksum of the object. This will only be present if it was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    ", + "documentation":"

    The Base64 encoded, 32-bit CRC-32 checksum of the object. This checksum is only be present if the checksum was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    ", "location":"header", "locationName":"x-amz-checksum-crc32" }, "ChecksumCRC32C":{ "shape":"ChecksumCRC32C", - "documentation":"

    The base64-encoded, 32-bit CRC-32C checksum of the object. This will only be present if it was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    ", + "documentation":"

    The Base64 encoded, 32-bit CRC-32C checksum of the object. This checksum is only present if the checksum was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    ", "location":"header", "locationName":"x-amz-checksum-crc32c" }, + "ChecksumCRC64NVME":{ + "shape":"ChecksumCRC64NVME", + "documentation":"

    The Base64 encoded, 64-bit CRC-64NVME checksum of the object. This header is present if the object was uploaded with the CRC-64NVME checksum algorithm, or if it was uploaded without a checksum (and Amazon S3 added the default checksum, CRC-64NVME, to the uploaded object). For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    ", + "location":"header", + "locationName":"x-amz-checksum-crc64nvme" + }, "ChecksumSHA1":{ "shape":"ChecksumSHA1", - "documentation":"

    The base64-encoded, 160-bit SHA-1 digest of the object. This will only be present if it was uploaded with the object. When you use the API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    ", + "documentation":"

    The Base64 encoded, 160-bit SHA-1 digest of the object. This will only be present if the object was uploaded with the object. When you use the API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    ", "location":"header", "locationName":"x-amz-checksum-sha1" }, "ChecksumSHA256":{ "shape":"ChecksumSHA256", - "documentation":"

    The base64-encoded, 256-bit SHA-256 digest of the object. This will only be present if it was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    ", + "documentation":"

    The Base64 encoded, 256-bit SHA-256 digest of the object. This will only be present if the object was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    ", "location":"header", "locationName":"x-amz-checksum-sha256" }, + "ChecksumType":{ + "shape":"ChecksumType", + "documentation":"

    This header specifies the checksum type of the object, which determines how part-level checksums are combined to create an object-level checksum for multipart objects. For PutObject uploads, the checksum type is always FULL_OBJECT. You can use this header as a data integrity check to verify that the checksum type that is received is the same checksum that was specified. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", + "location":"header", + "locationName":"x-amz-checksum-type" + }, "ServerSideEncryption":{ "shape":"ServerSideEncryption", "documentation":"

    The server-side encryption algorithm used when you store this object in Amazon S3.

    ", @@ -9706,7 +9839,7 @@ }, "SSEKMSEncryptionContext":{ "shape":"SSEKMSEncryptionContext", - "documentation":"

    If present, indicates the Amazon Web Services KMS Encryption Context to use for object encryption. The value of this header is a Base64-encoded string of a UTF-8 encoded JSON, which contains the encryption context as key-value pairs. This value is stored as object metadata and automatically gets passed on to Amazon Web Services KMS for future GetObject operations on this object.

    ", + "documentation":"

    If present, indicates the Amazon Web Services KMS Encryption Context to use for object encryption. The value of this header is a Base64 encoded string of a UTF-8 encoded JSON, which contains the encryption context as key-value pairs. This value is stored as object metadata and automatically gets passed on to Amazon Web Services KMS for future GetObject operations on this object.

    ", "location":"header", "locationName":"x-amz-server-side-encryption-context" }, @@ -9718,7 +9851,7 @@ }, "Size":{ "shape":"Size", - "documentation":"

    The size of the object in bytes. This will only be present if you append to an object.

    This functionality is only supported for objects in the Amazon S3 Express One Zone storage class in directory buckets.

    ", + "documentation":"

    The size of the object in bytes. This value is only be present if you append to an object.

    This functionality is only supported for objects in the Amazon S3 Express One Zone storage class in directory buckets.

    ", "location":"header", "locationName":"x-amz-object-size" }, @@ -9786,7 +9919,7 @@ }, "ContentMD5":{ "shape":"ContentMD5", - "documentation":"

    The base64-encoded 128-bit MD5 digest of the message (without the headers) according to RFC 1864. This header can be used as a message integrity check to verify that the data is the same data that was originally sent. Although it is optional, we recommend using the Content-MD5 mechanism as an end-to-end integrity check. For more information about REST request authentication, see REST Authentication.

    The Content-MD5 or x-amz-sdk-checksum-algorithm header is required for any request to upload an object with a retention period configured using Amazon S3 Object Lock. For more information, see Uploading objects to an Object Lock enabled bucket in the Amazon S3 User Guide.

    This functionality is not supported for directory buckets.

    ", + "documentation":"

    The Base64 encoded 128-bit MD5 digest of the message (without the headers) according to RFC 1864. This header can be used as a message integrity check to verify that the data is the same data that was originally sent. Although it is optional, we recommend using the Content-MD5 mechanism as an end-to-end integrity check. For more information about REST request authentication, see REST Authentication.

    The Content-MD5 or x-amz-sdk-checksum-algorithm header is required for any request to upload an object with a retention period configured using Amazon S3 Object Lock. For more information, see Uploading objects to an Object Lock enabled bucket in the Amazon S3 User Guide.

    This functionality is not supported for directory buckets.

    ", "location":"header", "locationName":"Content-MD5" }, @@ -9798,31 +9931,37 @@ }, "ChecksumAlgorithm":{ "shape":"ChecksumAlgorithm", - "documentation":"

    Indicates the algorithm used to create the checksum for the object when you use the SDK. This header will not provide any additional functionality if you don't use the SDK. When you send this header, there must be a corresponding x-amz-checksum-algorithm or x-amz-trailer header sent. Otherwise, Amazon S3 fails the request with the HTTP status code 400 Bad Request.

    For the x-amz-checksum-algorithm header, replace algorithm with the supported algorithm from the following list:

    • CRC32

    • CRC32C

    • SHA1

    • SHA256

    For more information, see Checking object integrity in the Amazon S3 User Guide.

    If the individual checksum value you provide through x-amz-checksum-algorithm doesn't match the checksum algorithm you set through x-amz-sdk-checksum-algorithm, Amazon S3 ignores any provided ChecksumAlgorithm parameter and uses the checksum algorithm that matches the provided value in x-amz-checksum-algorithm .

    The Content-MD5 or x-amz-sdk-checksum-algorithm header is required for any request to upload an object with a retention period configured using Amazon S3 Object Lock. For more information, see Uploading objects to an Object Lock enabled bucket in the Amazon S3 User Guide.

    For directory buckets, when you use Amazon Web Services SDKs, CRC32 is the default checksum algorithm that's used for performance.

    ", + "documentation":"

    Indicates the algorithm used to create the checksum for the object when you use the SDK. This header will not provide any additional functionality if you don't use the SDK. When you send this header, there must be a corresponding x-amz-checksum-algorithm or x-amz-trailer header sent. Otherwise, Amazon S3 fails the request with the HTTP status code 400 Bad Request.

    For the x-amz-checksum-algorithm header, replace algorithm with the supported algorithm from the following list:

    • CRC-32

    • CRC-32C

    • CRC-64NVME

    • SHA-1

    • SHA-256

    For more information, see Checking object integrity in the Amazon S3 User Guide.

    If the individual checksum value you provide through x-amz-checksum-algorithm doesn't match the checksum algorithm you set through x-amz-sdk-checksum-algorithm, Amazon S3 fails the request with a BadDigest error.

    The Content-MD5 or x-amz-sdk-checksum-algorithm header is required for any request to upload an object with a retention period configured using Amazon S3 Object Lock. For more information, see Uploading objects to an Object Lock enabled bucket in the Amazon S3 User Guide.

    For directory buckets, when you use Amazon Web Services SDKs, CRC32 is the default checksum algorithm that's used for performance.

    ", "location":"header", "locationName":"x-amz-sdk-checksum-algorithm" }, "ChecksumCRC32":{ "shape":"ChecksumCRC32", - "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This header specifies the base64-encoded, 32-bit CRC-32 checksum of the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", + "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This header specifies the Base64 encoded, 32-bit CRC-32 checksum of the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", "location":"header", "locationName":"x-amz-checksum-crc32" }, "ChecksumCRC32C":{ "shape":"ChecksumCRC32C", - "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This header specifies the base64-encoded, 32-bit CRC-32C checksum of the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", + "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This header specifies the Base64 encoded, 32-bit CRC-32C checksum of the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", "location":"header", "locationName":"x-amz-checksum-crc32c" }, + "ChecksumCRC64NVME":{ + "shape":"ChecksumCRC64NVME", + "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This header specifies the Base64 encoded, 64-bit CRC-64NVME checksum of the object. The CRC-64NVME checksum is always a full object checksum. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", + "location":"header", + "locationName":"x-amz-checksum-crc64nvme" + }, "ChecksumSHA1":{ "shape":"ChecksumSHA1", - "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This header specifies the base64-encoded, 160-bit SHA-1 digest of the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", + "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This header specifies the Base64 encoded, 160-bit SHA-1 digest of the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", "location":"header", "locationName":"x-amz-checksum-sha1" }, "ChecksumSHA256":{ "shape":"ChecksumSHA256", - "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This header specifies the base64-encoded, 256-bit SHA-256 digest of the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", + "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This header specifies the Base64 encoded, 256-bit SHA-256 digest of the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", "location":"header", "locationName":"x-amz-checksum-sha256" }, @@ -9931,7 +10070,7 @@ }, "SSEKMSEncryptionContext":{ "shape":"SSEKMSEncryptionContext", - "documentation":"

    Specifies the Amazon Web Services KMS Encryption Context as an additional encryption context to use for object encryption. The value of this header is a Base64-encoded string of a UTF-8 encoded JSON, which contains the encryption context as key-value pairs. This value is stored as object metadata and automatically gets passed on to Amazon Web Services KMS for future GetObject operations on this object.

    General purpose buckets - This value must be explicitly added during CopyObject operations if you want an additional encryption context for your object. For more information, see Encryption context in the Amazon S3 User Guide.

    Directory buckets - You can optionally provide an explicit encryption context value. The value must match the default encryption context - the bucket Amazon Resource Name (ARN). An additional encryption context value is not supported.

    ", + "documentation":"

    Specifies the Amazon Web Services KMS Encryption Context as an additional encryption context to use for object encryption. The value of this header is a Base64 encoded string of a UTF-8 encoded JSON, which contains the encryption context as key-value pairs. This value is stored as object metadata and automatically gets passed on to Amazon Web Services KMS for future GetObject operations on this object.

    General purpose buckets - This value must be explicitly added during CopyObject operations if you want an additional encryption context for your object. For more information, see Encryption context in the Amazon S3 User Guide.

    Directory buckets - You can optionally provide an explicit encryption context value. The value must match the default encryption context - the bucket Amazon Resource Name (ARN). An additional encryption context value is not supported.

    ", "location":"header", "locationName":"x-amz-server-side-encryption-context" }, @@ -11622,25 +11761,31 @@ }, "ChecksumCRC32":{ "shape":"ChecksumCRC32", - "documentation":"

    The base64-encoded, 32-bit CRC-32 checksum of the object. This will only be present if it was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    ", + "documentation":"

    The Base64 encoded, 32-bit CRC-32 checksum of the object. This checksum is only be present if the checksum was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    ", "location":"header", "locationName":"x-amz-checksum-crc32" }, "ChecksumCRC32C":{ "shape":"ChecksumCRC32C", - "documentation":"

    The base64-encoded, 32-bit CRC-32C checksum of the object. This will only be present if it was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    ", + "documentation":"

    The Base64 encoded, 32-bit CRC-32C checksum of the object. This checksum is only present if the checksum was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    ", "location":"header", "locationName":"x-amz-checksum-crc32c" }, + "ChecksumCRC64NVME":{ + "shape":"ChecksumCRC64NVME", + "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This header specifies the Base64 encoded, 64-bit CRC-64NVME checksum of the part. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", + "location":"header", + "locationName":"x-amz-checksum-crc64nvme" + }, "ChecksumSHA1":{ "shape":"ChecksumSHA1", - "documentation":"

    The base64-encoded, 160-bit SHA-1 digest of the object. This will only be present if it was uploaded with the object. When you use the API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    ", + "documentation":"

    The Base64 encoded, 160-bit SHA-1 digest of the object. This will only be present if the object was uploaded with the object. When you use the API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    ", "location":"header", "locationName":"x-amz-checksum-sha1" }, "ChecksumSHA256":{ "shape":"ChecksumSHA256", - "documentation":"

    The base64-encoded, 256-bit SHA-256 digest of the object. This will only be present if it was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    ", + "documentation":"

    The Base64 encoded, 256-bit SHA-256 digest of the object. This will only be present if the object was uploaded with the object. When you use an API operation on an object that was uploaded using multipart uploads, this value may not be a direct checksum value of the full object. Instead, it's a calculation based on the checksum values of each individual part. For more information about how checksums are calculated with multipart uploads, see Checking object integrity in the Amazon S3 User Guide.

    ", "location":"header", "locationName":"x-amz-checksum-sha256" }, @@ -11704,7 +11849,7 @@ }, "ContentMD5":{ "shape":"ContentMD5", - "documentation":"

    The base64-encoded 128-bit MD5 digest of the part data. This parameter is auto-populated when using the command from the CLI. This parameter is required if object lock parameters are specified.

    This functionality is not supported for directory buckets.

    ", + "documentation":"

    The Base64 encoded 128-bit MD5 digest of the part data. This parameter is auto-populated when using the command from the CLI. This parameter is required if object lock parameters are specified.

    This functionality is not supported for directory buckets.

    ", "location":"header", "locationName":"Content-MD5" }, @@ -11716,25 +11861,31 @@ }, "ChecksumCRC32":{ "shape":"ChecksumCRC32", - "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This header specifies the base64-encoded, 32-bit CRC-32 checksum of the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", + "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This header specifies the Base64 encoded, 32-bit CRC-32 checksum of the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", "location":"header", "locationName":"x-amz-checksum-crc32" }, "ChecksumCRC32C":{ "shape":"ChecksumCRC32C", - "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This header specifies the base64-encoded, 32-bit CRC-32C checksum of the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", + "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This header specifies the Base64 encoded, 32-bit CRC-32C checksum of the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", "location":"header", "locationName":"x-amz-checksum-crc32c" }, + "ChecksumCRC64NVME":{ + "shape":"ChecksumCRC64NVME", + "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This header specifies the Base64 encoded, 64-bit CRC-64NVME checksum of the part. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", + "location":"header", + "locationName":"x-amz-checksum-crc64nvme" + }, "ChecksumSHA1":{ "shape":"ChecksumSHA1", - "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This header specifies the base64-encoded, 160-bit SHA-1 digest of the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", + "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This header specifies the Base64 encoded, 160-bit SHA-1 digest of the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", "location":"header", "locationName":"x-amz-checksum-sha1" }, "ChecksumSHA256":{ "shape":"ChecksumSHA256", - "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This header specifies the base64-encoded, 256-bit SHA-256 digest of the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", + "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This header specifies the Base64 encoded, 256-bit SHA-256 digest of the object. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", "location":"header", "locationName":"x-amz-checksum-sha256" }, @@ -11933,25 +12084,31 @@ }, "ChecksumCRC32":{ "shape":"ChecksumCRC32", - "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This specifies the base64-encoded, 32-bit CRC-32 checksum of the object returned by the Object Lambda function. This may not match the checksum for the object stored in Amazon S3. Amazon S3 will perform validation of the checksum values only when the original GetObject request required checksum validation. For more information about checksums, see Checking object integrity in the Amazon S3 User Guide.

    Only one checksum header can be specified at a time. If you supply multiple checksum headers, this request will fail.

    ", + "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This specifies the Base64 encoded, 32-bit CRC-32 checksum of the object returned by the Object Lambda function. This may not match the checksum for the object stored in Amazon S3. Amazon S3 will perform validation of the checksum values only when the original GetObject request required checksum validation. For more information about checksums, see Checking object integrity in the Amazon S3 User Guide.

    Only one checksum header can be specified at a time. If you supply multiple checksum headers, this request will fail.

    ", "location":"header", "locationName":"x-amz-fwd-header-x-amz-checksum-crc32" }, "ChecksumCRC32C":{ "shape":"ChecksumCRC32C", - "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This specifies the base64-encoded, 32-bit CRC-32C checksum of the object returned by the Object Lambda function. This may not match the checksum for the object stored in Amazon S3. Amazon S3 will perform validation of the checksum values only when the original GetObject request required checksum validation. For more information about checksums, see Checking object integrity in the Amazon S3 User Guide.

    Only one checksum header can be specified at a time. If you supply multiple checksum headers, this request will fail.

    ", + "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This specifies the Base64 encoded, 32-bit CRC-32C checksum of the object returned by the Object Lambda function. This may not match the checksum for the object stored in Amazon S3. Amazon S3 will perform validation of the checksum values only when the original GetObject request required checksum validation. For more information about checksums, see Checking object integrity in the Amazon S3 User Guide.

    Only one checksum header can be specified at a time. If you supply multiple checksum headers, this request will fail.

    ", "location":"header", "locationName":"x-amz-fwd-header-x-amz-checksum-crc32c" }, + "ChecksumCRC64NVME":{ + "shape":"ChecksumCRC64NVME", + "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This header specifies the Base64 encoded, 64-bit CRC-64NVME checksum of the part. For more information, see Checking object integrity in the Amazon S3 User Guide.

    ", + "location":"header", + "locationName":"x-amz-fwd-header-x-amz-checksum-crc64nvme" + }, "ChecksumSHA1":{ "shape":"ChecksumSHA1", - "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This specifies the base64-encoded, 160-bit SHA-1 digest of the object returned by the Object Lambda function. This may not match the checksum for the object stored in Amazon S3. Amazon S3 will perform validation of the checksum values only when the original GetObject request required checksum validation. For more information about checksums, see Checking object integrity in the Amazon S3 User Guide.

    Only one checksum header can be specified at a time. If you supply multiple checksum headers, this request will fail.

    ", + "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This specifies the Base64 encoded, 160-bit SHA-1 digest of the object returned by the Object Lambda function. This may not match the checksum for the object stored in Amazon S3. Amazon S3 will perform validation of the checksum values only when the original GetObject request required checksum validation. For more information about checksums, see Checking object integrity in the Amazon S3 User Guide.

    Only one checksum header can be specified at a time. If you supply multiple checksum headers, this request will fail.

    ", "location":"header", "locationName":"x-amz-fwd-header-x-amz-checksum-sha1" }, "ChecksumSHA256":{ "shape":"ChecksumSHA256", - "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This specifies the base64-encoded, 256-bit SHA-256 digest of the object returned by the Object Lambda function. This may not match the checksum for the object stored in Amazon S3. Amazon S3 will perform validation of the checksum values only when the original GetObject request required checksum validation. For more information about checksums, see Checking object integrity in the Amazon S3 User Guide.

    Only one checksum header can be specified at a time. If you supply multiple checksum headers, this request will fail.

    ", + "documentation":"

    This header can be used as a data integrity check to verify that the data received is the same data that was originally sent. This specifies the Base64 encoded, 256-bit SHA-256 digest of the object returned by the Object Lambda function. This may not match the checksum for the object stored in Amazon S3. Amazon S3 will perform validation of the checksum values only when the original GetObject request required checksum validation. For more information about checksums, see Checking object integrity in the Amazon S3 User Guide.

    Only one checksum header can be specified at a time. If you supply multiple checksum headers, this request will fail.

    ", "location":"header", "locationName":"x-amz-fwd-header-x-amz-checksum-sha256" }, diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/S3SignerTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/S3SignerTest.java index 32178fd4ec76..ffcbf54f20b1 100644 --- a/services/s3/src/test/java/software/amazon/awssdk/services/s3/S3SignerTest.java +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/S3SignerTest.java @@ -39,7 +39,7 @@ import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; import software.amazon.awssdk.auth.signer.AwsS3V4Signer; -import software.amazon.awssdk.core.checksums.Algorithm; +import software.amazon.awssdk.checksums.DefaultChecksumAlgorithm; import software.amazon.awssdk.core.checksums.ChecksumSpecs; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption; @@ -53,11 +53,11 @@ @RunWith(MockitoJUnitRunner.class) public class S3SignerTest { - public static final ChecksumSpecs CRC32_TRAILER = ChecksumSpecs.builder().algorithm(Algorithm.CRC32) + public static final ChecksumSpecs CRC32_TRAILER = ChecksumSpecs.builder().algorithmV2(DefaultChecksumAlgorithm.CRC32) .isRequestStreaming(true) .headerName("x-amz-checksum-crc32").build(); - public static final ChecksumSpecs SHA256_HEADER = ChecksumSpecs.builder().algorithm(Algorithm.SHA256) + public static final ChecksumSpecs SHA256_HEADER = ChecksumSpecs.builder().algorithmV2(DefaultChecksumAlgorithm.SHA256) .isRequestStreaming(false) .headerName("x-amz-checksum-sha256").build(); diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/checksums/ChecksumCalculatingInputStreamTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/checksums/ChecksumCalculatingInputStreamTest.java deleted file mode 100644 index 27c292f29a2f..000000000000 --- a/services/s3/src/test/java/software/amazon/awssdk/services/s3/checksums/ChecksumCalculatingInputStreamTest.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -package software.amazon.awssdk.services.s3.checksums; - -import static org.mockito.Mockito.verify; - -import java.io.IOException; -import java.io.InputStream; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; -import software.amazon.awssdk.core.checksums.SdkChecksum; -import software.amazon.awssdk.services.s3.internal.checksums.ChecksumCalculatingInputStream; - -/** - * Tests for {@link ChecksumCalculatingInputStream}. - */ -@RunWith(MockitoJUnitRunner.class) -public class ChecksumCalculatingInputStreamTest { - @Mock - private InputStream mockStream; - - @Mock - private SdkChecksum mockChecksum; - - @Test - public void closeMethodClosesWrappedStream() throws IOException { - ChecksumCalculatingInputStream is = new ChecksumCalculatingInputStream(mockStream, mockChecksum); - is.close(); - verify(mockStream).close(); - } -} diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/checksums/ChecksumConfigurationTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/checksums/ChecksumConfigurationTest.java new file mode 100644 index 000000000000..0c27f3ad4bae --- /dev/null +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/checksums/ChecksumConfigurationTest.java @@ -0,0 +1,50 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.services.s3.checksums; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidation; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.S3ClientBuilder; +import software.amazon.awssdk.services.s3.S3Configuration; + +public class ChecksumConfigurationTest { + + @Test + public void s3Client_requestChecksumCalculationAndChecksumValidationEnabledBothSet_throwsError() { + S3ClientBuilder clientBuilder = S3Client.builder() + .requestChecksumCalculation(RequestChecksumCalculation.WHEN_REQUIRED) + .serviceConfiguration(S3Configuration.builder().checksumValidationEnabled(false).build()); + + Exception exception = assertThrows(IllegalStateException.class, clientBuilder::build); + assertThat(exception.getMessage()) + .contains("Checksum behavior has been configured on both S3Configuration and the client/global level"); + } + @Test + public void s3Client_responseChecksumValidationAndChecksumValidationEnabledBothSet_throwsError() { + S3ClientBuilder clientBuilder = S3Client.builder() + .responseChecksumValidation(ResponseChecksumValidation.WHEN_SUPPORTED) + .serviceConfiguration(S3Configuration.builder().checksumValidationEnabled(true).build()); + + Exception exception = assertThrows(IllegalStateException.class, clientBuilder::build); + assertThat(exception.getMessage()) + .contains("Checksum behavior has been configured on both S3Configuration and the client/global level"); + } +} diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/checksums/ChecksumsEnabledValidatorTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/checksums/ChecksumsEnabledValidatorTest.java index eebe16d636e0..619aa53a1aac 100644 --- a/services/s3/src/test/java/software/amazon/awssdk/services/s3/checksums/ChecksumsEnabledValidatorTest.java +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/checksums/ChecksumsEnabledValidatorTest.java @@ -17,7 +17,8 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static software.amazon.awssdk.core.interceptor.SdkExecutionAttribute.CLIENT_TYPE; -import static software.amazon.awssdk.core.interceptor.SdkExecutionAttribute.SERVICE_CONFIG; +import static software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute.REQUEST_CHECKSUM_CALCULATION; +import static software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute.RESPONSE_CHECKSUM_VALIDATION; import static software.amazon.awssdk.services.s3.internal.checksums.ChecksumConstant.CHECKSUM_ENABLED_RESPONSE_HEADER; import static software.amazon.awssdk.services.s3.internal.checksums.ChecksumConstant.CONTENT_LENGTH_HEADER; import static software.amazon.awssdk.services.s3.internal.checksums.ChecksumConstant.ENABLE_MD5_CHECKSUM_HEADER_VALUE; @@ -26,52 +27,41 @@ import static software.amazon.awssdk.services.s3.internal.checksums.ChecksumsEnabledValidator.getObjectChecksumEnabledPerRequest; import static software.amazon.awssdk.services.s3.internal.checksums.ChecksumsEnabledValidator.getObjectChecksumEnabledPerResponse; import static software.amazon.awssdk.services.s3.internal.checksums.ChecksumsEnabledValidator.responseChecksumIsValid; -import static software.amazon.awssdk.services.s3.internal.checksums.ChecksumsEnabledValidator.shouldRecordChecksum; import static software.amazon.awssdk.services.s3.model.ServerSideEncryption.AWS_KMS; import org.junit.jupiter.api.Test; import software.amazon.awssdk.core.ClientType; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidation; import software.amazon.awssdk.core.interceptor.ExecutionAttributes; -import software.amazon.awssdk.http.SdkHttpFullRequest; import software.amazon.awssdk.http.SdkHttpFullResponse; -import software.amazon.awssdk.http.SdkHttpMethod; -import software.amazon.awssdk.http.SdkHttpRequest; import software.amazon.awssdk.http.SdkHttpResponse; -import software.amazon.awssdk.services.s3.S3Configuration; import software.amazon.awssdk.services.s3.model.ChecksumMode; import software.amazon.awssdk.services.s3.model.GetObjectAclRequest; import software.amazon.awssdk.services.s3.model.GetObjectRequest; -import software.amazon.awssdk.services.s3.model.PutBucketAclRequest; -import software.amazon.awssdk.services.s3.model.PutObjectRequest; public class ChecksumsEnabledValidatorTest { @Test public void getObjectChecksumEnabledPerRequest_nonGetObjectRequest_returnsFalse() { assertThat(getObjectChecksumEnabledPerRequest(GetObjectAclRequest.builder().build(), - new ExecutionAttributes())).isFalse(); + getExecutionAttributesWithChecksumEnabled())).isFalse(); } @Test - public void getObjectChecksumEnabledPerRequest_checksumValidationEnabledChecksumModeDisabled_returnsTrue() { - assertThat(getObjectChecksumEnabledPerRequest(GetObjectRequest.builder().build(), - new ExecutionAttributes())).isTrue(); - } - - @Test - public void getObjectChecksumEnabledPerRequest_checksumValidationEnabledChecksumModeEnabled_returnsFalse() { + public void getObjectChecksumEnabledPerRequest_checksumEnabledChecksumModeEnabled_returnsFalse() { assertThat(getObjectChecksumEnabledPerRequest(GetObjectRequest.builder().checksumMode(ChecksumMode.ENABLED).build(), - new ExecutionAttributes())).isFalse(); + getExecutionAttributesWithChecksumEnabled())).isFalse(); } @Test - public void getObjectChecksumEnabledPerRequest_checksumValidationDisabledChecksumModeDisabled_returnsFalse() { + public void getObjectChecksumEnabledPerRequest_checksumDisabledChecksumModeDisabled_returnsFalse() { assertThat(getObjectChecksumEnabledPerRequest(GetObjectRequest.builder().build(), getExecutionAttributesWithChecksumDisabled())).isFalse(); } @Test - public void getObjectChecksumEnabledPerRequest_checksumValidationDisabledChecksumModeEnabled_returnsFalse() { + public void getObjectChecksumEnabledPerRequest_checksumDisabledChecksumModeEnabled_returnsFalse() { assertThat(getObjectChecksumEnabledPerRequest(GetObjectRequest.builder().checksumMode(ChecksumMode.ENABLED).build(), getExecutionAttributesWithChecksumDisabled())).isFalse(); } @@ -79,127 +69,22 @@ public void getObjectChecksumEnabledPerRequest_checksumValidationDisabledChecksu @Test public void getObjectChecksumEnabledPerResponse_nonGetObjectRequestFalse() { assertThat(getObjectChecksumEnabledPerResponse(GetObjectAclRequest.builder().build(), - getSdkHttpResponseWithChecksumHeader())).isFalse(); + getSdkHttpResponseWithChecksumHeader(), + getExecutionAttributesWithChecksumEnabled())).isFalse(); } @Test public void getObjectChecksumEnabledPerResponse_responseContainsChecksumHeader_returnTrue() { assertThat(getObjectChecksumEnabledPerResponse(GetObjectRequest.builder().build(), - getSdkHttpResponseWithChecksumHeader())).isTrue(); + getSdkHttpResponseWithChecksumHeader(), + getExecutionAttributesWithChecksumEnabled())).isTrue(); } @Test public void getObjectChecksumEnabledPerResponse_responseNotContainsChecksumHeader_returnFalse() { assertThat(getObjectChecksumEnabledPerResponse(GetObjectRequest.builder().build(), - SdkHttpFullResponse.builder().build())).isFalse(); - } - - @Test - public void putObjectChecksumEnabled_defaultShouldRecord() { - assertThat(shouldRecordChecksum(PutObjectRequest.builder().build(), - ClientType.SYNC, - getSyncExecutionAttributes(), - emptyHttpRequest().build())).isTrue(); - } - - @Test - public void putObjectChecksumEnabled_nonPutObjectRequest_false() { - assertThat(shouldRecordChecksum(PutBucketAclRequest.builder().build(), - ClientType.SYNC, - getSyncExecutionAttributes(), - emptyHttpRequest().build())).isFalse(); - } - - @Test - public void putObjectChecksumEnabled_disabledFromConfig_false() { - ExecutionAttributes executionAttributes = getExecutionAttributesWithChecksumDisabled(); - - assertThat(shouldRecordChecksum(PutObjectRequest.builder().build(), - ClientType.SYNC, - executionAttributes, - emptyHttpRequest().build())).isFalse(); - } - - @Test - public void putObjectChecksumEnabled_wrongClientType_false() { - ExecutionAttributes executionAttributes = getSyncExecutionAttributes(); - - assertThat(shouldRecordChecksum(PutObjectRequest.builder().build(), - ClientType.ASYNC, - executionAttributes, - emptyHttpRequest().build())).isFalse(); - } - - @Test - public void putObjectChecksumEnabled_serverSideCustomerEncryption_false() { - ExecutionAttributes executionAttributes = getSyncExecutionAttributes(); - SdkHttpRequest response = emptyHttpRequest().putHeader(SERVER_SIDE_CUSTOMER_ENCRYPTION_HEADER, "test") - .build(); - - assertThat(shouldRecordChecksum(PutObjectRequest.builder().build(), - ClientType.SYNC, - executionAttributes, - response)).isFalse(); - } - - @Test - public void putObjectChecksumEnabled_serverSideEncryption_false() { - ExecutionAttributes executionAttributes = getSyncExecutionAttributes(); - SdkHttpRequest response = emptyHttpRequest().putHeader(SERVER_SIDE_ENCRYPTION_HEADER, AWS_KMS.toString()) - .build(); - - assertThat(shouldRecordChecksum(PutObjectRequest.builder().build(), - ClientType.SYNC, - executionAttributes, - response)).isFalse(); - } - - @Test - public void putObject_crc32ValueSupplied_shouldNotValidateMd5() { - ExecutionAttributes executionAttributes = getSyncExecutionAttributes(); - - assertThat(shouldRecordChecksum(PutObjectRequest.builder() - .checksumCRC32("checksumVal") - .build(), - ClientType.SYNC, - executionAttributes, - emptyHttpRequest().build())).isFalse(); - } - - @Test - public void putObject_crc32cValueSupplied_shouldNotValidateMd5() { - ExecutionAttributes executionAttributes = getSyncExecutionAttributes(); - - assertThat(shouldRecordChecksum(PutObjectRequest.builder() - .checksumCRC32C("checksumVal") - .build(), - ClientType.SYNC, - executionAttributes, - emptyHttpRequest().build())).isFalse(); - } - - @Test - public void putObject_sha1ValueSupplied_shouldNotValidateMd5() { - ExecutionAttributes executionAttributes = getSyncExecutionAttributes(); - - assertThat(shouldRecordChecksum(PutObjectRequest.builder() - .checksumSHA1("checksumVal") - .build(), - ClientType.SYNC, - executionAttributes, - emptyHttpRequest().build())).isFalse(); - } - - @Test - public void putObject_sha256ValueSupplied_shouldNotValidateMd5() { - ExecutionAttributes executionAttributes = getSyncExecutionAttributes(); - - assertThat(shouldRecordChecksum(PutObjectRequest.builder() - .checksumSHA256("checksumVal") - .build(), - ClientType.SYNC, - executionAttributes, - emptyHttpRequest().build())).isFalse(); + SdkHttpFullResponse.builder().build(), + getExecutionAttributesWithChecksumEnabled())).isFalse(); } @Test @@ -225,15 +110,23 @@ public void responseChecksumIsValid_serverSideEncryption_false() { assertThat(responseChecksumIsValid(response)).isFalse(); } - private ExecutionAttributes getSyncExecutionAttributes() { + private ExecutionAttributes getExecutionAttributesWithChecksumEnabled() { ExecutionAttributes executionAttributes = new ExecutionAttributes(); + executionAttributes.putAttribute(REQUEST_CHECKSUM_CALCULATION, RequestChecksumCalculation.WHEN_SUPPORTED); + executionAttributes.putAttribute(RESPONSE_CHECKSUM_VALIDATION, ResponseChecksumValidation.WHEN_SUPPORTED); + return executionAttributes; + } + + private ExecutionAttributes getSyncExecutionAttributes() { + ExecutionAttributes executionAttributes = getExecutionAttributesWithChecksumEnabled(); executionAttributes.putAttribute(CLIENT_TYPE, ClientType.SYNC); return executionAttributes; } private ExecutionAttributes getExecutionAttributesWithChecksumDisabled() { ExecutionAttributes executionAttributes = getSyncExecutionAttributes(); - executionAttributes.putAttribute(SERVICE_CONFIG, S3Configuration.builder().checksumValidationEnabled(false).build()); + executionAttributes.putAttribute(REQUEST_CHECKSUM_CALCULATION, RequestChecksumCalculation.WHEN_REQUIRED); + executionAttributes.putAttribute(RESPONSE_CHECKSUM_VALIDATION, ResponseChecksumValidation.WHEN_REQUIRED); return executionAttributes; } @@ -243,13 +136,4 @@ private SdkHttpResponse getSdkHttpResponseWithChecksumHeader() { .putHeader(CHECKSUM_ENABLED_RESPONSE_HEADER, ENABLE_MD5_CHECKSUM_HEADER_VALUE) .build(); } - - private SdkHttpRequest.Builder emptyHttpRequest() { - return SdkHttpFullRequest.builder() - .method(SdkHttpMethod.GET) - .protocol("https") - .host("localhost") - .port(80); - } - } diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/functionaltests/ContentLengthMismatchTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/functionaltests/ContentLengthMismatchTest.java index 89870fab2758..6bde6763c7bb 100644 --- a/services/s3/src/test/java/software/amazon/awssdk/services/s3/functionaltests/ContentLengthMismatchTest.java +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/functionaltests/ContentLengthMismatchTest.java @@ -18,47 +18,71 @@ import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; import static com.github.tomakehurst.wiremock.client.WireMock.any; import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl; -import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; import static com.github.tomakehurst.wiremock.client.WireMock.putRequestedFor; import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; import static com.github.tomakehurst.wiremock.client.WireMock.verify; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import com.github.tomakehurst.wiremock.junit.WireMockRule; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo; +import com.github.tomakehurst.wiremock.junit5.WireMockTest; +import com.github.tomakehurst.wiremock.matching.MatchResult; +import com.github.tomakehurst.wiremock.matching.StringValuePattern; import java.net.URI; import java.nio.ByteBuffer; import java.util.Optional; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; -import org.junit.Rule; -import org.junit.Test; +import java.util.stream.Stream; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; import org.reactivestreams.Subscriber; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; import software.amazon.awssdk.core.async.AsyncRequestBody; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.s3.S3AsyncClient; import software.amazon.awssdk.services.s3.S3AsyncClientBuilder; import software.amazon.awssdk.services.s3.model.PutObjectResponse; +@WireMockTest public class ContentLengthMismatchTest { - @Rule - public WireMockRule wireMock = new WireMockRule(0); - - private S3AsyncClientBuilder getAsyncClientBuilder() { - return S3AsyncClient.builder() - .region(Region.US_EAST_1) - .endpointOverride(endpoint()) - .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create("key", "secret"))); + + private S3AsyncClientBuilder s3AsyncClientBuilder; + + private S3AsyncClient s3AsyncClient(RequestChecksumCalculation requestChecksumCalculation) { + return requestChecksumCalculation == null + ? s3AsyncClientBuilder.build() + : s3AsyncClientBuilder.requestChecksumCalculation(requestChecksumCalculation).build(); + } + + @BeforeEach + void init(WireMockRuntimeInfo wm) { + s3AsyncClientBuilder = S3AsyncClient.builder() + .region(Region.US_EAST_1) + .endpointOverride(endpoint(wm)) + .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create( + "key", "secret"))); } - private URI endpoint() { - return URI.create("http://localhost:" + wireMock.port()); + static Stream requestChecksumCalculations() { + return Stream.of( + null, + RequestChecksumCalculation.WHEN_REQUIRED, + RequestChecksumCalculation.WHEN_SUPPORTED + ); } - @Test - public void checksumDoesNotExceedContentLengthHeaderForPuts() { + private URI endpoint(WireMockRuntimeInfo wiremock) { + return URI.create("http://localhost:" + wiremock.getHttpPort()); + } + + @ParameterizedTest(name = "RequestChecksumCalculation: {arguments}") + @MethodSource("requestChecksumCalculations") + public void checksumDoesNotExceedContentLengthHeaderForPuts(RequestChecksumCalculation requestChecksumCalculation) { String bucket = "Example-Bucket"; String key = "Example-Object"; String content = "Hello, World!"; @@ -66,18 +90,20 @@ public void checksumDoesNotExceedContentLengthHeaderForPuts() { stubFor(any(anyUrl()).willReturn(aResponse().withStatus(200).withHeader("ETag", eTag))); - S3AsyncClient s3Client = getAsyncClientBuilder().build(); + S3AsyncClient s3Client = s3AsyncClient(requestChecksumCalculation); PutObjectResponse response = s3Client.putObject(r -> r.bucket(bucket).key(key).contentLength((long) content.length()), AsyncRequestBody.fromString(content + " Extra stuff!")) .join(); - verify(putRequestedFor(anyUrl()).withRequestBody(equalTo(content))); + verify(putRequestedFor(anyUrl()).withRequestBody(notContaining("stuff!"))); assertThat(response.eTag()).isEqualTo(eTag); } - @Test - public void checksumDoesNotExceedAsyncRequestBodyLengthForPuts() { + + @ParameterizedTest(name = "RequestChecksumCalculation: {arguments}") + @MethodSource("requestChecksumCalculations") + public void checksumDoesNotExceedAsyncRequestBodyLengthForPuts(RequestChecksumCalculation requestChecksumCalculation) { String bucket = "Example-Bucket"; String key = "Example-Object"; String content = "Hello, World!"; @@ -85,7 +111,7 @@ public void checksumDoesNotExceedAsyncRequestBodyLengthForPuts() { stubFor(any(anyUrl()).willReturn(aResponse().withStatus(200).withHeader("ETag", eTag))); - S3AsyncClient s3Client = getAsyncClientBuilder().build(); + S3AsyncClient s3Client = s3AsyncClient(requestChecksumCalculation); PutObjectResponse response = s3Client.putObject(r -> r.bucket(bucket).key(key), @@ -102,16 +128,19 @@ public void subscribe(Subscriber subscriber) { }) .join(); - verify(putRequestedFor(anyUrl()).withRequestBody(equalTo(content))); + verify(putRequestedFor(anyUrl()).withRequestBody(notContaining("stuff!"))); assertThat(response.eTag()).isEqualTo(eTag); } - @Test - public void contentShorterThanContentLengthHeaderFails() { + @ParameterizedTest(name = "RequestChecksumCalculation: {arguments}") + @MethodSource("requestChecksumCalculations") + public void contentShorterThanContentLengthHeaderFails(RequestChecksumCalculation requestChecksumCalculation) { String bucket = "Example-Bucket"; String key = "Example-Object"; + String eTag = "65A8E27D8879283831B664BD8B7F0AD4"; - S3AsyncClient s3Client = getAsyncClientBuilder().build(); + S3AsyncClient s3Client = s3AsyncClient(requestChecksumCalculation); + stubFor(any(anyUrl()).willReturn(aResponse().withStatus(200).withHeader("ETag", eTag))); AsyncRequestBody requestBody = new AsyncRequestBody() { @Override @@ -131,12 +160,15 @@ public void subscribe(Subscriber subscriber) { .hasMessageContaining("content-length"); } - @Test - public void contentShorterThanRequestBodyLengthFails() { + @ParameterizedTest(name = "RequestChecksumCalculation: {arguments}") + @MethodSource("requestChecksumCalculations") + public void contentShorterThanRequestBodyLengthFails(RequestChecksumCalculation requestChecksumCalculation) { String bucket = "Example-Bucket"; String key = "Example-Object"; + String eTag = "65A8E27D8879283831B664BD8B7F0AD4"; - S3AsyncClient s3Client = getAsyncClientBuilder().build(); + stubFor(any(anyUrl()).willReturn(aResponse().withStatus(200).withHeader("ETag", eTag))); + S3AsyncClient s3Client = s3AsyncClient(requestChecksumCalculation); AsyncRequestBody requestBody = new AsyncRequestBody() { @Override @@ -156,4 +188,18 @@ public void subscribe(Subscriber subscriber) { .hasMessageContaining("content-length"); } + static StringValuePattern notContaining(String expected) { + return new NotContainsPattern(expected); + } + + private static final class NotContainsPattern extends StringValuePattern { + private NotContainsPattern(@JsonProperty("expectedValue") String expectedValue) { + super(expectedValue); + } + @Override + public MatchResult match(String value) { + return MatchResult.of(value != null && !value.contains(expectedValue)); + } + } + } diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/functionaltests/GetObjectWithChecksumTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/functionaltests/GetObjectWithChecksumTest.java index bf930d971047..aaba32cfd5e4 100644 --- a/services/s3/src/test/java/software/amazon/awssdk/services/s3/functionaltests/GetObjectWithChecksumTest.java +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/functionaltests/GetObjectWithChecksumTest.java @@ -34,6 +34,7 @@ import org.junit.jupiter.api.Test; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.checksums.DefaultChecksumAlgorithm; import software.amazon.awssdk.core.ResponseInputStream; import software.amazon.awssdk.core.async.AsyncResponseTransformer; import software.amazon.awssdk.core.checksums.Algorithm; @@ -94,7 +95,7 @@ public void async_getObject_with_correct_http_checksum(WireMockRuntimeInfo wm) { assertThat(response).isEqualTo("Hello world"); assertThat(captureChecksumValidationInterceptor.responseValidation()).isEqualTo(ChecksumValidation.VALIDATED); - assertThat(captureChecksumValidationInterceptor.validationAlgorithm()).isEqualTo(Algorithm.CRC32); + assertThat(captureChecksumValidationInterceptor.validationAlgorithm()).isEqualTo(DefaultChecksumAlgorithm.CRC32); } @@ -160,7 +161,7 @@ public void sync_getObject_with_correct_http_checksum(WireMockRuntimeInfo wm) { assertThat(stringFromStream.apply(getObject)).isEqualTo("Hello world"); assertThat(captureChecksumValidationInterceptor.responseValidation()).isEqualTo(ChecksumValidation.VALIDATED); - assertThat(captureChecksumValidationInterceptor.validationAlgorithm()).isEqualTo(Algorithm.CRC32); + assertThat(captureChecksumValidationInterceptor.validationAlgorithm()).isEqualTo(DefaultChecksumAlgorithm.CRC32); } diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/functionaltests/PutObjectWithChecksumTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/functionaltests/PutObjectWithChecksumTest.java deleted file mode 100644 index d2350f3ecf36..000000000000 --- a/services/s3/src/test/java/software/amazon/awssdk/services/s3/functionaltests/PutObjectWithChecksumTest.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -package software.amazon.awssdk.services.s3.functionaltests; - -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.github.tomakehurst.wiremock.client.WireMock.any; -import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl; -import static com.github.tomakehurst.wiremock.client.WireMock.containing; -import static com.github.tomakehurst.wiremock.client.WireMock.putRequestedFor; -import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; -import static com.github.tomakehurst.wiremock.client.WireMock.verify; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; - -import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo; -import com.github.tomakehurst.wiremock.junit5.WireMockTest; -import java.io.BufferedReader; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.util.function.Function; -import java.util.stream.Collectors; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Test; -import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; -import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; -import software.amazon.awssdk.core.async.AsyncRequestBody; -import software.amazon.awssdk.core.exception.RetryableException; -import software.amazon.awssdk.core.sync.RequestBody; -import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.s3.S3AsyncClient; -import software.amazon.awssdk.services.s3.S3AsyncClientBuilder; -import software.amazon.awssdk.services.s3.S3Client; -import software.amazon.awssdk.services.s3.S3ClientBuilder; -import software.amazon.awssdk.services.s3.model.ChecksumAlgorithm; -import software.amazon.awssdk.services.s3.model.PutObjectRequest; -import software.amazon.awssdk.services.s3.model.PutObjectResponse; -import software.amazon.awssdk.services.s3.utils.CaptureChecksumValidationInterceptor; - -@WireMockTest -public class PutObjectWithChecksumTest { - - String CONTENT = "Hello, World!"; - String INCORRECT_ETAG = "65A8E27D8879283831B664BD8B7F0AD5"; - String ETAG = "65A8E27D8879283831B664BD8B7F0AD4"; - public static final Function stringFromStream = inputStream -> - new BufferedReader( - new InputStreamReader(inputStream, StandardCharsets.UTF_8)).lines().collect(Collectors.joining("\n")); - private static final String BUCKET = "Example-Bucket"; - private static final String EXAMPLE_RESPONSE_BODY = "Hello world"; - private final CaptureChecksumValidationInterceptor captureChecksumValidationInterceptor = - new CaptureChecksumValidationInterceptor(); - - private S3ClientBuilder getSyncClientBuilder(WireMockRuntimeInfo wm) { - return S3Client.builder() - .region(Region.US_EAST_1) - .endpointOverride(URI.create(wm.getHttpBaseUrl())) - .credentialsProvider( - StaticCredentialsProvider.create(AwsBasicCredentials.create("key", "secret"))); - } - - @AfterEach - public void reset() { - captureChecksumValidationInterceptor.reset(); - } - - private S3AsyncClientBuilder getAsyncClientBuilder(WireMockRuntimeInfo wm) { - return S3AsyncClient.builder() - .region(Region.US_EAST_1) - .endpointOverride(URI.create(wm.getHttpBaseUrl())) - .credentialsProvider( - StaticCredentialsProvider.create(AwsBasicCredentials.create("key", "secret"))); - } - - // Exception is thrown means the default Md5 validation has taken place. - @Test - void sync_putObject_default_MD5_validation_withIncorrectChecksum(WireMockRuntimeInfo wm) { - stubFor(any(anyUrl()).willReturn(aResponse().withStatus(200) - .withHeader("x-amz-checksum-crc32", "i9aeUg==") - .withHeader("etag", INCORRECT_ETAG))); - S3Client s3Client = - getSyncClientBuilder(wm).overrideConfiguration(o -> o.addExecutionInterceptor(captureChecksumValidationInterceptor)).build(); - - PutObjectRequest putObjectRequest = PutObjectRequest.builder().bucket(BUCKET).key("KEY").build(); - RequestBody requestBody = RequestBody.fromBytes(CONTENT.getBytes()); - - assertThatExceptionOfType(RetryableException.class) - .isThrownBy(() -> s3Client.putObject(putObjectRequest, requestBody)) - .withMessage("Data read has a different checksum than expected. Was 0x" + ETAG.toLowerCase() + ", but expected 0x" - + INCORRECT_ETAG.toLowerCase() + ". This commonly means that the data was corrupted between the client " - + "and service. Note: Despite this error, the upload still completed and was persisted in S3."); - assertThat(captureChecksumValidationInterceptor.validationAlgorithm()).isNull(); - } - - @Test - void sync_putObject_default_MD5_validation_withCorrectChecksum(WireMockRuntimeInfo wm) { - stubFor(any(anyUrl()).willReturn(aResponse().withStatus(200) - .withHeader("x-amz-checksum-crc32", "WRONG_CHECKSUM") - .withHeader("etag", ETAG))); - S3Client s3Client = - getSyncClientBuilder(wm).overrideConfiguration(o -> o.addExecutionInterceptor(captureChecksumValidationInterceptor)) - .build(); - PutObjectResponse putObjectResponse = s3Client.putObject(b -> b.bucket(BUCKET) - .key("KEY"), - RequestBody.fromBytes(CONTENT.getBytes())); - assertThat(putObjectResponse.eTag()).isEqualTo(ETAG); - assertThat(captureChecksumValidationInterceptor.validationAlgorithm()).isNull(); - - } - - // Exception is thrown means the default Md5 validation has taken place. - @Test - void async_putObject_default_MD5_validation_withIncorrectChecksum(WireMockRuntimeInfo wm) { - stubFor(any(anyUrl()).willReturn(aResponse().withStatus(200) - .withHeader("x-amz-checksum-crc32", "i9aeUg==") - .withHeader("etag", INCORRECT_ETAG))); - S3Client s3Client = - getSyncClientBuilder(wm).overrideConfiguration(o -> o.addExecutionInterceptor(captureChecksumValidationInterceptor)).build(); - - PutObjectRequest putObjectRequest = PutObjectRequest.builder().bucket(BUCKET).key("KEY").build(); - RequestBody requestBody = RequestBody.fromBytes(CONTENT.getBytes()); - - assertThatExceptionOfType(RetryableException.class) - .isThrownBy(() -> s3Client.putObject(putObjectRequest, requestBody)) - .withMessage("Data read has a different checksum than expected. Was 0x" + ETAG.toLowerCase() + ", but expected 0x" - + INCORRECT_ETAG.toLowerCase() + ". This commonly means that the data was corrupted between the client " - + "and service. Note: Despite this error, the upload still completed and was persisted in S3."); - assertThat(captureChecksumValidationInterceptor.validationAlgorithm()).isNull(); - - } - - @Test - void async_putObject_default_MD5_validation_withCorrectChecksum(WireMockRuntimeInfo wm) { - stubFor(any(anyUrl()).willReturn(aResponse().withStatus(200) - .withHeader("x-amz-checksum-crc32", "WRONG_CHECKSUM") - .withHeader("etag", ETAG))); - S3AsyncClient s3Async = - getAsyncClientBuilder(wm).overrideConfiguration(o -> o.addExecutionInterceptor(captureChecksumValidationInterceptor)).build(); - PutObjectResponse putObjectResponse = s3Async.putObject(PutObjectRequest.builder() - .bucket(BUCKET) - .key("KEY") - .build(), AsyncRequestBody.fromString(CONTENT)).join(); - - assertThat(putObjectResponse.eTag()).isEqualTo(ETAG); - assertThat(captureChecksumValidationInterceptor.requestChecksumInTrailer()).isNull(); - } - - // Even with incorrect Etag, exception is not thrown because default check is skipped when checksumAlgorithm is set - @Test - void sync_putObject_httpChecksumValidation_withIncorrectChecksum(WireMockRuntimeInfo wm) { - stubFor(any(anyUrl()).willReturn(aResponse().withStatus(200) - .withHeader("x-amz-checksum-crc32", "7ErD0A==") - .withHeader("etag", INCORRECT_ETAG))); - S3Client s3Client = - getSyncClientBuilder(wm).overrideConfiguration(o -> o.addExecutionInterceptor(captureChecksumValidationInterceptor)).build(); - - s3Client.putObject(b -> b.bucket(BUCKET).key("KEY").checksumAlgorithm(ChecksumAlgorithm.CRC32), - RequestBody.fromBytes(CONTENT.getBytes())); - assertThat(captureChecksumValidationInterceptor.validationAlgorithm()).isNull(); - assertThat(captureChecksumValidationInterceptor.requestChecksumInTrailer()).isEqualTo("x-amz-checksum-crc32"); - - verify(putRequestedFor(anyUrl()).withRequestBody(containing("Hello, World!")) - .withRequestBody(containing("x-amz-checksum-crc32:7ErD0A==")) - .withRequestBody(containing("0;"))); - } - - // Even with incorrect Etag, exception is not thrown because default check is skipped when checksumAlgorithm is set - @Test - void async_putObject_httpChecksumValidation_withIncorrectChecksum(WireMockRuntimeInfo wm) { - stubFor(any(anyUrl()).willReturn(aResponse().withStatus(200) - .withHeader("x-amz-checksum-crc32", "7ErD0A==") - .withHeader("etag", INCORRECT_ETAG))); - S3AsyncClient s3Async = - getAsyncClientBuilder(wm).overrideConfiguration(o -> o.addExecutionInterceptor(captureChecksumValidationInterceptor)).build(); - - s3Async.putObject(PutObjectRequest.builder().bucket(BUCKET).checksumAlgorithm(ChecksumAlgorithm.CRC32).key("KEY").build(), - AsyncRequestBody.fromString(CONTENT)).join(); - - assertThat(captureChecksumValidationInterceptor.validationAlgorithm()).isNull(); - assertThat(captureChecksumValidationInterceptor.requestChecksumInTrailer()).isEqualTo("x-amz-checksum-crc32"); - - verify(putRequestedFor(anyUrl()).withRequestBody(containing("x-amz-checksum-crc32:7ErD0A==")) - .withRequestBody(containing("Hello, World!"))); - } -} diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/functionaltests/S3ExpressTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/functionaltests/S3ExpressTest.java index 15d915ba11aa..3963751631f9 100644 --- a/services/s3/src/test/java/software/amazon/awssdk/services/s3/functionaltests/S3ExpressTest.java +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/functionaltests/S3ExpressTest.java @@ -126,7 +126,7 @@ public void uploadPart(ClientType clientType, Protocol protocol, createClientAndCallUploadPart(clientType, protocol, s3ExpressSessionAuth, checksumAlgorithm, wm); verifyUploadPart(s3ExpressSessionAuth); - verifyUploadPartHeaders(clientType, protocol, checksumAlgorithm); + verifyUploadPartHeaders(clientType, protocol); } @ParameterizedTest @@ -290,23 +290,17 @@ void verifyPutObjectHeaders(ClientType clientType, Protocol protocol, ChecksumAl assertThat(headers.get("x-amz-content-sha256").get(0)).isEqualToIgnoringCase(streamingSha256); } - void verifyUploadPartHeaders(ClientType clientType, Protocol protocol, ChecksumAlgorithm checksumAlgorithm) { + void verifyUploadPartHeaders(ClientType clientType, Protocol protocol) { Map> headers = CAPTURING_INTERCEPTOR.headers; assertThat(headers.get("Content-Length")).isNotNull(); assertThat(headers.get("x-amz-content-sha256")).isNotNull(); - if ((protocol == Protocol.HTTPS || clientType == ClientType.ASYNC) && - checksumAlgorithm == ChecksumAlgorithm.UNKNOWN_TO_SDK_VERSION) { - assertThat(headers.get("x-amz-content-sha256").get(0)).isEqualToIgnoringCase("UNSIGNED-PAYLOAD"); - } else { - assertThat(headers.get("x-amz-decoded-content-length")).isNotNull(); - String streamingSha256 = "STREAMING-UNSIGNED-PAYLOAD-TRAILER"; - if (protocol == Protocol.HTTP && clientType == ClientType.SYNC) { - streamingSha256 = checksumAlgorithm == ChecksumAlgorithm.UNKNOWN_TO_SDK_VERSION ? - "STREAMING-AWS4-HMAC-SHA256-PAYLOAD" : "STREAMING-AWS4-HMAC-SHA256-PAYLOAD-TRAILER"; - } - assertThat(headers.get("x-amz-content-sha256").get(0)).isEqualToIgnoringCase(streamingSha256); + assertThat(headers.get("x-amz-decoded-content-length")).isNotNull(); + String streamingSha256 = "STREAMING-UNSIGNED-PAYLOAD-TRAILER"; + if (protocol == Protocol.HTTP && clientType == ClientType.SYNC) { + streamingSha256 = "STREAMING-AWS4-HMAC-SHA256-PAYLOAD-TRAILER"; } + assertThat(headers.get("x-amz-content-sha256").get(0)).isEqualToIgnoringCase(streamingSha256); } void verifyGetObjectHeaders() { diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/crt/CrtChecksumUtilsTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/crt/CrtChecksumUtilsTest.java index b5273591afbf..ebd1bd37d9fa 100644 --- a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/crt/CrtChecksumUtilsTest.java +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/crt/CrtChecksumUtilsTest.java @@ -23,6 +23,8 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidation; import software.amazon.awssdk.core.interceptor.trait.HttpChecksum; import software.amazon.awssdk.crt.s3.ChecksumAlgorithm; import software.amazon.awssdk.crt.s3.ChecksumConfig; @@ -35,53 +37,89 @@ private static Stream crtChecksumInput() { checksumAlgorithms.add(ChecksumAlgorithm.SHA256); checksumAlgorithms.add(ChecksumAlgorithm.SHA1); return Stream.of( - // DEFAULT request, should pass empty config - Arguments.of(HttpChecksum.builder().build(), S3MetaRequestOptions.MetaRequestType.DEFAULT, true, - new ChecksumConfig()), + // DEFAULT request, should set default algorithm CRC32 in header + Arguments.of(HttpChecksum.builder().build(), S3MetaRequestOptions.MetaRequestType.DEFAULT, + RequestChecksumCalculation.WHEN_SUPPORTED, ResponseChecksumValidation.WHEN_SUPPORTED, + new ChecksumConfig().withChecksumAlgorithm(ChecksumAlgorithm.CRC32) + .withChecksumLocation(ChecksumConfig.ChecksumLocation.HEADER)), - // PUT request with request algorithm, should set algorithm + // PUT request with SHA256 request algorithm, should set algorithm in trailer Arguments.of(HttpChecksum.builder() .requestAlgorithm("sha256") + .isRequestStreaming(true) + .build(), + S3MetaRequestOptions.MetaRequestType.PUT_OBJECT, + RequestChecksumCalculation.WHEN_SUPPORTED, ResponseChecksumValidation.WHEN_SUPPORTED, + new ChecksumConfig().withChecksumAlgorithm(ChecksumAlgorithm.SHA256) + .withChecksumLocation(ChecksumConfig.ChecksumLocation.TRAILER)), + // PUT request with CRC64NVME request algorithm, should set algorithm in trailer + Arguments.of(HttpChecksum.builder() + .requestAlgorithm("crc64nvme") + .isRequestStreaming(true) .build(), S3MetaRequestOptions.MetaRequestType.PUT_OBJECT, - true, - new ChecksumConfig().withChecksumAlgorithm(ChecksumAlgorithm.SHA256).withChecksumLocation(ChecksumConfig.ChecksumLocation.TRAILER)), + RequestChecksumCalculation.WHEN_SUPPORTED, ResponseChecksumValidation.WHEN_SUPPORTED, + new ChecksumConfig().withChecksumAlgorithm(ChecksumAlgorithm.CRC64NVME) + .withChecksumLocation(ChecksumConfig.ChecksumLocation.TRAILER)), - // PUT request w/o request algorithm, should set default algorithm - Arguments.of(HttpChecksum.builder().build(), S3MetaRequestOptions.MetaRequestType.PUT_OBJECT, true, - new ChecksumConfig().withChecksumAlgorithm(ChecksumAlgorithm.CRC32).withChecksumLocation(ChecksumConfig.ChecksumLocation.TRAILER)), + // PUT request w/o request algorithm, should set default algorithm CRC32 in trailer + Arguments.of(HttpChecksum.builder().isRequestStreaming(true).build(), + S3MetaRequestOptions.MetaRequestType.PUT_OBJECT, + RequestChecksumCalculation.WHEN_SUPPORTED, ResponseChecksumValidation.WHEN_SUPPORTED, + new ChecksumConfig().withChecksumAlgorithm(ChecksumAlgorithm.CRC32) + .withChecksumLocation(ChecksumConfig.ChecksumLocation.TRAILER)), // PUT request w/o request algorithm and checksum disabled, should pass empty config - Arguments.of(HttpChecksum.builder().build(), S3MetaRequestOptions.MetaRequestType.PUT_OBJECT, false, + Arguments.of(HttpChecksum.builder().build(), + S3MetaRequestOptions.MetaRequestType.PUT_OBJECT, + RequestChecksumCalculation.WHEN_REQUIRED, ResponseChecksumValidation.WHEN_REQUIRED, new ChecksumConfig()), // No HttpChecksum, should pass empty config - Arguments.of(null, S3MetaRequestOptions.MetaRequestType.PUT_OBJECT, true, + Arguments.of(null, + S3MetaRequestOptions.MetaRequestType.PUT_OBJECT, + RequestChecksumCalculation.WHEN_SUPPORTED, ResponseChecksumValidation.WHEN_SUPPORTED, new ChecksumConfig()), - // GET request w/o validate response algorithm, should set validate to true by default + // GET request w/o validate response algorithm, should set validate to true by default and set default algorithm CRC32 in header Arguments.of(HttpChecksum.builder().build(), - S3MetaRequestOptions.MetaRequestType.GET_OBJECT, true, - new ChecksumConfig().withValidateChecksum(true)), + S3MetaRequestOptions.MetaRequestType.GET_OBJECT, + RequestChecksumCalculation.WHEN_SUPPORTED, ResponseChecksumValidation.WHEN_SUPPORTED, + new ChecksumConfig().withChecksumAlgorithm(ChecksumAlgorithm.CRC32) + .withChecksumLocation(ChecksumConfig.ChecksumLocation.HEADER) + .withValidateChecksum(true)), - // GET request w/o validate response algorithm, should set validate to true by defaultt - Arguments.of(HttpChecksum.builder().responseAlgorithms("sha256", "sha1").build(), - S3MetaRequestOptions.MetaRequestType.GET_OBJECT, true, - new ChecksumConfig().withValidateChecksum(true).withValidateChecksumAlgorithmList(checksumAlgorithms)), - - // GET request with validate response algorithm, should set ChecksumConfig - Arguments.of(HttpChecksum.builder().requestValidationMode("true").build(), - S3MetaRequestOptions.MetaRequestType.GET_OBJECT, true, - new ChecksumConfig().withValidateChecksum(true)), + // GET request w/o validate response algorithm, should set validate to true by default and set default algorithm CRC32 in header + Arguments.of(HttpChecksum.builder() + .responseAlgorithms("sha256", "sha1") + .build(), + S3MetaRequestOptions.MetaRequestType.GET_OBJECT, + RequestChecksumCalculation.WHEN_SUPPORTED, ResponseChecksumValidation.WHEN_SUPPORTED, + new ChecksumConfig().withChecksumAlgorithm(ChecksumAlgorithm.CRC32) + .withChecksumLocation(ChecksumConfig.ChecksumLocation.HEADER) + .withValidateChecksum(true) + .withValidateChecksumAlgorithmList(checksumAlgorithms)), + + // GET request with validate response algorithm, should set default algorithm CRC32 in header + Arguments.of(HttpChecksum.builder() + .requestValidationMode("true") + .build(), + S3MetaRequestOptions.MetaRequestType.GET_OBJECT, + RequestChecksumCalculation.WHEN_SUPPORTED, ResponseChecksumValidation.WHEN_SUPPORTED, + new ChecksumConfig().withChecksumAlgorithm(ChecksumAlgorithm.CRC32) + .withChecksumLocation(ChecksumConfig.ChecksumLocation.HEADER) + .withValidateChecksum(true)), // GET request w/o requestValidationMode and checksum disabled, should pass empty config Arguments.of(HttpChecksum.builder().build(), - S3MetaRequestOptions.MetaRequestType.GET_OBJECT, false, + S3MetaRequestOptions.MetaRequestType.GET_OBJECT, + RequestChecksumCalculation.WHEN_REQUIRED, ResponseChecksumValidation.WHEN_REQUIRED, new ChecksumConfig().withValidateChecksum(false)), // GET request, No HttpChecksum, should pass empty config Arguments.of(null, - S3MetaRequestOptions.MetaRequestType.GET_OBJECT, true, + S3MetaRequestOptions.MetaRequestType.GET_OBJECT, + RequestChecksumCalculation.WHEN_SUPPORTED, ResponseChecksumValidation.WHEN_SUPPORTED, new ChecksumConfig()) ); @@ -91,8 +129,10 @@ private static Stream crtChecksumInput() { @MethodSource("crtChecksumInput") void crtChecksumAlgorithm_differentInput(HttpChecksum checksum, S3MetaRequestOptions.MetaRequestType type, - boolean checksumValidationEnabled, + RequestChecksumCalculation requestChecksumCalculation, + ResponseChecksumValidation responseChecksumValidation, ChecksumConfig expected) { - assertThat(CrtChecksumUtils.checksumConfig(checksum, type, checksumValidationEnabled)).usingRecursiveComparison().isEqualTo(expected); + assertThat(CrtChecksumUtils.checksumConfig(checksum, type, requestChecksumCalculation, responseChecksumValidation)) + .usingRecursiveComparison().isEqualTo(expected); } } diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/crt/S3CrtAsyncHttpClientTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/crt/S3CrtAsyncHttpClientTest.java index 31f12507eb14..f7c107add488 100644 --- a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/crt/S3CrtAsyncHttpClientTest.java +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/crt/S3CrtAsyncHttpClientTest.java @@ -22,6 +22,8 @@ import static software.amazon.awssdk.http.Header.CONTENT_LENGTH; import static software.amazon.awssdk.services.s3.internal.crt.S3InternalSdkHttpExecutionAttribute.HTTP_CHECKSUM; import static software.amazon.awssdk.services.s3.internal.crt.S3InternalSdkHttpExecutionAttribute.OPERATION_NAME; +import static software.amazon.awssdk.services.s3.internal.crt.S3InternalSdkHttpExecutionAttribute.REQUEST_CHECKSUM_CALCULATION; +import static software.amazon.awssdk.services.s3.internal.crt.S3InternalSdkHttpExecutionAttribute.RESPONSE_CHECKSUM_VALIDATION; import static software.amazon.awssdk.services.s3.internal.crt.S3InternalSdkHttpExecutionAttribute.SIGNING_NAME; import static software.amazon.awssdk.services.s3.internal.crt.S3InternalSdkHttpExecutionAttribute.SIGNING_REGION; import static software.amazon.awssdk.services.s3.internal.crt.S3InternalSdkHttpExecutionAttribute.USE_S3_EXPRESS_AUTH; @@ -41,6 +43,8 @@ import org.mockito.Mockito; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidation; import software.amazon.awssdk.core.interceptor.trait.HttpChecksum; import software.amazon.awssdk.crt.auth.signing.AwsSigningConfig; import software.amazon.awssdk.crt.http.HttpProxyEnvironmentVariableSetting; @@ -81,7 +85,6 @@ public void methodSetup() { .endpointOverride(DEFAULT_ENDPOINT) .credentialsProvider( StaticCredentialsProvider.create(AwsBasicCredentials.create("FOO", "BARR"))) - .checksumValidationEnabled(true) .signingRegion("us-west-2") .build(); @@ -169,7 +172,7 @@ public void cancelRequest_shouldForwardCancellation() { } @Test - public void nonStreamingOperation_noChecksumAlgoProvided_shouldNotSetByDefault() { + public void nonStreamingOperation_noChecksumAlgoProvided_shouldSetToDefaultCRC32() { HttpChecksum httpChecksum = HttpChecksum.builder() .isRequestStreaming(false) .build(); @@ -182,11 +185,11 @@ public void nonStreamingOperation_noChecksumAlgoProvided_shouldNotSetByDefault() .build(); S3MetaRequestOptions actual = makeRequest(asyncExecuteRequest); - assertThat(actual.getChecksumConfig().getChecksumAlgorithm()).isEqualTo(ChecksumAlgorithm.NONE); + assertThat(actual.getChecksumConfig().getChecksumAlgorithm()).isEqualTo(ChecksumAlgorithm.CRC32); } @Test - public void nonStreamingOperation_checksumAlgoProvided_shouldNotPassToCrt() { + public void nonStreamingOperation_checksumAlgoSHA1Provided_shouldPassToCrt() { HttpChecksum httpChecksum = HttpChecksum.builder() .isRequestStreaming(false) .requestAlgorithm("SHA1") @@ -199,7 +202,24 @@ public void nonStreamingOperation_checksumAlgoProvided_shouldNotPassToCrt() { .build(); S3MetaRequestOptions actual = makeRequest(asyncExecuteRequest); - assertThat(actual.getChecksumConfig().getChecksumAlgorithm()).isEqualTo(ChecksumAlgorithm.NONE); + assertThat(actual.getChecksumConfig().getChecksumAlgorithm()).isEqualTo(ChecksumAlgorithm.SHA1); + } + + @Test + public void nonStreamingOperation_checksumAlgoCRC64NVMEProvided_shouldPassToCrt() { + HttpChecksum httpChecksum = HttpChecksum.builder() + .isRequestStreaming(false) + .requestAlgorithm("CRC64NVME") + .build(); + AsyncExecuteRequest asyncExecuteRequest = getExecuteRequestBuilder().putHttpExecutionAttribute(OPERATION_NAME, + "NonStreaming") + + .putHttpExecutionAttribute(HTTP_CHECKSUM, + httpChecksum) + .build(); + + S3MetaRequestOptions actual = makeRequest(asyncExecuteRequest); + assertThat(actual.getChecksumConfig().getChecksumAlgorithm()).isEqualTo(ChecksumAlgorithm.CRC64NVME); } @Test @@ -209,9 +229,12 @@ public void checksumRequiredOperation_noChecksumAlgoProvided_shouldSetByDefault( .build(); AsyncExecuteRequest asyncExecuteRequest = getExecuteRequestBuilder().putHttpExecutionAttribute(OPERATION_NAME, "PutObject") - .putHttpExecutionAttribute(HTTP_CHECKSUM, httpChecksum) + .putHttpExecutionAttribute(REQUEST_CHECKSUM_CALCULATION, + RequestChecksumCalculation.WHEN_SUPPORTED) + .putHttpExecutionAttribute(RESPONSE_CHECKSUM_VALIDATION, + ResponseChecksumValidation.WHEN_SUPPORTED) .build(); S3MetaRequestOptions actual = makeRequest(asyncExecuteRequest); @@ -225,9 +248,12 @@ public void streamingOperation_noChecksumAlgoProvided_shouldSetByDefault() { .build(); AsyncExecuteRequest asyncExecuteRequest = getExecuteRequestBuilder().putHttpExecutionAttribute(OPERATION_NAME, "PutObject") - .putHttpExecutionAttribute(HTTP_CHECKSUM, httpChecksum) + .putHttpExecutionAttribute(REQUEST_CHECKSUM_CALCULATION, + RequestChecksumCalculation.WHEN_SUPPORTED) + .putHttpExecutionAttribute(RESPONSE_CHECKSUM_VALIDATION, + ResponseChecksumValidation.WHEN_SUPPORTED) .build(); S3MetaRequestOptions actual = makeRequest(asyncExecuteRequest); @@ -241,9 +267,12 @@ public void operationWithResponseAlgorithms_validateNotSpecified_shouldValidateB .build(); AsyncExecuteRequest asyncExecuteRequest = getExecuteRequestBuilder().putHttpExecutionAttribute(OPERATION_NAME, "GetObject") - .putHttpExecutionAttribute(HTTP_CHECKSUM, httpChecksum) + .putHttpExecutionAttribute(REQUEST_CHECKSUM_CALCULATION, + RequestChecksumCalculation.WHEN_SUPPORTED) + .putHttpExecutionAttribute(RESPONSE_CHECKSUM_VALIDATION, + ResponseChecksumValidation.WHEN_SUPPORTED) .build(); S3MetaRequestOptions actual = makeRequest(asyncExecuteRequest); @@ -259,7 +288,6 @@ public void operationWithResponseAlgorithms_optOutValidationFromClient_shouldHon s3NativeClientConfiguration = S3NativeClientConfiguration.builder() .endpointOverride(DEFAULT_ENDPOINT) .credentialsProvider(null) - .checksumValidationEnabled(false) .build(); asyncHttpClient = new S3CrtAsyncHttpClient(s3Client, S3CrtAsyncHttpClient.builder() @@ -267,7 +295,6 @@ public void operationWithResponseAlgorithms_optOutValidationFromClient_shouldHon AsyncExecuteRequest asyncExecuteRequest = getExecuteRequestBuilder().putHttpExecutionAttribute(OPERATION_NAME, "GetObject") - .putHttpExecutionAttribute(HTTP_CHECKSUM, httpChecksum) .build(); @@ -286,7 +313,6 @@ public void operationWithResponseAlgorithms_optInFromRequest_shouldHonor() { s3NativeClientConfiguration = S3NativeClientConfiguration.builder() .endpointOverride(DEFAULT_ENDPOINT) .credentialsProvider(null) - .checksumValidationEnabled(false) .build(); asyncHttpClient = new S3CrtAsyncHttpClient(s3Client, S3CrtAsyncHttpClient.builder() @@ -294,7 +320,6 @@ public void operationWithResponseAlgorithms_optInFromRequest_shouldHonor() { AsyncExecuteRequest asyncExecuteRequest = getExecuteRequestBuilder().putHttpExecutionAttribute(OPERATION_NAME, "GetObject") - .putHttpExecutionAttribute(HTTP_CHECKSUM, httpChecksum) .build(); @@ -322,7 +347,6 @@ public void streamingOperation_checksumAlgoProvided_shouldTakePrecedence() { .build(); AsyncExecuteRequest asyncExecuteRequest = getExecuteRequestBuilder().putHttpExecutionAttribute(OPERATION_NAME, "PutObject") - .putHttpExecutionAttribute(HTTP_CHECKSUM, httpChecksum) .build(); @@ -342,6 +366,10 @@ public void s3Express_shouldUseS3ExpressSigner() { Region.AP_SOUTH_1) .putHttpExecutionAttribute(SIGNING_NAME, "s3express") .putHttpExecutionAttribute(USE_S3_EXPRESS_AUTH, true) + .putHttpExecutionAttribute(REQUEST_CHECKSUM_CALCULATION, + RequestChecksumCalculation.WHEN_SUPPORTED) + .putHttpExecutionAttribute(RESPONSE_CHECKSUM_VALIDATION, + ResponseChecksumValidation.WHEN_SUPPORTED) .putHttpExecutionAttribute(HTTP_CHECKSUM, httpChecksum) .build(); @@ -367,6 +395,10 @@ public void nonS3Express_shouldUseDefaultSigner() { .putHttpExecutionAttribute(SIGNING_NAME, "s3") .putHttpExecutionAttribute(HTTP_CHECKSUM, httpChecksum) + .putHttpExecutionAttribute(REQUEST_CHECKSUM_CALCULATION, + RequestChecksumCalculation.WHEN_SUPPORTED) + .putHttpExecutionAttribute(RESPONSE_CHECKSUM_VALIDATION, + ResponseChecksumValidation.WHEN_SUPPORTED) .build(); S3MetaRequestOptions actual = makeRequest(asyncExecuteRequest); diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/handlers/AsyncChecksumValidationInterceptorTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/handlers/AsyncChecksumValidationInterceptorTest.java index cb78620db9c1..0edd1edf5abb 100644 --- a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/handlers/AsyncChecksumValidationInterceptorTest.java +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/handlers/AsyncChecksumValidationInterceptorTest.java @@ -20,7 +20,8 @@ import static org.assertj.core.api.Java6Assertions.assertThatThrownBy; import static software.amazon.awssdk.core.ClientType.ASYNC; import static software.amazon.awssdk.core.interceptor.SdkExecutionAttribute.CLIENT_TYPE; -import static software.amazon.awssdk.core.interceptor.SdkExecutionAttribute.SERVICE_CONFIG; +import static software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute.REQUEST_CHECKSUM_CALCULATION; +import static software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute.RESPONSE_CHECKSUM_VALIDATION; import static software.amazon.awssdk.services.s3.internal.checksums.ChecksumConstant.CHECKSUM_ENABLED_RESPONSE_HEADER; import static software.amazon.awssdk.services.s3.internal.checksums.ChecksumConstant.CONTENT_LENGTH_HEADER; import static software.amazon.awssdk.services.s3.internal.checksums.ChecksumConstant.ENABLE_MD5_CHECKSUM_HEADER_VALUE; @@ -36,6 +37,8 @@ import org.reactivestreams.Publisher; import software.amazon.awssdk.core.async.AsyncRequestBody; import software.amazon.awssdk.core.checksums.Md5Checksum; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidation; import software.amazon.awssdk.core.checksums.SdkChecksum; import software.amazon.awssdk.core.interceptor.Context; import software.amazon.awssdk.core.interceptor.ExecutionAttributes; @@ -44,8 +47,6 @@ import software.amazon.awssdk.http.SdkHttpMethod; import software.amazon.awssdk.http.SdkHttpRequest; import software.amazon.awssdk.http.SdkHttpResponse; -import software.amazon.awssdk.services.s3.S3Configuration; -import software.amazon.awssdk.services.s3.internal.checksums.ChecksumCalculatingAsyncRequestBody; import software.amazon.awssdk.services.s3.internal.checksums.S3ChecksumValidatingPublisher; import software.amazon.awssdk.services.s3.model.GetObjectRequest; import software.amazon.awssdk.services.s3.model.PutObjectRequest; @@ -61,19 +62,6 @@ public class AsyncChecksumValidationInterceptorTest { private AsyncChecksumValidationInterceptor interceptor = new AsyncChecksumValidationInterceptor(); - @Test - public void modifyAsyncHttpContent_putObjectRequestChecksumEnabled_shouldWrapChecksumRequestBody() { - ExecutionAttributes executionAttributes = getExecutionAttributes(); - Context.ModifyHttpRequest modifyHttpRequest = - InterceptorTestUtils.modifyHttpRequestContext(PutObjectRequest.builder().build()); - Optional asyncRequestBody = interceptor.modifyAsyncHttpContent(modifyHttpRequest, - executionAttributes); - - assertThat(asyncRequestBody.isPresent()).isTrue(); - assertThat(executionAttributes.getAttribute(CHECKSUM)).isNotNull(); - assertThat(asyncRequestBody.get()).isExactlyInstanceOf(ChecksumCalculatingAsyncRequestBody.class); - } - @Test public void modifyAsyncHttpContent_nonPutObjectRequest_shouldNotModify() { ExecutionAttributes executionAttributes = getExecutionAttributes(); @@ -154,36 +142,6 @@ public void afterUnmarshalling_putObjectRequest_shouldValidateChecksum() { interceptor.afterUnmarshalling(afterUnmarshallingContext, getExecutionAttributesWithChecksum()); } - @Test - public void afterUnmarshalling_putObjectRequest_shouldValidateChecksum_throwExceptionIfInvalid() { - SdkHttpResponse sdkHttpResponse = getSdkHttpResponseWithChecksumHeader(); - - PutObjectResponse response = PutObjectResponse.builder() - .eTag(INVALID_CHECKSUM) - .build(); - - PutObjectRequest putObjectRequest = PutObjectRequest.builder().build(); - - SdkHttpRequest sdkHttpRequest = SdkHttpFullRequest.builder() - .uri(URI.create("http://localhost:8080")) - .method(SdkHttpMethod.PUT) - .build(); - - Context.AfterUnmarshalling afterUnmarshallingContext = - InterceptorContext.builder() - .request(putObjectRequest) - .httpRequest(sdkHttpRequest) - .response(response) - .httpResponse(sdkHttpResponse) - .asyncRequestBody(AsyncRequestBody.fromString("Test")) - .build(); - - ExecutionAttributes attributes = getExecutionAttributesWithChecksum(); - interceptor.modifyAsyncHttpContent(afterUnmarshallingContext, attributes); - assertThatThrownBy(() -> interceptor.afterUnmarshalling(afterUnmarshallingContext, attributes)) - .hasMessageContaining("Data read has a different checksum than expected."); - } - @Test public void afterUnmarshalling_putObjectRequest_with_SSE_shouldNotValidateChecksum() { SdkHttpResponse sdkHttpResponse = getSdkHttpResponseWithChecksumHeader(); @@ -215,6 +173,8 @@ private ExecutionAttributes getExecutionAttributesWithChecksum() { private ExecutionAttributes getExecutionAttributes() { ExecutionAttributes executionAttributes = new ExecutionAttributes(); executionAttributes.putAttribute(CLIENT_TYPE, ASYNC); + executionAttributes.putAttribute(REQUEST_CHECKSUM_CALCULATION, RequestChecksumCalculation.WHEN_SUPPORTED); + executionAttributes.putAttribute(RESPONSE_CHECKSUM_VALIDATION, ResponseChecksumValidation.WHEN_SUPPORTED); return executionAttributes; } @@ -227,7 +187,8 @@ private SdkHttpResponse getSdkHttpResponseWithChecksumHeader() { private ExecutionAttributes getExecutionAttributesWithChecksumDisabled() { ExecutionAttributes executionAttributes = getExecutionAttributes(); - executionAttributes.putAttribute(SERVICE_CONFIG, S3Configuration.builder().checksumValidationEnabled(false).build()); + executionAttributes.putAttribute(REQUEST_CHECKSUM_CALCULATION, RequestChecksumCalculation.WHEN_REQUIRED); + executionAttributes.putAttribute(RESPONSE_CHECKSUM_VALIDATION, ResponseChecksumValidation.WHEN_REQUIRED); return executionAttributes; } diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/handlers/EnableTrailingChecksumInterceptorTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/handlers/EnableTrailingChecksumInterceptorTest.java index 33de9db6352d..f5e56277dca0 100644 --- a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/handlers/EnableTrailingChecksumInterceptorTest.java +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/handlers/EnableTrailingChecksumInterceptorTest.java @@ -16,6 +16,8 @@ package software.amazon.awssdk.services.s3.internal.handlers; import static org.assertj.core.api.Assertions.assertThat; +import static software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute.REQUEST_CHECKSUM_CALCULATION; +import static software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute.RESPONSE_CHECKSUM_VALIDATION; import static software.amazon.awssdk.services.s3.internal.checksums.ChecksumConstant.CHECKSUM_ENABLED_RESPONSE_HEADER; import static software.amazon.awssdk.services.s3.internal.checksums.ChecksumConstant.ENABLE_CHECKSUM_REQUEST_HEADER; import static software.amazon.awssdk.services.s3.internal.checksums.ChecksumConstant.ENABLE_MD5_CHECKSUM_HEADER_VALUE; @@ -30,14 +32,14 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import software.amazon.awssdk.core.SdkRequest; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidation; import software.amazon.awssdk.core.interceptor.Context; import software.amazon.awssdk.core.interceptor.ExecutionAttributes; -import software.amazon.awssdk.core.interceptor.SdkExecutionAttribute; import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute; import software.amazon.awssdk.endpoints.Endpoint; import software.amazon.awssdk.http.SdkHttpFullResponse; import software.amazon.awssdk.http.SdkHttpRequest; -import software.amazon.awssdk.services.s3.S3Configuration; import software.amazon.awssdk.services.s3.endpoints.internal.KnownS3ExpressEndpointProperty; import software.amazon.awssdk.services.s3.model.ChecksumMode; import software.amazon.awssdk.services.s3.model.GetObjectAclRequest; @@ -131,8 +133,11 @@ public void modifyRequest_nonGetObjectRequest_shouldNotModify() { private ExecutionAttributes createExecutionAttributes(boolean disableChecksumValidation, boolean useS3Express) { ExecutionAttributes executionAttributes = new ExecutionAttributes(); if (disableChecksumValidation) { - executionAttributes.putAttribute(SdkExecutionAttribute.SERVICE_CONFIG, - S3Configuration.builder().checksumValidationEnabled(false).build()); + executionAttributes.putAttribute(REQUEST_CHECKSUM_CALCULATION, RequestChecksumCalculation.WHEN_REQUIRED); + executionAttributes.putAttribute(RESPONSE_CHECKSUM_VALIDATION, ResponseChecksumValidation.WHEN_REQUIRED); + } else { + executionAttributes.putAttribute(REQUEST_CHECKSUM_CALCULATION, RequestChecksumCalculation.WHEN_SUPPORTED); + executionAttributes.putAttribute(RESPONSE_CHECKSUM_VALIDATION, ResponseChecksumValidation.WHEN_SUPPORTED); } if (useS3Express) { Endpoint s3ExpressEndpoint = Endpoint.builder().putAttribute(KnownS3ExpressEndpointProperty.BACKEND, "S3Express").build(); diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/handlers/S3ExpressChecksumInterceptorTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/handlers/S3ExpressChecksumInterceptorTest.java deleted file mode 100644 index 181b37c39fff..000000000000 --- a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/handlers/S3ExpressChecksumInterceptorTest.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"). - * You may not use this file except in compliance with the License. - * A copy of the License is located at - * - * http://aws.amazon.com/apache2.0 - * - * or in the "license" file accompanying this file. This file is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -package software.amazon.awssdk.services.s3.internal.handlers; - -import static org.assertj.core.api.Assertions.assertThat; -import static software.amazon.awssdk.core.interceptor.SdkExecutionAttribute.RESOLVED_CHECKSUM_SPECS; -import static software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute.RESOLVED_ENDPOINT; -import static software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute.SELECTED_AUTH_SCHEME; -import static software.amazon.awssdk.http.auth.aws.signer.AwsV4FamilyHttpSigner.CHECKSUM_ALGORITHM; -import static software.amazon.awssdk.services.s3.utils.InterceptorTestUtils.modifyHttpRequestContext; - -import java.util.concurrent.CompletableFuture; -import org.junit.jupiter.api.Test; -import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute; -import software.amazon.awssdk.checksums.DefaultChecksumAlgorithm; -import software.amazon.awssdk.core.SdkRequest; -import software.amazon.awssdk.core.SelectedAuthScheme; -import software.amazon.awssdk.core.checksums.Algorithm; -import software.amazon.awssdk.core.checksums.ChecksumSpecs; -import software.amazon.awssdk.core.interceptor.Context; -import software.amazon.awssdk.core.interceptor.ExecutionAttributes; -import software.amazon.awssdk.endpoints.Endpoint; -import software.amazon.awssdk.http.SdkHttpRequest; -import software.amazon.awssdk.http.auth.spi.scheme.AuthSchemeOption; -import software.amazon.awssdk.services.s3.internal.s3express.DefaultS3ExpressHttpSigner; -import software.amazon.awssdk.services.s3.endpoints.internal.KnownS3ExpressEndpointProperty; -import software.amazon.awssdk.services.s3.s3express.S3ExpressSessionCredentials; -import software.amazon.awssdk.services.s3.model.PutObjectRequest; - -public class S3ExpressChecksumInterceptorTest { - - private final S3ExpressChecksumInterceptor interceptor = new S3ExpressChecksumInterceptor(); - - @Test - public void putObjectRequest_withNoChecksumSet_addsCrc32() { - PutObjectRequest request = PutObjectRequest.builder().build(); - Algorithm algorithm = null; - ExecutionAttributes executionAttributes = createExecutionAttributes(algorithm); - - Context.ModifyRequest modifyRequestContext = () -> request; - SdkRequest modifiedRequest = interceptor.modifyRequest(modifyRequestContext, executionAttributes); - assertThat(executionAttributes.getAttribute(SELECTED_AUTH_SCHEME).authSchemeOption().signerProperty(CHECKSUM_ALGORITHM)).isEqualTo(DefaultChecksumAlgorithm.CRC32); - - Context.ModifyHttpRequest modifyHttpRequestContext = modifyHttpRequestContext(modifiedRequest); - SdkHttpRequest sdkHttpRequest = interceptor.modifyHttpRequest(modifyHttpRequestContext, executionAttributes); - assertThat(sdkHttpRequest.firstMatchingHeader("x-amz-sdk-checksum-algorithm")).contains("CRC32"); - } - - @Test - public void putObjectRequest_withNonCrc32AlgorithmTypeSet_doesNotAddCrc32() { - PutObjectRequest request = PutObjectRequest.builder().build(); - Algorithm algorithm = Algorithm.SHA1; - ExecutionAttributes executionAttributes = createExecutionAttributes(algorithm); - - Context.ModifyRequest modifyRequestContext = () -> request; - SdkRequest modifiedRequest = interceptor.modifyRequest(modifyRequestContext, executionAttributes); - assertThat(executionAttributes.getAttribute(SELECTED_AUTH_SCHEME).authSchemeOption().signerProperty(CHECKSUM_ALGORITHM)).isEqualTo(DefaultChecksumAlgorithm.SHA1); - - Context.ModifyHttpRequest modifyHttpRequestContext = modifyHttpRequestContext(modifiedRequest); - SdkHttpRequest sdkHttpRequest = interceptor.modifyHttpRequest(modifyHttpRequestContext, executionAttributes); - assertThat(sdkHttpRequest.firstMatchingHeader("x-amz-sdk-checksum-algorithm")).isEmpty(); - } - - @Test - public void putObjectRequest_withChecksumSha1ValueSet_doesNotAddCrc32() { - PutObjectRequest request = PutObjectRequest.builder() - .checksumSHA1("sha1Value") - .build(); - Algorithm algorithm = null; - ExecutionAttributes executionAttributes = createExecutionAttributes(algorithm); - - Context.ModifyRequest modifyRequestContext = () -> request; - SdkRequest modifiedRequest = interceptor.modifyRequest(modifyRequestContext, executionAttributes); - assertThat(executionAttributes.getAttribute(SELECTED_AUTH_SCHEME).authSchemeOption().signerProperty(CHECKSUM_ALGORITHM)).isNull(); - - Context.ModifyHttpRequest modifyHttpRequestContext = modifyHttpRequestContext(modifiedRequest); - SdkHttpRequest sdkHttpRequest = interceptor.modifyHttpRequest(modifyHttpRequestContext, executionAttributes); - assertThat(sdkHttpRequest.firstMatchingHeader("x-amz-sdk-checksum-algorithm")).isEmpty(); - } - - @Test - public void putObjectRequest_withChecksumSha256ValueSet_doesNotAddCrc32() { - PutObjectRequest request = PutObjectRequest.builder() - .checksumSHA256("sha256Value") - .build(); - Algorithm algorithm = null; - ExecutionAttributes executionAttributes = createExecutionAttributes(algorithm); - - Context.ModifyRequest modifyRequestContext = () -> request; - SdkRequest modifiedRequest = interceptor.modifyRequest(modifyRequestContext, executionAttributes); - assertThat(executionAttributes.getAttribute(SELECTED_AUTH_SCHEME).authSchemeOption().signerProperty(CHECKSUM_ALGORITHM)).isNull(); - - Context.ModifyHttpRequest modifyHttpRequestContext = modifyHttpRequestContext(modifiedRequest); - SdkHttpRequest sdkHttpRequest = interceptor.modifyHttpRequest(modifyHttpRequestContext, executionAttributes); - assertThat(sdkHttpRequest.firstMatchingHeader("x-amz-sdk-checksum-algorithm")).isEmpty(); - } - - @Test - public void putObjectRequest_withChecksumCrc32ValueSet_doesNotAddCrc32() { - PutObjectRequest request = PutObjectRequest.builder() - .checksumCRC32("crc32Value") - .build(); - Algorithm algorithm = null; - ExecutionAttributes executionAttributes = createExecutionAttributes(algorithm); - - Context.ModifyRequest modifyRequestContext = () -> request; - SdkRequest modifiedRequest = interceptor.modifyRequest(modifyRequestContext, executionAttributes); - assertThat(executionAttributes.getAttribute(SELECTED_AUTH_SCHEME).authSchemeOption().signerProperty(CHECKSUM_ALGORITHM)).isNull(); - - Context.ModifyHttpRequest modifyHttpRequestContext = modifyHttpRequestContext(modifiedRequest); - SdkHttpRequest sdkHttpRequest = interceptor.modifyHttpRequest(modifyHttpRequestContext, executionAttributes); - assertThat(sdkHttpRequest.firstMatchingHeader("x-amz-sdk-checksum-algorithm")).isEmpty(); - } - - @Test - public void putObjectRequest_withChecksumCrc32CValueSet_doesNotAddCrc32() { - PutObjectRequest request = PutObjectRequest.builder() - .checksumCRC32C("crc32CValue") - .build(); - Algorithm algorithm = null; - ExecutionAttributes executionAttributes = createExecutionAttributes(algorithm); - - Context.ModifyRequest modifyRequestContext = () -> request; - SdkRequest modifiedRequest = interceptor.modifyRequest(modifyRequestContext, executionAttributes); - assertThat(executionAttributes.getAttribute(SELECTED_AUTH_SCHEME).authSchemeOption().signerProperty(CHECKSUM_ALGORITHM)).isNull(); - - Context.ModifyHttpRequest modifyHttpRequestContext = modifyHttpRequestContext(modifiedRequest); - SdkHttpRequest sdkHttpRequest = interceptor.modifyHttpRequest(modifyHttpRequestContext, executionAttributes); - assertThat(sdkHttpRequest.firstMatchingHeader("x-amz-sdk-checksum-algorithm")).isEmpty(); - } - - private ExecutionAttributes createExecutionAttributes(Algorithm algorithm) { - Endpoint endpoint = Endpoint.builder() - .putAttribute(KnownS3ExpressEndpointProperty.BACKEND, "S3Express") - .build(); - - S3ExpressSessionCredentials credentials = S3ExpressSessionCredentials.create("akid", "sak", "token"); - AuthSchemeOption authSchemeOption = AuthSchemeOption.builder().schemeId("aws.auth#sigv4-s3express").build(); - SelectedAuthScheme authScheme = - new SelectedAuthScheme<>(CompletableFuture.completedFuture(credentials), DefaultS3ExpressHttpSigner.create(), authSchemeOption); - - ChecksumSpecs checksumSpecs = ChecksumSpecs.builder() - .algorithm(algorithm) - .build(); - - return ExecutionAttributes.builder() - .put(RESOLVED_ENDPOINT, endpoint) - .put(SELECTED_AUTH_SCHEME, authScheme) - .put(RESOLVED_CHECKSUM_SPECS, checksumSpecs) - .build(); - } -} diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/handlers/SyncChecksumValidationInterceptorTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/handlers/SyncChecksumValidationInterceptorTest.java index 7b60b867e15a..c5e67a9a3ef9 100644 --- a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/handlers/SyncChecksumValidationInterceptorTest.java +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/handlers/SyncChecksumValidationInterceptorTest.java @@ -17,10 +17,10 @@ import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Java6Assertions.assertThatThrownBy; import static software.amazon.awssdk.core.ClientType.SYNC; import static software.amazon.awssdk.core.interceptor.SdkExecutionAttribute.CLIENT_TYPE; -import static software.amazon.awssdk.core.interceptor.SdkExecutionAttribute.SERVICE_CONFIG; +import static software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute.REQUEST_CHECKSUM_CALCULATION; +import static software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute.RESPONSE_CHECKSUM_VALIDATION; import static software.amazon.awssdk.services.s3.internal.checksums.ChecksumConstant.CHECKSUM_ENABLED_RESPONSE_HEADER; import static software.amazon.awssdk.services.s3.internal.checksums.ChecksumConstant.CONTENT_LENGTH_HEADER; import static software.amazon.awssdk.services.s3.internal.checksums.ChecksumConstant.ENABLE_MD5_CHECKSUM_HEADER_VALUE; @@ -33,30 +33,24 @@ import java.net.URI; import java.nio.ByteBuffer; import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.List; import java.util.Optional; import org.junit.jupiter.api.Test; import software.amazon.awssdk.core.checksums.Md5Checksum; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; +import software.amazon.awssdk.core.checksums.ResponseChecksumValidation; import software.amazon.awssdk.core.checksums.SdkChecksum; import software.amazon.awssdk.core.interceptor.Context; import software.amazon.awssdk.core.interceptor.ExecutionAttributes; -import software.amazon.awssdk.core.interceptor.InterceptorContext; import software.amazon.awssdk.core.sync.RequestBody; -import software.amazon.awssdk.http.ContentStreamProvider; import software.amazon.awssdk.http.SdkHttpFullRequest; import software.amazon.awssdk.http.SdkHttpMethod; import software.amazon.awssdk.http.SdkHttpRequest; import software.amazon.awssdk.http.SdkHttpResponse; -import software.amazon.awssdk.services.s3.S3Configuration; -import software.amazon.awssdk.services.s3.internal.checksums.ChecksumCalculatingInputStream; import software.amazon.awssdk.services.s3.internal.checksums.S3ChecksumValidatingInputStream; -import software.amazon.awssdk.services.s3.internal.handlers.SyncChecksumValidationInterceptor.ChecksumCalculatingStreamProvider; import software.amazon.awssdk.services.s3.model.GetObjectRequest; import software.amazon.awssdk.services.s3.model.PutObjectRequest; import software.amazon.awssdk.services.s3.model.PutObjectResponse; import software.amazon.awssdk.services.s3.utils.InterceptorTestUtils; -import software.amazon.awssdk.utils.IoUtils; import software.amazon.awssdk.utils.StringInputStream; import software.amazon.awssdk.utils.internal.Base16Lower; @@ -68,19 +62,6 @@ public class SyncChecksumValidationInterceptorTest { private SyncChecksumValidationInterceptor interceptor = new SyncChecksumValidationInterceptor(); - @Test - public void modifyHttpContent_putObjectRequestChecksumEnabled_shouldWrapChecksumRequestBody() { - ExecutionAttributes executionAttributes = getExecutionAttributes(); - Context.ModifyHttpRequest modifyHttpRequest = - InterceptorTestUtils.modifyHttpRequestContext(PutObjectRequest.builder().build()); - Optional requestBody = interceptor.modifyHttpContent(modifyHttpRequest, - executionAttributes); - - assertThat(requestBody.isPresent()).isTrue(); - assertThat(executionAttributes.getAttribute(CHECKSUM)).isNotNull(); - assertThat(requestBody.get().contentStreamProvider()).isNotEqualTo(modifyHttpRequest.requestBody().get().contentStreamProvider()); - } - @Test public void modifyHttpContent_nonPutObjectRequest_shouldNotModify() { ExecutionAttributes executionAttributes = getExecutionAttributes(); @@ -139,31 +120,6 @@ public void modifyHttpResponseContent_nonGetObjectRequest_shouldNotModify() { } - @Test - public void checksumCalculatingStreamProvider_shouldReturnNewStreamResetChecksum() throws IOException { - List closeAwareStreams = new ArrayList<>(); - ContentStreamProvider underlyingStreamProvider = () -> { - CloseAwareStream stream = new CloseAwareStream(new StringInputStream("helloWorld")); - closeAwareStreams.add(stream); - return stream; - }; - SdkChecksum checksum = new Md5Checksum(); - ChecksumCalculatingStreamProvider checksumCalculatingStreamProvider = - new ChecksumCalculatingStreamProvider(underlyingStreamProvider, checksum); - - ChecksumCalculatingInputStream currentStream = (ChecksumCalculatingInputStream) checksumCalculatingStreamProvider.newStream(); - IoUtils.drainInputStream(currentStream); - byte[] checksumBytes = currentStream.getChecksumBytes(); - - ChecksumCalculatingInputStream newStream = (ChecksumCalculatingInputStream) checksumCalculatingStreamProvider.newStream(); - assertThat(closeAwareStreams.get(0).isClosed).isTrue(); - IoUtils.drainInputStream(newStream); - byte[] newStreamChecksumBytes = newStream.getChecksumBytes(); - - assertThat(getChecksum(checksumBytes)).isEqualTo(getChecksum(newStreamChecksumBytes)); - newStream.close(); - } - @Test public void afterUnmarshalling_putObjectRequest_shouldValidateChecksum() { SdkHttpResponse sdkHttpResponse = getSdkHttpResponseWithChecksumHeader(); @@ -186,37 +142,6 @@ public void afterUnmarshalling_putObjectRequest_shouldValidateChecksum() { interceptor.afterUnmarshalling(afterUnmarshallingContext, getExecutionAttributesWithChecksum()); } - @Test - public void afterUnmarshalling_putObjectRequest_shouldValidateChecksum_throwExceptionIfInvalid() { - SdkHttpResponse sdkHttpResponse = getSdkHttpResponseWithChecksumHeader(); - - PutObjectResponse response = PutObjectResponse.builder() - .eTag(INVALID_CHECKSUM) - .build(); - - PutObjectRequest putObjectRequest = PutObjectRequest.builder().build(); - - SdkHttpRequest sdkHttpRequest = SdkHttpFullRequest.builder() - .uri(URI.create("http://localhost:8080")) - .method(SdkHttpMethod.PUT) - .contentStreamProvider(() -> new StringInputStream("Test")) - .build(); - - Context.AfterUnmarshalling afterUnmarshallingContext = - InterceptorContext.builder() - .request(putObjectRequest) - .httpRequest(sdkHttpRequest) - .response(response) - .httpResponse(sdkHttpResponse) - .requestBody(RequestBody.fromString("Test")) - .build(); - - ExecutionAttributes attributes = getExecutionAttributesWithChecksum(); - interceptor.modifyHttpContent(afterUnmarshallingContext, attributes); - assertThatThrownBy(() -> interceptor.afterUnmarshalling(afterUnmarshallingContext, attributes)) - .hasMessageContaining("Data read has a different checksum than expected."); - } - @Test public void afterUnmarshalling_putObjectRequest_with_SSE_shouldNotValidateChecksum() { SdkHttpResponse sdkHttpResponse = getSdkHttpResponseWithChecksumHeader(); @@ -268,6 +193,8 @@ private int getChecksum(byte[] checksumBytes) { private ExecutionAttributes getExecutionAttributes() { ExecutionAttributes executionAttributes = new ExecutionAttributes(); executionAttributes.putAttribute(CLIENT_TYPE, SYNC); + executionAttributes.putAttribute(REQUEST_CHECKSUM_CALCULATION, RequestChecksumCalculation.WHEN_SUPPORTED); + executionAttributes.putAttribute(RESPONSE_CHECKSUM_VALIDATION, ResponseChecksumValidation.WHEN_SUPPORTED); return executionAttributes; } @@ -280,7 +207,8 @@ private SdkHttpResponse getSdkHttpResponseWithChecksumHeader() { private ExecutionAttributes getExecutionAttributesWithChecksumDisabled() { ExecutionAttributes executionAttributes = getExecutionAttributes(); - executionAttributes.putAttribute(SERVICE_CONFIG, S3Configuration.builder().checksumValidationEnabled(false).build()); + executionAttributes.putAttribute(REQUEST_CHECKSUM_CALCULATION, RequestChecksumCalculation.WHEN_REQUIRED); + executionAttributes.putAttribute(RESPONSE_CHECKSUM_VALIDATION, ResponseChecksumValidation.WHEN_REQUIRED); return executionAttributes; } diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/KnownContentLengthAsyncRequestBodySubscriberTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/KnownContentLengthAsyncRequestBodySubscriberTest.java index ee98bbe9e4c8..68c54bd4b7c1 100644 --- a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/KnownContentLengthAsyncRequestBodySubscriberTest.java +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/KnownContentLengthAsyncRequestBodySubscriberTest.java @@ -105,7 +105,8 @@ private S3ResumeToken configureSubscriberAndPause(int numExistingParts, new CompletableFuture<>()); when(multipartUploadHelper.completeMultipartUpload(any(CompletableFuture.class), any(String.class), - any(CompletedPart[].class), any(PutObjectRequest.class))) + any(CompletedPart[].class), any(PutObjectRequest.class), + any(Long.class))) .thenReturn(completeMpuFuture); subscriber.onComplete(); return subscriber.pause(); diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/MultipartClientChecksumTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/MultipartClientChecksumTest.java index 351c1a750a60..52a1b1dac748 100644 --- a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/MultipartClientChecksumTest.java +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/MultipartClientChecksumTest.java @@ -15,131 +15,259 @@ package software.amazon.awssdk.services.s3.internal.multipart; +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.put; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; import static org.assertj.core.api.Assertions.assertThat; +import com.github.tomakehurst.wiremock.WireMockServer; +import java.io.IOException; +import java.io.OutputStream; +import java.io.UncheckedIOException; import java.net.URI; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; +import java.util.stream.Stream; +import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import software.amazon.awssdk.core.async.AsyncRequestBody; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; import software.amazon.awssdk.core.interceptor.Context; import software.amazon.awssdk.core.interceptor.ExecutionAttributes; import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; -import software.amazon.awssdk.http.HttpExecuteResponse; -import software.amazon.awssdk.http.SdkHttpRequest; -import software.amazon.awssdk.http.SdkHttpResponse; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.s3.S3AsyncClient; import software.amazon.awssdk.services.s3.model.ChecksumAlgorithm; +import software.amazon.awssdk.services.s3.model.ChecksumType; +import software.amazon.awssdk.services.s3.model.CompleteMultipartUploadRequest; +import software.amazon.awssdk.services.s3.model.CreateMultipartUploadRequest; import software.amazon.awssdk.services.s3.model.PutObjectRequest; -import software.amazon.awssdk.testutils.service.http.MockAsyncHttpClient; +import software.amazon.awssdk.services.s3.model.UploadPartRequest; class MultipartClientChecksumTest { - private MockAsyncHttpClient mockAsyncHttpClient; + private static final WireMockServer wireMock = new WireMockServer(wireMockConfig().dynamicPort()); + private static final long FILE_SIZE = 16 * 1024 * 1024L; + private static Path testFile; private ChecksumCapturingInterceptor checksumCapturingInterceptor; - private S3AsyncClient s3Client; + private S3AsyncClient multipartS3; + + @BeforeAll + public static void setup() throws IOException { + testFile = Files.createTempFile("16mib", ".dat"); + writeTestFile(testFile, FILE_SIZE); + wireMock.start(); + } + + public static Stream checksumAlgorithmParams() { + List checksumAlgorithms = new ArrayList<>(ChecksumAlgorithm.knownValues()); + checksumAlgorithms.add(null); + return checksumAlgorithms.stream(); + } @BeforeEach void init() { - this.mockAsyncHttpClient = new MockAsyncHttpClient(); this.checksumCapturingInterceptor = new ChecksumCapturingInterceptor(); - s3Client = S3AsyncClient.builder() - .httpClient(mockAsyncHttpClient) - .endpointOverride(URI.create("http://localhost")) - .overrideConfiguration(c -> c.addExecutionInterceptor(checksumCapturingInterceptor)) - .multipartEnabled(true) - .region(Region.US_EAST_1) - .build(); + multipartS3 = S3AsyncClient.builder() + .credentialsProvider(StaticCredentialsProvider.create( + AwsBasicCredentials.create("akid", "skid"))) + .endpointOverride(URI.create("http://localhost:" + wireMock.port())) + .overrideConfiguration(c -> c.addExecutionInterceptor(checksumCapturingInterceptor)) + .region(Region.US_EAST_1) + .multipartEnabled(true) + .forcePathStyle(true) + .build(); } @AfterEach void reset() { - this.mockAsyncHttpClient.reset(); + multipartS3.close(); } - @Test - public void putObject_default_shouldAddCrc32() { - HttpExecuteResponse response = HttpExecuteResponse.builder() - .response(SdkHttpResponse.builder().statusCode(200).build()) - .build(); - mockAsyncHttpClient.stubResponses(response); + @AfterAll + public static void teardown() throws IOException { + Files.deleteIfExists(testFile); + wireMock.stop(); + } - PutObjectRequest putObjectRequest = putObjectRequestBuilder().build(); + @ParameterizedTest + @MethodSource("checksumAlgorithmParams") + public void multipartUpload_withChecksumAlgorithmAndNoChecksumValueProvided_shouldNotAddChecksumType(ChecksumAlgorithm checksumAlgorithm) { + stubSuccessfulResponses(); + PutObjectRequest putObjectRequest = putObjectRequestBuilder().checksumAlgorithm(checksumAlgorithm).build(); - s3Client.putObject(putObjectRequest, AsyncRequestBody.fromString("hello world")); - assertThat(checksumCapturingInterceptor.checksumHeader).isEqualTo("CRC32"); + String expectedChecksumAlgo = checksumAlgorithm == null ? "CRC32" : checksumAlgorithm.toString(); + multipartS3.putObject(putObjectRequest, testFile).join(); + assertThat(checksumCapturingInterceptor.createMpuChecksumAlgorithm).isEqualTo(expectedChecksumAlgo); + assertThat(checksumCapturingInterceptor.uploadPartChecksumAlgorithm).isEqualTo(expectedChecksumAlgo); + assertThat(checksumCapturingInterceptor.createMpuChecksumType).isNull(); + assertThat(checksumCapturingInterceptor.completeMpuChecksumType).isNull(); + assertThat(checksumCapturingInterceptor.completeMpuMpObjectSize).isEqualTo(FILE_SIZE); } - @Test - public void putObject_withNonCrc32ChecksumType_shouldNotAddCrc32() { - HttpExecuteResponse response = HttpExecuteResponse.builder() - .response(SdkHttpResponse.builder().statusCode(200).build()) - .build(); - mockAsyncHttpClient.stubResponses(response); + @ParameterizedTest + @MethodSource("checksumAlgorithmParams") + public void multipartUpload_withChecksumValueProvided_shouldUseSameAlgorithmForUploadAndAddChecksumTypeFullObject(ChecksumAlgorithm checksumAlgorithm) { + stubSuccessfulResponses(); - PutObjectRequest putObjectRequest = - putObjectRequestBuilder() - .checksumAlgorithm(ChecksumAlgorithm.SHA256) - .build(); + PutObjectRequest.Builder requestBuilder = putObjectRequestBuilder(); + if (checksumAlgorithm != null) { + switch (checksumAlgorithm) { + case CRC32: + requestBuilder.checksumCRC32("checksumVal"); + break; + case SHA256: + requestBuilder.checksumSHA256("checksumVal"); + break; + case CRC32_C: + requestBuilder.checksumCRC32C("checksumVal"); + break; + case SHA1: + requestBuilder.checksumSHA1("checksumVal"); + break; + case CRC64_NVME: + requestBuilder.checksumCRC64NVME("checksumVal"); + break; + default: + throw new UnsupportedOperationException("Unsupported checksum algorithm: " + checksumAlgorithm); + } + } - s3Client.putObject(putObjectRequest, AsyncRequestBody.fromString("hello world")); - assertThat(checksumCapturingInterceptor.checksumHeader).isEqualTo("SHA256"); - } + String expectedChecksumAlgo = checksumAlgorithm == null ? "CRC32" : checksumAlgorithm.toString(); - @Test - public void putObject_withNonCrc32ChecksumValue_shouldNotAddCrc32() { - HttpExecuteResponse response = HttpExecuteResponse.builder() - .response(SdkHttpResponse.builder().statusCode(200).build()) - .build(); - mockAsyncHttpClient.stubResponses(response); - - PutObjectRequest putObjectRequest = - putObjectRequestBuilder() - .checksumSHA256("checksumVal") - .build(); - - s3Client.putObject(putObjectRequest, AsyncRequestBody.fromString("hello world")); - assertThat(checksumCapturingInterceptor.checksumHeader).isNull(); - assertThat(checksumCapturingInterceptor.headers.get("x-amz-checksum-sha256")).contains("checksumVal"); - } + multipartS3.putObject(requestBuilder.build(), testFile).join(); + assertThat(checksumCapturingInterceptor.createMpuChecksumAlgorithm).isEqualTo(expectedChecksumAlgo); + assertThat(checksumCapturingInterceptor.uploadPartChecksumAlgorithm).isEqualTo(expectedChecksumAlgo); + if (checksumAlgorithm != null) { + assertThat(checksumCapturingInterceptor.completeMpuHeaders.get("x-amz-checksum-" + expectedChecksumAlgo.toLowerCase(Locale.US))).contains( + "checksumVal"); - @Test - public void putObject_withCrc32Value_shouldNotAddCrc32TypeHeader() { - HttpExecuteResponse response = HttpExecuteResponse.builder() - .response(SdkHttpResponse.builder().statusCode(200).build()) - .build(); - mockAsyncHttpClient.stubResponses(response); - - PutObjectRequest putObjectRequest = - putObjectRequestBuilder() - .checksumCRC32("checksumVal") - .build(); - - s3Client.putObject(putObjectRequest, AsyncRequestBody.fromString("hello world")); - assertThat(checksumCapturingInterceptor.checksumHeader).isNull(); - assertThat(checksumCapturingInterceptor.headers.get("x-amz-checksum-crc32")).contains("checksumVal"); + assertThat(checksumCapturingInterceptor.createMpuChecksumType).isEqualTo(ChecksumType.FULL_OBJECT.toString()); + assertThat(checksumCapturingInterceptor.completeMpuChecksumType).isEqualTo(ChecksumType.FULL_OBJECT.toString()); + } + assertThat(checksumCapturingInterceptor.completeMpuMpObjectSize).isEqualTo(FILE_SIZE); } private PutObjectRequest.Builder putObjectRequestBuilder() { return PutObjectRequest.builder().bucket("bucket").key("key"); } + private void stubSuccessfulResponses() { + stubCreateMpuSuccessfulResponse(); + stubSuccessfulUploadParts(2); // 16 MB File Size / 8 MB Default Part Size + stubCompleteMpuSuccessfulResponse(); + } + + private void stubCreateMpuSuccessfulResponse() { + String mpuInitBody = "\n" + + "\n" + + " bucket\n" + + " key\n" + + " uploadId\n" + + ""; + + wireMock.stubFor(post(urlEqualTo("/bucket/key?uploads")) + .willReturn(aResponse() + .withStatus(200) + .withBody(mpuInitBody))); + } + + private void stubCompleteMpuSuccessfulResponse() { + String mpuCompleteBody = "\n" + + "\n" + + " bucket\n" + + " key\n" + + " etag\n" + + ""; + + wireMock.stubFor(post(urlEqualTo("/bucket/key?uploadId=uploadId")) + .willReturn(aResponse() + .withStatus(200) + .withBody(mpuCompleteBody))); + } + + private void stubSuccessfulUploadParts(int numParts) { + for (int i = 1; i <= numParts; i++) { + wireMock.stubFor(put(urlEqualTo("/bucket/key?partNumber=" + i + "&uploadId=uploadId")) + .willReturn(aResponse() + .withStatus(200) + .withBody("" + i + + "\"etag\""))); + } + + } + + private static void writeTestFile(Path file, long size) { + try (OutputStream os = Files.newOutputStream(file, StandardOpenOption.CREATE)) { + byte[] buff = new byte[4096]; + long remaining = size; + while (remaining != 0) { + int writeLen = (int) Math.min(remaining, buff.length); + os.write(buff, 0, writeLen); + remaining -= writeLen; + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + private static final class ChecksumCapturingInterceptor implements ExecutionInterceptor { - String checksumHeader; - Map> headers; + private static final String CHECKSUM_ALGORITHM_HEADER = "x-amz-checksum-algorithm"; + private static final String CHECKSUM_TYPE_HEADER = "x-amz-checksum-type"; + private static final String MP_OBJECT_SIZE_HEADER = "x-amz-mp-object-size"; + private static final String SDK_CHECKSUM_ALGORITHM_HEADER = "x-amz-sdk-checksum-algorithm"; + Map> completeMpuHeaders; + String createMpuChecksumType; + String createMpuChecksumAlgorithm; + String uploadPartChecksumAlgorithm; + String completeMpuChecksumType; + Long completeMpuMpObjectSize; @Override public void beforeTransmission(Context.BeforeTransmission context, ExecutionAttributes executionAttributes) { - SdkHttpRequest sdkHttpRequest = context.httpRequest(); - headers = sdkHttpRequest.headers(); - String checksumHeaderName = "x-amz-sdk-checksum-algorithm"; - if (headers.containsKey(checksumHeaderName)) { - List checksumHeaderVals = headers.get(checksumHeaderName); - assertThat(checksumHeaderVals).hasSize(1); - checksumHeader = checksumHeaderVals.get(0); + Map> headers = context.httpRequest().headers(); + if (isCreateMpuRequest(context) && headers.containsKey(CHECKSUM_ALGORITHM_HEADER)) { + createMpuChecksumAlgorithm = headers.get(CHECKSUM_ALGORITHM_HEADER).get(0); } + + if (isUploadPartRequest(context) && headers.containsKey(SDK_CHECKSUM_ALGORITHM_HEADER)) { + uploadPartChecksumAlgorithm = headers.get(SDK_CHECKSUM_ALGORITHM_HEADER).get(0); + } + + if (headers.containsKey(CHECKSUM_TYPE_HEADER)) { + if (isCreateMpuRequest(context)) { + createMpuChecksumType = headers.get(CHECKSUM_TYPE_HEADER).get(0); + } else if (isCompleteMpuRequest(context)) { + completeMpuChecksumType = headers.get(CHECKSUM_TYPE_HEADER).get(0); + } + } + + if (isCompleteMpuRequest(context) && headers.containsKey(MP_OBJECT_SIZE_HEADER)) { + completeMpuMpObjectSize = Long.valueOf(headers.get(MP_OBJECT_SIZE_HEADER).get(0)); + completeMpuHeaders = headers; + } + } + + private static boolean isCreateMpuRequest(Context.BeforeTransmission context) { + return context.request() instanceof CreateMultipartUploadRequest; + } + + private static boolean isCompleteMpuRequest(Context.BeforeTransmission context) { + return context.request() instanceof CompleteMultipartUploadRequest; + } + + private static boolean isUploadPartRequest(Context.BeforeTransmission context) { + return context.request() instanceof UploadPartRequest; } } -} +} \ No newline at end of file diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/MultipartS3AsyncClientTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/MultipartS3AsyncClientTest.java index 9d80be02bb71..848d7259124b 100644 --- a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/MultipartS3AsyncClientTest.java +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/MultipartS3AsyncClientTest.java @@ -15,7 +15,6 @@ package software.amazon.awssdk.services.s3.internal.multipart; -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; @@ -44,7 +43,7 @@ void byteRangeManuallySpecified_shouldBypassMultipart() { .key("test-key") .range("Range: bytes 0-499/1234") .build(); - S3AsyncClient s3AsyncClient = MultipartS3AsyncClient.create(mockDelegate, MultipartConfiguration.builder().build()); + S3AsyncClient s3AsyncClient = MultipartS3AsyncClient.create(mockDelegate, MultipartConfiguration.builder().build(), true); s3AsyncClient.getObject(req, mockTransformer); verify(mockTransformer, never()).split(any(SplittingTransformerConfiguration.class)); verify(mockDelegate, times(1)).getObject(any(GetObjectRequest.class), eq(mockTransformer)); @@ -60,7 +59,7 @@ void partManuallySpecified_shouldBypassMultipart() { .key("test-key") .partNumber(1) .build(); - S3AsyncClient s3AsyncClient = MultipartS3AsyncClient.create(mockDelegate, MultipartConfiguration.builder().build()); + S3AsyncClient s3AsyncClient = MultipartS3AsyncClient.create(mockDelegate, MultipartConfiguration.builder().build(), true); s3AsyncClient.getObject(req, mockTransformer); verify(mockTransformer, never()).split(any(SplittingTransformerConfiguration.class)); verify(mockDelegate, times(1)).getObject(any(GetObjectRequest.class), eq(mockTransformer)); diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/S3ChecksumUtilsTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/S3ChecksumUtilsTest.java new file mode 100644 index 000000000000..32ca15d326b8 --- /dev/null +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/S3ChecksumUtilsTest.java @@ -0,0 +1,62 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.services.s3.internal.multipart; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.services.s3.model.ChecksumAlgorithm; +import software.amazon.awssdk.services.s3.model.CreateMultipartUploadRequest; +import software.amazon.awssdk.services.s3.model.PutObjectRequest; + +public class S3ChecksumUtilsTest { + + @Test + public void checksumValueSpecified_requestWithoutChecksum_returnsFalse() { + boolean checksumValueSpecified = S3ChecksumUtils.checksumValueSpecified(putObjectRequestBuilder().build()); + assertThat(checksumValueSpecified).isFalse(); + } + + @Test + public void checksumValueSpecified_requestWithChecksum_returnsTrue() { + boolean checksumValueSpecified = S3ChecksumUtils.checksumValueSpecified(putObjectRequestBuilder() + .checksumCRC64NVME("val") + .build()); + assertThat(checksumValueSpecified).isTrue(); + } + + @Test + public void setChecksumAlgorithm_requestWithoutChecksum_doesNotSetAlgoOnCreateMpu() { + PutObjectRequest putObject = putObjectRequestBuilder().build(); + assertThat(S3ChecksumUtils.checksumAlgorithmFromPutObjectRequest(putObject)) + .isEmpty(); + } + + @Test + public void setChecksumAlgorithm_requestWithChecksum_setsAlgoOnCreateMpu() { + PutObjectRequest putObject = putObjectRequestBuilder().checksumCRC64NVME("val").build(); + assertThat(S3ChecksumUtils.checksumAlgorithmFromPutObjectRequest(putObject)) + .contains(ChecksumAlgorithm.CRC64_NVME); + } + + private PutObjectRequest.Builder putObjectRequestBuilder() { + return PutObjectRequest.builder().bucket("bucket").key("key"); + } + + private CreateMultipartUploadRequest.Builder createMultipartUploadRequestBuilder() { + return CreateMultipartUploadRequest.builder().bucket("bucket").key("key"); + } +} diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/SdkPojoConversionUtilsTest.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/SdkPojoConversionUtilsTest.java index 0f3ab5b5589f..3e93682113c5 100644 --- a/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/SdkPojoConversionUtilsTest.java +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/internal/multipart/SdkPojoConversionUtilsTest.java @@ -17,6 +17,7 @@ import static org.assertj.core.api.Assertions.assertThat; +import static software.amazon.awssdk.services.s3.internal.multipart.SdkPojoConversionUtils.PUT_OBJECT_REQUEST_TO_UPLOAD_PART_FIELDS_TO_IGNORE; import java.time.Instant; import java.util.ArrayList; @@ -37,6 +38,7 @@ import software.amazon.awssdk.http.SdkHttpFullResponse; import software.amazon.awssdk.services.s3.internal.multipart.SdkPojoConversionUtils; import software.amazon.awssdk.services.s3.model.AbortMultipartUploadRequest; +import software.amazon.awssdk.services.s3.model.ChecksumAlgorithm; import software.amazon.awssdk.services.s3.model.CompleteMultipartUploadRequest; import software.amazon.awssdk.services.s3.model.CompleteMultipartUploadResponse; import software.amazon.awssdk.services.s3.model.CompletedPart; @@ -152,9 +154,7 @@ void toUploadPartCopyRequest_shouldCopyProperties() { void toUploadPartRequest_shouldCopyProperties() { PutObjectRequest randomObject = randomPutObjectRequest(); UploadPartRequest convertedObject = SdkPojoConversionUtils.toUploadPartRequest(randomObject, 1, "id"); - Set fieldsToIgnore = new HashSet<>(Arrays.asList("ChecksumCRC32", "ChecksumSHA256", "ContentMD5", "ChecksumSHA1", - "ChecksumCRC32C")); - verifyFieldsAreCopied(randomObject, convertedObject, fieldsToIgnore, + verifyFieldsAreCopied(randomObject, convertedObject, PUT_OBJECT_REQUEST_TO_UPLOAD_PART_FIELDS_TO_IGNORE, PutObjectRequest.builder().sdkFields(), UploadPartRequest.builder().sdkFields()); assertThat(convertedObject.partNumber()).isEqualTo(1); @@ -184,11 +184,22 @@ void toCreateMultipartUploadRequest_putObjectRequest_shouldCopyProperties() { PutObjectRequest randomObject = randomPutObjectRequest(); CreateMultipartUploadRequest convertedObject = SdkPojoConversionUtils.toCreateMultipartUploadRequest(randomObject); Set fieldsToIgnore = new HashSet<>(); + // ChecksumAlgorithm is set in CreateMPU request to the checksum type of the value provided by the user, per TM spec + fieldsToIgnore.add("ChecksumAlgorithm"); verifyFieldsAreCopied(randomObject, convertedObject, fieldsToIgnore, PutObjectRequest.builder().sdkFields(), CreateMultipartUploadRequest.builder().sdkFields()); } + @Test + void toCreateMultipartUploadRequest_putObjectRequestWithChecksumAlgorithm_shouldHonor() { + PutObjectRequest randomObject = PutObjectRequest.builder() + .checksumAlgorithm(ChecksumAlgorithm.SHA256) + .checksumSHA1("123").build(); + CreateMultipartUploadRequest convertedObject = SdkPojoConversionUtils.toCreateMultipartUploadRequest(randomObject); + assertThat(convertedObject.checksumAlgorithm()).isEqualTo(ChecksumAlgorithm.SHA256); + } + @Test void toCompletedPart_putObject_shouldCopyProperties() { UploadPartResponse.Builder fromObject = UploadPartResponse.builder(); @@ -209,7 +220,7 @@ void toCompleteMultipartUploadRequest_putObject_shouldCopyProperties() { CompletedPart completedPart = CompletedPart.builder().partNumber(1).build(); parts[0] = completedPart; CompleteMultipartUploadRequest convertedObject = - SdkPojoConversionUtils.toCompleteMultipartUploadRequest(randomObject, "uploadId", parts); + SdkPojoConversionUtils.toCompleteMultipartUploadRequest(randomObject, "uploadId", parts, 99L); Set fieldsToIgnore = new HashSet<>(); verifyFieldsAreCopied(randomObject, convertedObject, fieldsToIgnore, @@ -217,6 +228,7 @@ void toCompleteMultipartUploadRequest_putObject_shouldCopyProperties() { CompleteMultipartUploadRequest.builder().sdkFields()); assertThat(convertedObject.uploadId()).isEqualTo("uploadId"); assertThat(convertedObject.multipartUpload().parts()).contains(completedPart); + assertThat(convertedObject.mpuObjectSize()).isEqualTo(99); } @Test @@ -279,6 +291,12 @@ private PutObjectRequest randomPutObjectRequest() { return builder.build(); } + private PutObjectRequest.Builder randomPutObjectRequestBuilder() { + PutObjectRequest.Builder builder = PutObjectRequest.builder(); + setFieldsToRandomValues(builder.sdkFields(), builder); + return builder; + } + private void populateFields(SdkPojo pojo) { setFieldsToRandomValues(pojo.sdkFields(), pojo); } @@ -330,4 +348,4 @@ private static Integer randomInteger() { private static long randomLong() { return RNG.nextLong(); } -} +} \ No newline at end of file diff --git a/services/s3/src/test/java/software/amazon/awssdk/services/s3/utils/CaptureChecksumValidationInterceptor.java b/services/s3/src/test/java/software/amazon/awssdk/services/s3/utils/CaptureChecksumValidationInterceptor.java index e751c103521a..8c322ef4ef04 100644 --- a/services/s3/src/test/java/software/amazon/awssdk/services/s3/utils/CaptureChecksumValidationInterceptor.java +++ b/services/s3/src/test/java/software/amazon/awssdk/services/s3/utils/CaptureChecksumValidationInterceptor.java @@ -15,7 +15,9 @@ package software.amazon.awssdk.services.s3.utils; -import software.amazon.awssdk.core.checksums.Algorithm; +import java.util.List; +import java.util.Map; +import software.amazon.awssdk.checksums.spi.ChecksumAlgorithm; import software.amazon.awssdk.core.checksums.ChecksumValidation; import software.amazon.awssdk.core.interceptor.Context; import software.amazon.awssdk.core.interceptor.ExecutionAttributes; @@ -23,7 +25,7 @@ import software.amazon.awssdk.core.interceptor.SdkExecutionAttribute; public class CaptureChecksumValidationInterceptor implements ExecutionInterceptor { - private Algorithm validationAlgorithm; + private ChecksumAlgorithm validationAlgorithm; private ChecksumValidation responseValidation; private String requestChecksumInTrailer; private String requestChecksumInHeader; @@ -31,12 +33,13 @@ public class CaptureChecksumValidationInterceptor implements ExecutionIntercepto private String responseTransferEncodingHeader; private String responseFlexibleChecksumHeader; private String contentEncoding; + private Map> requestHeaders; public String contentEncoding() { return contentEncoding; } - public Algorithm validationAlgorithm() { + public ChecksumAlgorithm validationAlgorithm() { return validationAlgorithm; } @@ -64,6 +67,10 @@ public String responseFlexibleChecksumHeader() { return responseFlexibleChecksumHeader; } + public Map> requestHeaders() { + return requestHeaders; + } + public void reset() { validationAlgorithm = null; responseValidation = null; @@ -76,6 +83,7 @@ public void reset() { @Override public void beforeTransmission(Context.BeforeTransmission context, ExecutionAttributes executionAttributes) { + requestHeaders = context.httpRequest().headers(); requestChecksumInTrailer = context.httpRequest().firstMatchingHeader("x-amz-trailer").orElse(null); requestChecksumInHeader = @@ -87,7 +95,7 @@ public void beforeTransmission(Context.BeforeTransmission context, ExecutionAttr @Override public void afterExecution(Context.AfterExecution context, ExecutionAttributes executionAttributes) { validationAlgorithm = - executionAttributes.getOptionalAttribute(SdkExecutionAttribute.HTTP_CHECKSUM_VALIDATION_ALGORITHM).orElse(null); + executionAttributes.getOptionalAttribute(SdkExecutionAttribute.HTTP_CHECKSUM_VALIDATION_ALGORITHM_V2).orElse(null); responseValidation = executionAttributes.getOptionalAttribute(SdkExecutionAttribute.HTTP_RESPONSE_CHECKSUM_VALIDATION).orElse(null); contentEncoding = String.join(",", context.httpRequest().matchingHeaders("content-encoding")); @@ -100,7 +108,7 @@ public void afterExecution(Context.AfterExecution context, ExecutionAttributes e @Override public void onExecutionFailure(Context.FailedExecution context, ExecutionAttributes executionAttributes) { validationAlgorithm = - executionAttributes.getOptionalAttribute(SdkExecutionAttribute.HTTP_CHECKSUM_VALIDATION_ALGORITHM).orElse(null); + executionAttributes.getOptionalAttribute(SdkExecutionAttribute.HTTP_CHECKSUM_VALIDATION_ALGORITHM_V2).orElse(null); responseValidation = executionAttributes.getOptionalAttribute(SdkExecutionAttribute.HTTP_RESPONSE_CHECKSUM_VALIDATION).orElse(null); } diff --git a/services/s3control/pom.xml b/services/s3control/pom.xml index 0146a5556ef7..085f1b00dd96 100644 --- a/services/s3control/pom.xml +++ b/services/s3control/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 s3control AWS Java SDK :: Services :: Amazon S3 Control diff --git a/services/s3control/src/it/java/software.amazon.awssdk.services.s3control/S3MrapIntegrationTest.java b/services/s3control/src/it/java/software.amazon.awssdk.services.s3control/S3MrapIntegrationTest.java index 3b59ea2c593c..d71c89c9c522 100644 --- a/services/s3control/src/it/java/software.amazon.awssdk.services.s3control/S3MrapIntegrationTest.java +++ b/services/s3control/src/it/java/software.amazon.awssdk.services.s3control/S3MrapIntegrationTest.java @@ -66,8 +66,9 @@ public class S3MrapIntegrationTest extends S3ControlIntegrationTestBase { private static final Logger log = Logger.loggerFor(S3MrapIntegrationTest.class); - private static final String SIGV4A_CHUNKED_PAYLOAD_SIGNING = "STREAMING-AWS4-ECDSA-P256-SHA256-PAYLOAD"; - private static final String SIGV4_CHUNKED_PAYLOAD_SIGNING = "STREAMING-AWS4-HMAC-SHA256-PAYLOAD"; + private static final String SIGV4A_CHUNKED_PAYLOAD_SIGNING = "STREAMING-AWS4-ECDSA-P256-SHA256-PAYLOAD-TRAILER"; + private static final String SIGV4_CHUNKED_PAYLOAD_SIGNING = "STREAMING-AWS4-HMAC-SHA256-PAYLOAD-TRAILER"; + private static final String STREAMING_UNSIGNED_PAYLOAD_TRAILER = "STREAMING-UNSIGNED-PAYLOAD-TRAILER"; private static final String UNSIGNED_PAYLOAD = "UNSIGNED-PAYLOAD"; private static final Region REGION = Region.US_WEST_2; private static String bucket; @@ -113,7 +114,7 @@ public static void setupFixture() { @ParameterizedTest(name = "{index}:key = {1}, {0}") @MethodSource("keys") public void when_callingMrapWithDifferentPaths_unsignedPayload_requestIsAccepted(String name, String key, String expected) { - putGetDeleteObjectMrap(s3Client, UNSIGNED_PAYLOAD, key, expected); + putGetDeleteObjectMrap(s3Client, STREAMING_UNSIGNED_PAYLOAD_TRAILER, key, expected); } @ParameterizedTest(name = "{index}:key = {1}, {0}") @@ -125,7 +126,7 @@ public void when_callingMrapWithDifferentPaths_signedPayload_requestIsAccepted(S @ParameterizedTest(name = "{index}:key = {1}, {0}") @MethodSource("keys") public void when_callingS3WithDifferentPaths_unsignedPayload_requestIsAccepted(String name, String key, String expected) { - putGetDeleteObjectStandard(s3Client, UNSIGNED_PAYLOAD, key, expected); + putGetDeleteObjectStandard(s3Client, STREAMING_UNSIGNED_PAYLOAD_TRAILER, key, expected); } @ParameterizedTest(name = "{index}:key = {1}, {0}") @@ -146,7 +147,7 @@ public void when_creatingPresignedMrapUrl_getRequestWorks() { String object = applyPresignedUrl(presignedGetObjectRequest, null); assertEquals(CONTENT, object); - verifySigv4aRequest(captureInterceptor.request(), UNSIGNED_PAYLOAD); + verifySigv4aRequest(captureInterceptor.request(), STREAMING_UNSIGNED_PAYLOAD_TRAILER); } public void putGetDeleteObjectMrap(S3Client testClient, String payloadSigningTag, String key, String expected) { diff --git a/services/s3outposts/pom.xml b/services/s3outposts/pom.xml index 4e31965ac634..21dd9d05a978 100644 --- a/services/s3outposts/pom.xml +++ b/services/s3outposts/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 s3outposts AWS Java SDK :: Services :: S3 Outposts diff --git a/services/s3tables/pom.xml b/services/s3tables/pom.xml index 7ed02fdd217a..25df65e957cc 100644 --- a/services/s3tables/pom.xml +++ b/services/s3tables/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 s3tables AWS Java SDK :: Services :: S3 Tables diff --git a/services/sagemaker/pom.xml b/services/sagemaker/pom.xml index b8842c4a42b0..37f833de2085 100644 --- a/services/sagemaker/pom.xml +++ b/services/sagemaker/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 sagemaker diff --git a/services/sagemakera2iruntime/pom.xml b/services/sagemakera2iruntime/pom.xml index 547184965eb6..076d59dd3084 100644 --- a/services/sagemakera2iruntime/pom.xml +++ b/services/sagemakera2iruntime/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 sagemakera2iruntime AWS Java SDK :: Services :: SageMaker A2I Runtime diff --git a/services/sagemakeredge/pom.xml b/services/sagemakeredge/pom.xml index 87e468430c6d..3b475ac2831b 100644 --- a/services/sagemakeredge/pom.xml +++ b/services/sagemakeredge/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 sagemakeredge AWS Java SDK :: Services :: Sagemaker Edge diff --git a/services/sagemakerfeaturestoreruntime/pom.xml b/services/sagemakerfeaturestoreruntime/pom.xml index 96d5a315a295..0d1c1963e857 100644 --- a/services/sagemakerfeaturestoreruntime/pom.xml +++ b/services/sagemakerfeaturestoreruntime/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 sagemakerfeaturestoreruntime AWS Java SDK :: Services :: Sage Maker Feature Store Runtime diff --git a/services/sagemakergeospatial/pom.xml b/services/sagemakergeospatial/pom.xml index a68ae6bcd828..c78430855595 100644 --- a/services/sagemakergeospatial/pom.xml +++ b/services/sagemakergeospatial/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 sagemakergeospatial AWS Java SDK :: Services :: Sage Maker Geospatial diff --git a/services/sagemakermetrics/pom.xml b/services/sagemakermetrics/pom.xml index eebb1f5d217a..36c621d7011b 100644 --- a/services/sagemakermetrics/pom.xml +++ b/services/sagemakermetrics/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 sagemakermetrics AWS Java SDK :: Services :: Sage Maker Metrics diff --git a/services/sagemakerruntime/pom.xml b/services/sagemakerruntime/pom.xml index 827911f50b92..1bd690e5eaa1 100644 --- a/services/sagemakerruntime/pom.xml +++ b/services/sagemakerruntime/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 sagemakerruntime AWS Java SDK :: Services :: SageMaker Runtime diff --git a/services/savingsplans/pom.xml b/services/savingsplans/pom.xml index ae69f85f5420..54d3fbcfaa83 100644 --- a/services/savingsplans/pom.xml +++ b/services/savingsplans/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 savingsplans AWS Java SDK :: Services :: Savingsplans diff --git a/services/scheduler/pom.xml b/services/scheduler/pom.xml index 663e28be68db..3cd6cabe0718 100644 --- a/services/scheduler/pom.xml +++ b/services/scheduler/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 scheduler AWS Java SDK :: Services :: Scheduler diff --git a/services/schemas/pom.xml b/services/schemas/pom.xml index 4de5e0b925b4..d3179c367720 100644 --- a/services/schemas/pom.xml +++ b/services/schemas/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 schemas AWS Java SDK :: Services :: Schemas diff --git a/services/secretsmanager/pom.xml b/services/secretsmanager/pom.xml index 55e2851fb46d..dd19bee56402 100644 --- a/services/secretsmanager/pom.xml +++ b/services/secretsmanager/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 secretsmanager AWS Java SDK :: Services :: AWS Secrets Manager diff --git a/services/securityhub/pom.xml b/services/securityhub/pom.xml index 71d6ecad8a34..97a3505da24a 100644 --- a/services/securityhub/pom.xml +++ b/services/securityhub/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 securityhub AWS Java SDK :: Services :: SecurityHub diff --git a/services/securityir/pom.xml b/services/securityir/pom.xml index c8066a885a2d..63b5e730c4bd 100644 --- a/services/securityir/pom.xml +++ b/services/securityir/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 securityir AWS Java SDK :: Services :: Security IR diff --git a/services/securityir/src/main/resources/codegen-resources/service-2.json b/services/securityir/src/main/resources/codegen-resources/service-2.json index 104941de8528..a41dafc46637 100644 --- a/services/securityir/src/main/resources/codegen-resources/service-2.json +++ b/services/securityir/src/main/resources/codegen-resources/service-2.json @@ -2244,7 +2244,7 @@ "UserAgent":{ "type":"string", "max":500, - "min":0 + "min":1 }, "ValidationException":{ "type":"structure", diff --git a/services/securitylake/pom.xml b/services/securitylake/pom.xml index 2429aab19282..549f36082651 100644 --- a/services/securitylake/pom.xml +++ b/services/securitylake/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 securitylake AWS Java SDK :: Services :: Security Lake diff --git a/services/serverlessapplicationrepository/pom.xml b/services/serverlessapplicationrepository/pom.xml index 8db23d04deee..f6f1dacb8995 100644 --- a/services/serverlessapplicationrepository/pom.xml +++ b/services/serverlessapplicationrepository/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 serverlessapplicationrepository diff --git a/services/servicecatalog/pom.xml b/services/servicecatalog/pom.xml index beb030fdfa68..a832733f9254 100644 --- a/services/servicecatalog/pom.xml +++ b/services/servicecatalog/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 servicecatalog AWS Java SDK :: Services :: AWS Service Catalog diff --git a/services/servicecatalogappregistry/pom.xml b/services/servicecatalogappregistry/pom.xml index 4a841029a2de..719936866869 100644 --- a/services/servicecatalogappregistry/pom.xml +++ b/services/servicecatalogappregistry/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 servicecatalogappregistry AWS Java SDK :: Services :: Service Catalog App Registry diff --git a/services/servicediscovery/pom.xml b/services/servicediscovery/pom.xml index 201744aa8ffd..59b43fd38f96 100644 --- a/services/servicediscovery/pom.xml +++ b/services/servicediscovery/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 servicediscovery diff --git a/services/servicequotas/pom.xml b/services/servicequotas/pom.xml index ed91dd14c282..6ce7e5729f95 100644 --- a/services/servicequotas/pom.xml +++ b/services/servicequotas/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 servicequotas AWS Java SDK :: Services :: Service Quotas diff --git a/services/ses/pom.xml b/services/ses/pom.xml index 0e5c71c01abe..14ed3d937c52 100644 --- a/services/ses/pom.xml +++ b/services/ses/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 ses AWS Java SDK :: Services :: Amazon SES diff --git a/services/sesv2/pom.xml b/services/sesv2/pom.xml index c16b4cbc4b31..917e2aec1d41 100644 --- a/services/sesv2/pom.xml +++ b/services/sesv2/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 sesv2 AWS Java SDK :: Services :: SESv2 diff --git a/services/sesv2/src/main/resources/codegen-resources/service-2.json b/services/sesv2/src/main/resources/codegen-resources/service-2.json index 6018ffc67ac8..f666cd6be541 100644 --- a/services/sesv2/src/main/resources/codegen-resources/service-2.json +++ b/services/sesv2/src/main/resources/codegen-resources/service-2.json @@ -6390,7 +6390,8 @@ "DKIM", "DMARC", "SPF", - "BIMI" + "BIMI", + "COMPLAINT" ] }, "RecommendationsList":{ diff --git a/services/sfn/pom.xml b/services/sfn/pom.xml index 4d01726d3ad0..f106b9ebb785 100644 --- a/services/sfn/pom.xml +++ b/services/sfn/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 sfn AWS Java SDK :: Services :: AWS Step Functions diff --git a/services/shield/pom.xml b/services/shield/pom.xml index 1a2dbc56aaec..16d9820cb4b5 100644 --- a/services/shield/pom.xml +++ b/services/shield/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 shield AWS Java SDK :: Services :: AWS Shield diff --git a/services/signer/pom.xml b/services/signer/pom.xml index 0e0a71d1b8c7..449d21f17d7f 100644 --- a/services/signer/pom.xml +++ b/services/signer/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 signer AWS Java SDK :: Services :: Signer diff --git a/services/simspaceweaver/pom.xml b/services/simspaceweaver/pom.xml index d6d76c02dff3..00f494536dc4 100644 --- a/services/simspaceweaver/pom.xml +++ b/services/simspaceweaver/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 simspaceweaver AWS Java SDK :: Services :: Sim Space Weaver diff --git a/services/sms/pom.xml b/services/sms/pom.xml index c2699f0b154e..36360ce15e48 100644 --- a/services/sms/pom.xml +++ b/services/sms/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 sms AWS Java SDK :: Services :: AWS Server Migration diff --git a/services/snowball/pom.xml b/services/snowball/pom.xml index fdfa9b725014..fedf9c401b40 100644 --- a/services/snowball/pom.xml +++ b/services/snowball/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 snowball AWS Java SDK :: Services :: Amazon Snowball diff --git a/services/snowdevicemanagement/pom.xml b/services/snowdevicemanagement/pom.xml index 3ed536dd42d6..3fcffdc4a2ff 100644 --- a/services/snowdevicemanagement/pom.xml +++ b/services/snowdevicemanagement/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 snowdevicemanagement AWS Java SDK :: Services :: Snow Device Management diff --git a/services/sns/pom.xml b/services/sns/pom.xml index 81d29cb5c9e6..b296791ebc76 100644 --- a/services/sns/pom.xml +++ b/services/sns/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 sns AWS Java SDK :: Services :: Amazon SNS diff --git a/services/socialmessaging/pom.xml b/services/socialmessaging/pom.xml index 0790890c5d22..d7a519e3f4e6 100644 --- a/services/socialmessaging/pom.xml +++ b/services/socialmessaging/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 socialmessaging AWS Java SDK :: Services :: Social Messaging diff --git a/services/sqs/pom.xml b/services/sqs/pom.xml index b5f2c7b40f17..3857791b86c8 100644 --- a/services/sqs/pom.xml +++ b/services/sqs/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 sqs AWS Java SDK :: Services :: Amazon SQS diff --git a/services/ssm/pom.xml b/services/ssm/pom.xml index 33d09a307430..ad571030ef86 100644 --- a/services/ssm/pom.xml +++ b/services/ssm/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 ssm AWS Java SDK :: Services :: AWS Simple Systems Management (SSM) diff --git a/services/ssmcontacts/pom.xml b/services/ssmcontacts/pom.xml index d5ff16e8695b..7c2ba10a5c21 100644 --- a/services/ssmcontacts/pom.xml +++ b/services/ssmcontacts/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 ssmcontacts AWS Java SDK :: Services :: SSM Contacts diff --git a/services/ssmincidents/pom.xml b/services/ssmincidents/pom.xml index 291ae313b2f2..bd918c8ef95b 100644 --- a/services/ssmincidents/pom.xml +++ b/services/ssmincidents/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 ssmincidents AWS Java SDK :: Services :: SSM Incidents diff --git a/services/ssmquicksetup/pom.xml b/services/ssmquicksetup/pom.xml index a1623abc8ec0..8affea2f8e8f 100644 --- a/services/ssmquicksetup/pom.xml +++ b/services/ssmquicksetup/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 ssmquicksetup AWS Java SDK :: Services :: SSM Quick Setup diff --git a/services/ssmsap/pom.xml b/services/ssmsap/pom.xml index 65812d40352f..e3e244097270 100644 --- a/services/ssmsap/pom.xml +++ b/services/ssmsap/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 ssmsap AWS Java SDK :: Services :: Ssm Sap diff --git a/services/sso/pom.xml b/services/sso/pom.xml index 66a3393c862f..20c669697f69 100644 --- a/services/sso/pom.xml +++ b/services/sso/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 sso AWS Java SDK :: Services :: SSO diff --git a/services/ssoadmin/pom.xml b/services/ssoadmin/pom.xml index f13f1c2d345c..0456235b55d4 100644 --- a/services/ssoadmin/pom.xml +++ b/services/ssoadmin/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 ssoadmin AWS Java SDK :: Services :: SSO Admin diff --git a/services/ssooidc/pom.xml b/services/ssooidc/pom.xml index 8f706e72890c..6ec47f022715 100644 --- a/services/ssooidc/pom.xml +++ b/services/ssooidc/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 ssooidc AWS Java SDK :: Services :: SSO OIDC diff --git a/services/storagegateway/pom.xml b/services/storagegateway/pom.xml index 8abd115a79d2..bdc200ee466d 100644 --- a/services/storagegateway/pom.xml +++ b/services/storagegateway/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 storagegateway AWS Java SDK :: Services :: AWS Storage Gateway diff --git a/services/sts/pom.xml b/services/sts/pom.xml index 191567eab34b..68a5cf03762d 100644 --- a/services/sts/pom.xml +++ b/services/sts/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 sts AWS Java SDK :: Services :: AWS STS diff --git a/services/supplychain/pom.xml b/services/supplychain/pom.xml index 0a39f9173a97..e374db350b9d 100644 --- a/services/supplychain/pom.xml +++ b/services/supplychain/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 supplychain AWS Java SDK :: Services :: Supply Chain diff --git a/services/support/pom.xml b/services/support/pom.xml index 2b7fbb19a4f4..1dc6c62d9777 100644 --- a/services/support/pom.xml +++ b/services/support/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 support AWS Java SDK :: Services :: AWS Support diff --git a/services/supportapp/pom.xml b/services/supportapp/pom.xml index b0cb8a87aaef..3952ea23bfa9 100644 --- a/services/supportapp/pom.xml +++ b/services/supportapp/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 supportapp AWS Java SDK :: Services :: Support App diff --git a/services/swf/pom.xml b/services/swf/pom.xml index 912b279153a8..c6e84f56f286 100644 --- a/services/swf/pom.xml +++ b/services/swf/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 swf AWS Java SDK :: Services :: Amazon SWF diff --git a/services/synthetics/pom.xml b/services/synthetics/pom.xml index 3f3bcf7f1381..5a2cc50d771b 100644 --- a/services/synthetics/pom.xml +++ b/services/synthetics/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 synthetics AWS Java SDK :: Services :: Synthetics diff --git a/services/taxsettings/pom.xml b/services/taxsettings/pom.xml index 8e0212a10f0f..47cd829097c7 100644 --- a/services/taxsettings/pom.xml +++ b/services/taxsettings/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 taxsettings AWS Java SDK :: Services :: Tax Settings diff --git a/services/textract/pom.xml b/services/textract/pom.xml index 3cf8d9b6d142..f55e02a9d555 100644 --- a/services/textract/pom.xml +++ b/services/textract/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 textract AWS Java SDK :: Services :: Textract diff --git a/services/timestreaminfluxdb/pom.xml b/services/timestreaminfluxdb/pom.xml index 164a4651fa42..6a6fc4c60a58 100644 --- a/services/timestreaminfluxdb/pom.xml +++ b/services/timestreaminfluxdb/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 timestreaminfluxdb AWS Java SDK :: Services :: Timestream Influx DB diff --git a/services/timestreamquery/pom.xml b/services/timestreamquery/pom.xml index e2a8ec35217d..c1433c1d72ce 100644 --- a/services/timestreamquery/pom.xml +++ b/services/timestreamquery/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 timestreamquery AWS Java SDK :: Services :: Timestream Query diff --git a/services/timestreamwrite/pom.xml b/services/timestreamwrite/pom.xml index 9c0297475baa..c63d27c8af91 100644 --- a/services/timestreamwrite/pom.xml +++ b/services/timestreamwrite/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 timestreamwrite AWS Java SDK :: Services :: Timestream Write diff --git a/services/tnb/pom.xml b/services/tnb/pom.xml index d3b7ab2f40c9..3629e27e13b3 100644 --- a/services/tnb/pom.xml +++ b/services/tnb/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 tnb AWS Java SDK :: Services :: Tnb diff --git a/services/transcribe/pom.xml b/services/transcribe/pom.xml index 1f9106a8ea48..59c1e5a3d45b 100644 --- a/services/transcribe/pom.xml +++ b/services/transcribe/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 transcribe AWS Java SDK :: Services :: Transcribe diff --git a/services/transcribestreaming/pom.xml b/services/transcribestreaming/pom.xml index 9f767bd1ee82..3437ca6f1596 100644 --- a/services/transcribestreaming/pom.xml +++ b/services/transcribestreaming/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 transcribestreaming AWS Java SDK :: Services :: AWS Transcribe Streaming diff --git a/services/transfer/pom.xml b/services/transfer/pom.xml index c2a8b8589423..c4c814c81672 100644 --- a/services/transfer/pom.xml +++ b/services/transfer/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 transfer AWS Java SDK :: Services :: Transfer diff --git a/services/translate/pom.xml b/services/translate/pom.xml index d54b097240c8..9cbd236b9eb8 100644 --- a/services/translate/pom.xml +++ b/services/translate/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 translate diff --git a/services/trustedadvisor/pom.xml b/services/trustedadvisor/pom.xml index 9fcbaa1ee2b8..62180d72d55c 100644 --- a/services/trustedadvisor/pom.xml +++ b/services/trustedadvisor/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 trustedadvisor AWS Java SDK :: Services :: Trusted Advisor diff --git a/services/verifiedpermissions/pom.xml b/services/verifiedpermissions/pom.xml index ca30ba424013..de83a4821ff8 100644 --- a/services/verifiedpermissions/pom.xml +++ b/services/verifiedpermissions/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 verifiedpermissions AWS Java SDK :: Services :: Verified Permissions diff --git a/services/voiceid/pom.xml b/services/voiceid/pom.xml index 989bda012db7..7bfbd7cff234 100644 --- a/services/voiceid/pom.xml +++ b/services/voiceid/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 voiceid AWS Java SDK :: Services :: Voice ID diff --git a/services/vpclattice/pom.xml b/services/vpclattice/pom.xml index 285288a57375..14a5dff3b8e5 100644 --- a/services/vpclattice/pom.xml +++ b/services/vpclattice/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 vpclattice AWS Java SDK :: Services :: VPC Lattice diff --git a/services/waf/pom.xml b/services/waf/pom.xml index 34e22f57f859..3581e835dcff 100644 --- a/services/waf/pom.xml +++ b/services/waf/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 waf AWS Java SDK :: Services :: AWS WAF diff --git a/services/wafv2/pom.xml b/services/wafv2/pom.xml index be49e994fa41..d830b3bbab14 100644 --- a/services/wafv2/pom.xml +++ b/services/wafv2/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 wafv2 AWS Java SDK :: Services :: WAFV2 diff --git a/services/wellarchitected/pom.xml b/services/wellarchitected/pom.xml index e23137d446d9..b20e14f4348e 100644 --- a/services/wellarchitected/pom.xml +++ b/services/wellarchitected/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 wellarchitected AWS Java SDK :: Services :: Well Architected diff --git a/services/wisdom/pom.xml b/services/wisdom/pom.xml index 08a55eb845dc..e25600cacc0d 100644 --- a/services/wisdom/pom.xml +++ b/services/wisdom/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 wisdom AWS Java SDK :: Services :: Wisdom diff --git a/services/workdocs/pom.xml b/services/workdocs/pom.xml index 77317de8a221..e8dd970023af 100644 --- a/services/workdocs/pom.xml +++ b/services/workdocs/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 workdocs AWS Java SDK :: Services :: Amazon WorkDocs diff --git a/services/workmail/pom.xml b/services/workmail/pom.xml index 7c221827f7f2..158768b26439 100644 --- a/services/workmail/pom.xml +++ b/services/workmail/pom.xml @@ -20,7 +20,7 @@ services software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 workmail diff --git a/services/workmailmessageflow/pom.xml b/services/workmailmessageflow/pom.xml index 5d6f593dfbf4..316264906cb4 100644 --- a/services/workmailmessageflow/pom.xml +++ b/services/workmailmessageflow/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 workmailmessageflow AWS Java SDK :: Services :: WorkMailMessageFlow diff --git a/services/workspaces/pom.xml b/services/workspaces/pom.xml index 655a1246b2bb..e924efeffe1f 100644 --- a/services/workspaces/pom.xml +++ b/services/workspaces/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 workspaces AWS Java SDK :: Services :: Amazon WorkSpaces diff --git a/services/workspaces/src/main/resources/codegen-resources/service-2.json b/services/workspaces/src/main/resources/codegen-resources/service-2.json index ebc4fada5dcc..c583e05a3142 100644 --- a/services/workspaces/src/main/resources/codegen-resources/service-2.json +++ b/services/workspaces/src/main/resources/codegen-resources/service-2.json @@ -2096,6 +2096,8 @@ "POWER", "GRAPHICS", "POWERPRO", + "GENERALPURPOSE_4XLARGE", + "GENERALPURPOSE_8XLARGE", "GRAPHICSPRO", "GRAPHICS_G4DN", "GRAPHICSPRO_G4DN" diff --git a/services/workspacesthinclient/pom.xml b/services/workspacesthinclient/pom.xml index c162fb2ed00b..0a919a3387a2 100644 --- a/services/workspacesthinclient/pom.xml +++ b/services/workspacesthinclient/pom.xml @@ -17,7 +17,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 workspacesthinclient AWS Java SDK :: Services :: Work Spaces Thin Client diff --git a/services/workspacesthinclient/src/main/resources/codegen-resources/service-2.json b/services/workspacesthinclient/src/main/resources/codegen-resources/service-2.json index 0442a76e609f..17834270b8d6 100644 --- a/services/workspacesthinclient/src/main/resources/codegen-resources/service-2.json +++ b/services/workspacesthinclient/src/main/resources/codegen-resources/service-2.json @@ -1136,6 +1136,7 @@ }, "MaintenanceWindow":{ "type":"structure", + "required":["type"], "members":{ "type":{ "shape":"MaintenanceWindowType", diff --git a/services/workspacesweb/pom.xml b/services/workspacesweb/pom.xml index 4b52e53f622e..70a164c17ee5 100644 --- a/services/workspacesweb/pom.xml +++ b/services/workspacesweb/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 workspacesweb AWS Java SDK :: Services :: Work Spaces Web diff --git a/services/xray/pom.xml b/services/xray/pom.xml index 2ab43b992168..5d3400e93c89 100644 --- a/services/xray/pom.xml +++ b/services/xray/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk services - 2.29.52 + 2.30.0 xray AWS Java SDK :: Services :: AWS X-Ray diff --git a/test/architecture-tests/archunit_store/18fc8858-1308-4d5d-b92d-87817d2fab53 b/test/architecture-tests/archunit_store/18fc8858-1308-4d5d-b92d-87817d2fab53 index e14541b8e3eb..00043c4de219 100644 --- a/test/architecture-tests/archunit_store/18fc8858-1308-4d5d-b92d-87817d2fab53 +++ b/test/architecture-tests/archunit_store/18fc8858-1308-4d5d-b92d-87817d2fab53 @@ -27,7 +27,6 @@ Class depends on an inte Class depends on an internal API from a different module (Class ) Class depends on an internal API from a different module (Class ) Class depends on an internal API from a different module (Class ) -Class depends on an internal API from a different module (Class ) Class depends on an internal API from a different module (Class ) Class depends on an internal API from a different module (Class ) Class depends on an internal API from a different module (Class ) @@ -65,10 +64,8 @@ Class depends on Class depends on an internal API from a different module (Class ) Class depends on an internal API from a different module (Class ) Class depends on an internal API from a different module (Class ) -Class depends on an internal API from a different module (Class ) Class depends on an internal API from a different module (Class ) Class depends on an internal API from a different module (Class ) -Class depends on an internal API from a different module (Class ) Class depends on an internal API from a different module (Class ) Class depends on an internal API from a different module (Class ) Class depends on an internal API from a different module (Class ) diff --git a/test/architecture-tests/archunit_store/c9da3398-6ad3-4ba7-9d7c-1b210e0c720f b/test/architecture-tests/archunit_store/c9da3398-6ad3-4ba7-9d7c-1b210e0c720f index 63fb363337d6..d3617d09cd1c 100644 --- a/test/architecture-tests/archunit_store/c9da3398-6ad3-4ba7-9d7c-1b210e0c720f +++ b/test/architecture-tests/archunit_store/c9da3398-6ad3-4ba7-9d7c-1b210e0c720f @@ -1,5 +1,4 @@ Class does not reside in any package ['..internal..'] in (HttpChecksumConstant.java:0) -Class does not reside in any package ['..internal..'] in (ChecksumSpecs.java:0) Class does not reside in any package ['..internal..'] in (Crc32CChecksum.java:0) Class does not reside in any package ['..internal..'] in (Crc32Checksum.java:0) Class does not reside in any package ['..internal..'] in (Md5Checksum.java:0) @@ -7,4 +6,3 @@ Class does not reside in an Class does not reside in any package ['..internal..'] in (Sha256Checksum.java:0) Class does not reside in any package ['..internal..'] in (EndpointDiscoveryProvider.java:0) Class does not reside in any package ['..internal..'] in (ProfileEndpointDiscoveryProvider.java:0) -Class does not reside in any package ['..internal..'] in (HttpChecksum.java:0) diff --git a/test/architecture-tests/pom.xml b/test/architecture-tests/pom.xml index 1aabc200a0d1..8f5168ef4990 100644 --- a/test/architecture-tests/pom.xml +++ b/test/architecture-tests/pom.xml @@ -21,7 +21,7 @@ aws-sdk-java-pom software.amazon.awssdk - 2.29.52 + 2.30.0 ../../pom.xml diff --git a/test/architecture-tests/src/test/java/software/amazon/awssdk/archtests/InternalApiBoundaryTest.java b/test/architecture-tests/src/test/java/software/amazon/awssdk/archtests/InternalApiBoundaryTest.java index 779234f47f30..d41cc995f4e5 100644 --- a/test/architecture-tests/src/test/java/software/amazon/awssdk/archtests/InternalApiBoundaryTest.java +++ b/test/architecture-tests/src/test/java/software/amazon/awssdk/archtests/InternalApiBoundaryTest.java @@ -37,6 +37,7 @@ import software.amazon.awssdk.core.internal.interceptor.trait.RequestCompression; import software.amazon.awssdk.core.internal.util.MetricUtils; import software.amazon.awssdk.core.internal.waiters.WaiterAttribute; +import software.amazon.awssdk.http.auth.aws.internal.signer.util.ChecksumUtil; import software.amazon.awssdk.utils.internal.EnumUtils; /** @@ -52,7 +53,7 @@ public class InternalApiBoundaryTest { */ private static final Set> ALLOWED_INTERNAL_API_ACROSS_MODULE_SUPPRESSION = new HashSet<>( Arrays.asList(WaiterAttribute.class, RequestCompression.class, RequestCompression.Builder.class, EnumUtils.class, - AwsServiceProtocol.class, AwsProtocolMetadata.class, MetricUtils.class)); + AwsServiceProtocol.class, AwsProtocolMetadata.class, MetricUtils.class, ChecksumUtil.class)); @Test void internalApi_shouldNotUsedAcrossModule() { diff --git a/test/auth-tests/pom.xml b/test/auth-tests/pom.xml index 702552053ad4..5c9722544219 100644 --- a/test/auth-tests/pom.xml +++ b/test/auth-tests/pom.xml @@ -20,7 +20,7 @@ aws-sdk-java-pom software.amazon.awssdk - 2.29.52 + 2.30.0 ../../pom.xml 4.0.0 diff --git a/test/bundle-logging-bridge-binding-test/pom.xml b/test/bundle-logging-bridge-binding-test/pom.xml index adedfa925928..4b5c9627481c 100644 --- a/test/bundle-logging-bridge-binding-test/pom.xml +++ b/test/bundle-logging-bridge-binding-test/pom.xml @@ -20,7 +20,7 @@ aws-sdk-java-pom software.amazon.awssdk - 2.29.52 + 2.30.0 ../../pom.xml 4.0.0 diff --git a/test/bundle-shading-tests/pom.xml b/test/bundle-shading-tests/pom.xml index 10c850871186..9f9d931f5188 100644 --- a/test/bundle-shading-tests/pom.xml +++ b/test/bundle-shading-tests/pom.xml @@ -20,7 +20,7 @@ aws-sdk-java-pom software.amazon.awssdk - 2.29.52 + 2.30.0 ../../pom.xml 4.0.0 diff --git a/test/codegen-generated-classes-test/pom.xml b/test/codegen-generated-classes-test/pom.xml index b22ed6b995c2..12ff5504696e 100644 --- a/test/codegen-generated-classes-test/pom.xml +++ b/test/codegen-generated-classes-test/pom.xml @@ -21,7 +21,7 @@ aws-sdk-java-pom software.amazon.awssdk - 2.29.52 + 2.30.0 ../../pom.xml @@ -157,6 +157,12 @@ junit-jupiter test + + software.amazon.awssdk.crt + aws-crt + ${awscrt.version} + test + org.junit.vintage junit-vintage-engine diff --git a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/customresponsemetadata/service-2.json b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/customresponsemetadata/service-2.json index e02de61903db..3893814d0b25 100644 --- a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/customresponsemetadata/service-2.json +++ b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/customresponsemetadata/service-2.json @@ -242,7 +242,7 @@ "requestChecksumRequired" : true, "requestAlgorithmMember": "ChecksumAlgorithm", "requestValidationModeMember" : "ChecksumMode", - "responseAlgorithms": ["crc32", "crc32c", "sha256", "sha1"] + "responseAlgorithms": ["crc64nvme","crc32", "crc32c", "sha256", "sha1"] } }, "StreamingInputOperation":{ @@ -294,9 +294,7 @@ "requestUri":"/" }, "input":{"shape":"ChecksumStructureWithStreaming"}, - "output":{"shape":"ChecksumStructureWithStreaming"}, "httpChecksum" : { - "requestChecksumRequired": true, "requestAlgorithmMember": "ChecksumAlgorithm" } }, @@ -335,7 +333,7 @@ "output":{"shape":"ChecksumStructureWithStreaming"}, "httpChecksum" : { "requestValidationModeMember": "ChecksumMode", - "responseAlgorithms": ["CRC32C", "CRC32", "SHA1", "SHA256"] + "responseAlgorithms": ["CRC64NVME","CRC32C", "CRC32", "SHA1", "SHA256"] } }, "GetOperationWithMapEndpointParam":{ @@ -359,7 +357,7 @@ "requestChecksumRequired": true, "requestAlgorithmMember": "ChecksumAlgorithm", "requestValidationModeMember": "ChecksumMode", - "responseAlgorithms": ["CRC32C", "CRC32", "SHA1", "SHA256"] + "responseAlgorithms": ["CRC64NVME","CRC32C", "CRC32", "SHA1", "SHA256"] } }, "QueryParameterOperation":{ @@ -981,7 +979,8 @@ "CRC32", "CRC32C", "SHA1", - "SHA256" + "SHA256", + "CRC64NVME" ] }, "ChecksumMode":{ @@ -1009,7 +1008,7 @@ "ChecksumAlgorithm":{ "shape":"ChecksumAlgorithm", "location":"header", - "locationName":"x-amz-checksum-algorithm" + "locationName":"x-amz-sdk-checksum-algorithm" } }, "payload":"Body" @@ -1032,7 +1031,7 @@ "ChecksumAlgorithm":{ "shape":"ChecksumAlgorithm", "location":"header", - "locationName":"x-amz-checksum-algorithm" + "locationName":"x-amz-sdk-checksum-algorithm" } } }, diff --git a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/serviceconfig/service-2.json b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/serviceconfig/service-2.json index 9d49f50b6809..d661cbaec87d 100644 --- a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/serviceconfig/service-2.json +++ b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/serviceconfig/service-2.json @@ -1009,7 +1009,7 @@ "ChecksumAlgorithm":{ "shape":"ChecksumAlgorithm", "location":"header", - "locationName":"x-amz-checksum-algorithm" + "locationName":"x-amz-sdk-checksum-algorithm" } }, "payload":"Body" @@ -1032,7 +1032,7 @@ "ChecksumAlgorithm":{ "shape":"ChecksumAlgorithm", "location":"header", - "locationName":"x-amz-checksum-algorithm" + "locationName":"x-amz-sdk-checksum-algorithm" } } }, diff --git a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/xml/service-2.json b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/xml/service-2.json index a61dde243708..089a698c8638 100644 --- a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/xml/service-2.json +++ b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/xml/service-2.json @@ -794,7 +794,7 @@ "ChecksumAlgorithm":{ "shape":"ChecksumAlgorithm", "location":"header", - "locationName":"x-amz-checksum-algorithm" + "locationName":"x-amz-sdk-checksum-algorithm" } }, "payload":"Body" @@ -817,7 +817,7 @@ "ChecksumAlgorithm":{ "shape":"ChecksumAlgorithm", "location":"header", - "locationName":"x-amz-checksum-algorithm" + "locationName":"x-amz-sdk-checksum-algorithm" } } }, diff --git a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/xmlinternalplugins/service-2.json b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/xmlinternalplugins/service-2.json index d456fd03d3c3..3622c92de695 100644 --- a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/xmlinternalplugins/service-2.json +++ b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/xmlinternalplugins/service-2.json @@ -794,7 +794,7 @@ "ChecksumAlgorithm":{ "shape":"ChecksumAlgorithm", "location":"header", - "locationName":"x-amz-checksum-algorithm" + "locationName":"x-amz-sdk-checksum-algorithm" } }, "payload":"Body" @@ -817,7 +817,7 @@ "ChecksumAlgorithm":{ "shape":"ChecksumAlgorithm", "location":"header", - "locationName":"x-amz-checksum-algorithm" + "locationName":"x-amz-sdk-checksum-algorithm" } } }, diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/AsyncRequestBodyFlexibleChecksumInTrailerTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/AsyncRequestBodyFlexibleChecksumInTrailerTest.java index d419b062fa1d..71600ce2fa94 100644 --- a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/AsyncRequestBodyFlexibleChecksumInTrailerTest.java +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/AsyncRequestBodyFlexibleChecksumInTrailerTest.java @@ -116,8 +116,7 @@ public void cleanUp() { public void asyncStreaming_NoSigner_shouldContainChecksum_fromInterceptors() { stubResponseWithHeaders(); asyncClient.putOperationWithChecksum(b -> b.checksumAlgorithm(ChecksumAlgorithm.CRC32), AsyncRequestBody.fromString( - "abc"), - AsyncResponseTransformer.toBytes()).join(); + "abc")).join(); //payload would in json form as "{"StringMember":"foo"}x-amz-checksum-crc32:tcUDMQ==[\r][\n]" verifyHeadersForPutRequest("44", "3", "x-amz-checksum-crc32"); verify(putRequestedFor(anyUrl()).withHeader("Content-Encoding", equalTo("aws-chunked"))); @@ -133,8 +132,7 @@ public void asyncStreaming_NoSigner_shouldContainChecksum_fromInterceptors_withC stubResponseWithHeaders(); asyncClient.putOperationWithChecksum(b -> b.checksumAlgorithm(ChecksumAlgorithm.CRC32).contentEncoding("deflate"), AsyncRequestBody.fromString( - "abc"), - AsyncResponseTransformer.toBytes()).join(); + "abc")).join(); //payload would in json form as "{"StringMember":"foo"}x-amz-checksum-crc32:tcUDMQ==[\r][\n]" verifyHeadersForPutRequest("44", "3", "x-amz-checksum-crc32"); verify(putRequestedFor(anyUrl()).withHeader("Content-Encoding", equalTo("aws-chunked"))); @@ -157,8 +155,7 @@ public void asyncStreaming_withRetry_NoSigner_shouldContainChecksum_fromIntercep + "x-amz-checksum-sha256:ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0=" + CRLF + CRLF; asyncClient.putOperationWithChecksum(b -> b.checksumAlgorithm(ChecksumAlgorithm.SHA256), AsyncRequestBody.fromString( - "abc"), - AsyncResponseTransformer.toBytes()).join(); + "abc")).join(); List requests = getRecordedRequests(); assertThat(requests.size()).isEqualTo(2); assertThat(requests.get(0).getBody()).contains(expectedRequestBody.getBytes()); @@ -183,8 +180,7 @@ public void asyncStreaming_FromAsyncRequestBody_VariableChunkSize_NoSigner_addsC asyncClient.putOperationWithChecksum(b -> b.checksumAlgorithm(ChecksumAlgorithm.CRC32), FileAsyncRequestBody.builder().path(randomFileOfFixedLength.toPath()) .chunkSizeInBytes(16 * KB) - .build(), - AsyncResponseTransformer.toBytes()).join(); + .build()).join(); verifyHeadersForPutRequest("37948", "37888", "x-amz-checksum-crc32"); verify(putRequestedFor(anyUrl()).withRequestBody( containing( @@ -207,8 +203,7 @@ public void asyncStreaming_withRetry_FromAsyncRequestBody_VariableChunkSize_NoSi asyncClient.putOperationWithChecksum(b -> b.checksumAlgorithm(ChecksumAlgorithm.CRC32), FileAsyncRequestBody.builder().path(randomFileOfFixedLength.toPath()) .chunkSizeInBytes(16 * KB) - .build(), - AsyncResponseTransformer.toBytes()).join(); + .build()).join(); verifyHeadersForPutRequest("37948", "37888", "x-amz-checksum-crc32"); verify(putRequestedFor(anyUrl()).withRequestBody( containing( diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/HttpChecksumCalculationTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/HttpChecksumCalculationTest.java new file mode 100644 index 000000000000..dee479590e67 --- /dev/null +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/HttpChecksumCalculationTest.java @@ -0,0 +1,272 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.services; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static software.amazon.awssdk.auth.signer.S3SignerExecutionAttribute.ENABLE_CHUNKED_ENCODING; +import static software.amazon.awssdk.core.HttpChecksumConstant.HTTP_CHECKSUM_HEADER_PREFIX; + +import io.reactivex.Flowable; +import java.io.IOException; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.ArgumentCaptor; +import org.mockito.Mockito; +import software.amazon.awssdk.auth.credentials.AnonymousCredentialsProvider; +import software.amazon.awssdk.core.HttpChecksumConstant; +import software.amazon.awssdk.core.SdkRequest; +import software.amazon.awssdk.core.async.AsyncRequestBody; +import software.amazon.awssdk.core.checksums.RequestChecksumCalculation; +import software.amazon.awssdk.core.interceptor.Context; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; +import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; +import software.amazon.awssdk.core.sync.RequestBody; +import software.amazon.awssdk.http.ExecutableHttpRequest; +import software.amazon.awssdk.http.HttpExecuteRequest; +import software.amazon.awssdk.http.HttpExecuteResponse; +import software.amazon.awssdk.http.SdkHttpClient; +import software.amazon.awssdk.http.SdkHttpFullResponse; +import software.amazon.awssdk.http.SdkHttpRequest; +import software.amazon.awssdk.http.SdkHttpResponse; +import software.amazon.awssdk.http.async.AsyncExecuteRequest; +import software.amazon.awssdk.http.async.SdkAsyncHttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.protocolrestjson.ProtocolRestJsonAsyncClient; +import software.amazon.awssdk.services.protocolrestjson.ProtocolRestJsonAsyncClientBuilder; +import software.amazon.awssdk.services.protocolrestjson.ProtocolRestJsonClient; +import software.amazon.awssdk.services.protocolrestjson.ProtocolRestJsonClientBuilder; +import software.amazon.awssdk.services.protocolrestjson.model.ChecksumAlgorithm; +import software.amazon.awssdk.services.protocolrestjson.model.OperationWithCustomRequestChecksumRequest; +import software.amazon.awssdk.services.protocolrestjson.model.PutOperationWithChecksumRequest; + +/** + * Verify HTTP checksum calculation behavior with different requestChecksumCalculation settings. + */ +public class HttpChecksumCalculationTest { + private SdkHttpClient httpClient; + private SdkAsyncHttpClient httpAsyncClient; + + private ProtocolRestJsonClientBuilder initializeSync(RequestChecksumCalculation calculation) { + return ProtocolRestJsonClient.builder().httpClient(httpClient) + .credentialsProvider(AnonymousCredentialsProvider.create()) + .requestChecksumCalculation(calculation) + .overrideConfiguration( + // // TODO(sra-identity-and-auth): we should remove these + // // overrides once we set up codegen to set chunk-encoding to true + // // for requests that are streaming and checksum-enabled + o -> o.addExecutionInterceptor(new EnableChunkedEncodingInterceptor())) + .region(Region.US_WEST_2); + } + + private ProtocolRestJsonAsyncClientBuilder initializeAsync(RequestChecksumCalculation calculation) { + return ProtocolRestJsonAsyncClient.builder().httpClient(httpAsyncClient) + .credentialsProvider(AnonymousCredentialsProvider.create()) + .requestChecksumCalculation(calculation) + .overrideConfiguration( + // TODO(sra-identity-and-auth): we should remove these + // overrides once we set up codegen to set chunk-encoding to true + // for requests that are streaming and checksum-enabled + o -> o.addExecutionInterceptor(new EnableChunkedEncodingInterceptor())) + .region(Region.US_WEST_2); + } + + private static final class EnableChunkedEncodingInterceptor implements ExecutionInterceptor { + public void beforeExecution(Context.BeforeExecution context, ExecutionAttributes executionAttributes) { + SdkRequest request = context.request(); + + if (request instanceof PutOperationWithChecksumRequest) { + executionAttributes.putAttributeIfAbsent(ENABLE_CHUNKED_ENCODING, true); + } + } + } + + @BeforeEach + public void setup() throws IOException { + httpClient = Mockito.mock(SdkHttpClient.class); + httpAsyncClient = Mockito.mock(SdkAsyncHttpClient.class); + + SdkHttpFullResponse successfulHttpResponse = SdkHttpResponse.builder() + .statusCode(200) + .putHeader("Content-Length", "0") + .build(); + + ExecutableHttpRequest request = Mockito.mock(ExecutableHttpRequest.class); + Mockito.when(request.call()).thenReturn(HttpExecuteResponse.builder() + .response(successfulHttpResponse) + .build()); + Mockito.when(httpClient.prepareRequest(any())).thenReturn(request); + + Mockito.when(httpAsyncClient.execute(any())).thenAnswer(invocation -> { + AsyncExecuteRequest asyncExecuteRequest = invocation.getArgument(0, AsyncExecuteRequest.class); + asyncExecuteRequest.responseHandler().onHeaders(successfulHttpResponse); + asyncExecuteRequest.responseHandler().onStream(Flowable.empty()); + return CompletableFuture.completedFuture(null); + }); + } + + public static Stream streamingInputChecksumCalculationParams() { + return Stream.of(Arguments.of(RequestChecksumCalculation.WHEN_SUPPORTED, null, "x-amz-checksum-crc32", + "requestChecksumWhenSupported_checksumAlgorithmNotProvided_shouldAddCrc32ChecksumTrailerByDefault"), + + Arguments.of(RequestChecksumCalculation.WHEN_SUPPORTED, ChecksumAlgorithm.SHA1, + "x-amz-checksum-sha1", + "requestChecksumWhenSupported_checksumAlgorithmProvided_shouldHonor"), + + Arguments.of(RequestChecksumCalculation.WHEN_REQUIRED, null, null, + "requestChecksumWhenRequired_checksumAlgorithmNotProvided_shouldNotAddChecksum"), + + Arguments.of(RequestChecksumCalculation.WHEN_REQUIRED, ChecksumAlgorithm.CRC32_C, + "x-amz-checksum-crc32c", + "requestChecksumWhenRequired_checksumAlgorithmProvided_shouldAddChecksumTrailer")); + } + + public static Stream checksumInHeaderRequiredParams() { + return Stream.of(Arguments.of(RequestChecksumCalculation.WHEN_SUPPORTED, null, "x-amz-checksum-crc32", "o6a/Qw==", + "requestChecksumWhenSupported_checksumAlgorithmNotProvided_shouldAddCrc32ChecksumTrailerByDefault"), + + Arguments.of(RequestChecksumCalculation.WHEN_SUPPORTED, ChecksumAlgorithm.SHA1, + "x-amz-checksum-sha1", "vyGp6PvFo4RvsFtPoIWeCReyIC8=", + "requestChecksumWhenSupported_checksumAlgorithmProvided_shouldHonor"), + + Arguments.of(RequestChecksumCalculation.WHEN_REQUIRED, null, "x-amz-checksum-crc32", "o6a/Qw==", + "requestChecksumWhenRequired_checksumAlgorithmNotProvided_shouldAddChecksum"), + + Arguments.of(RequestChecksumCalculation.WHEN_REQUIRED, ChecksumAlgorithm.CRC32_C, + "x-amz-checksum-crc32c", "KXvQqg==", + "requestChecksumWhenRequired_checksumAlgorithmProvided_shouldAddChecksum")); + } + + @ParameterizedTest(name = "{index} {3}") + @MethodSource("streamingInputChecksumCalculationParams") + public void syncStreamingInput_checksumCalculation(RequestChecksumCalculation requestChecksumCalculation, + ChecksumAlgorithm checksumAlgorithm, + String expectedTrailer, + String description) { + + try (ProtocolRestJsonClient client = initializeSync(requestChecksumCalculation).build()) { + client.putOperationWithChecksum(PutOperationWithChecksumRequest.builder() + .checksumAlgorithm(checksumAlgorithm) + .build(), + RequestBody.fromString("Hello world")); + + SdkHttpRequest request = getSyncRequest(); + validateChecksumTrailerHeader(expectedTrailer, request); + } + } + + @ParameterizedTest(name = "{index} {3}") + @MethodSource("streamingInputChecksumCalculationParams") + public void asyncStreamingInput_checksumCalculation(RequestChecksumCalculation requestChecksumCalculation, + ChecksumAlgorithm checksumAlgorithm, + String expectedTrailer, + String description) { + + try (ProtocolRestJsonAsyncClient client = initializeAsync(requestChecksumCalculation).build()) { + client.putOperationWithChecksum(PutOperationWithChecksumRequest.builder() + .checksumAlgorithm(checksumAlgorithm) + .build(), + AsyncRequestBody.fromString("Hello world")); + + SdkHttpRequest request = getAsyncRequest(); + validateChecksumTrailerHeader(expectedTrailer, request); + } + } + + @ParameterizedTest(name = "{index} {4}") + @MethodSource("checksumInHeaderRequiredParams") + public void syncChecksumInHeaderRequired_checksumCalculation(RequestChecksumCalculation requestChecksumCalculation, + ChecksumAlgorithm checksumAlgorithm, + String expectedChecksumHeader, + String expectedChecksumValue, + String description) { + + try (ProtocolRestJsonClient client = initializeSync(requestChecksumCalculation).build()) { + client.operationWithCustomRequestChecksum(OperationWithCustomRequestChecksumRequest.builder() + .checksumAlgorithm(checksumAlgorithm) + .build()); + SdkHttpRequest request = getSyncRequest(); + validateChecksumHeader(expectedChecksumHeader, expectedChecksumValue, request); + } + } + + @ParameterizedTest(name = "{index} {4}") + @MethodSource("checksumInHeaderRequiredParams") + public void asyncChecksumInHeaderRequired_checksumCalculation(RequestChecksumCalculation requestChecksumCalculation, + ChecksumAlgorithm checksumAlgorithm, + String expectedChecksumHeader, + String expectedChecksumValue, + String description) { + + try (ProtocolRestJsonAsyncClient client = initializeAsync(requestChecksumCalculation).build()) { + client.operationWithCustomRequestChecksum(OperationWithCustomRequestChecksumRequest.builder() + .checksumAlgorithm(checksumAlgorithm) + .build()).join(); + SdkHttpRequest request = getAsyncRequest(); + validateChecksumHeader(expectedChecksumHeader, expectedChecksumValue, request); + } + } + + private static void validateChecksumHeader(String expectedChecksumHeader, + String expectedChecksumValue, + SdkHttpRequest request) { + assertThat(request.firstMatchingHeader(HttpChecksumConstant.X_AMZ_TRAILER)).isEmpty(); + List checksumHeaders = request.headers() + .keySet() + .stream() + .filter(header -> header.contains(HTTP_CHECKSUM_HEADER_PREFIX) && !header.equals( + "x-amz-checksum-algorithm")) + .collect(Collectors.toList()); + + if (expectedChecksumHeader != null) { + assertThat(checksumHeaders).containsExactly(expectedChecksumHeader); + assertThat(request.firstMatchingHeader(expectedChecksumHeader)).contains(expectedChecksumValue); + assertThat(request.firstMatchingHeader("x-amz-sdk-checksum-algorithm")).isNotEmpty(); + } else { + assertThat(checksumHeaders).isEmpty(); + assertThat(request.firstMatchingHeader("x-amz-sdk-checksum-algorithm")).isEmpty(); + } + } + + private static void validateChecksumTrailerHeader(String expectedTrailer, SdkHttpRequest request) { + if (expectedTrailer != null) { + assertThat(request.firstMatchingHeader(HttpChecksumConstant.X_AMZ_TRAILER)).contains(expectedTrailer); + assertThat(request.firstMatchingHeader("x-amz-sdk-checksum-algorithm")).isNotEmpty(); + assertThat(request.firstMatchingHeader("x-amz-content-sha256")).contains("STREAMING-UNSIGNED-PAYLOAD-TRAILER"); + } else { + assertThat(request.firstMatchingHeader(HttpChecksumConstant.X_AMZ_TRAILER)).isEmpty(); + assertThat(request.firstMatchingHeader("x-amz-sdk-checksum-algorithm")).isEmpty(); + } + } + + private SdkHttpRequest getSyncRequest() { + ArgumentCaptor captor = ArgumentCaptor.forClass(HttpExecuteRequest.class); + Mockito.verify(httpClient).prepareRequest(captor.capture()); + return captor.getValue().httpRequest(); + } + + private SdkHttpRequest getAsyncRequest() { + ArgumentCaptor captor = ArgumentCaptor.forClass(AsyncExecuteRequest.class); + Mockito.verify(httpAsyncClient).execute(captor.capture()); + return captor.getValue().request(); + } +} \ No newline at end of file diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/HttpChecksumInHeaderTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/HttpChecksumInHeaderTest.java index 659bdf801c10..f24f7f35d1c6 100644 --- a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/HttpChecksumInHeaderTest.java +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/HttpChecksumInHeaderTest.java @@ -51,7 +51,7 @@ /** * Verify that the "HttpChecksum" C2J trait results in a valid checksum of the payload being included in the HTTP - * request. + * request for different protocols. */ public class HttpChecksumInHeaderTest { @@ -119,8 +119,7 @@ public void sync_xml_nonStreaming_unsignedPayload_with_Sha1_in_header() { .checksumAlgorithm(software.amazon.awssdk.services.protocolrestxml.model.ChecksumAlgorithm.SHA1).build()); assertThat(getSyncRequest().firstMatchingHeader("Content-MD5")).isNotPresent(); //Note that content will be of form "Hello world" - // TODO(sra-identity-and-auth): Uncomment once sra is set to true - // assertThat(getSyncRequest().firstMatchingHeader("x-amz-checksum-sha1")).hasValue("FB/utBbwFLbIIt5ul3Ojuy5dKgU="); + assertThat(getSyncRequest().firstMatchingHeader("x-amz-checksum-sha1")).hasValue("FB/utBbwFLbIIt5ul3Ojuy5dKgU="); } @Test @@ -129,8 +128,7 @@ public void sync_xml_nonStreaming_unsignedEmptyPayload_with_Sha1_in_header() { assertThat(getSyncRequest().firstMatchingHeader("Content-MD5")).isNotPresent(); //Note that content will be of form "Hello world" - // TODO(sra-identity-and-auth): Uncomment once sra is set to true - // assertThat(getSyncRequest().firstMatchingHeader("x-amz-checksum-sha1")).hasValue("2jmj7l5rSw0yVb/vlWAYkK/YBwk="); + assertThat(getSyncRequest().firstMatchingHeader("x-amz-checksum-sha1")).hasValue("2jmj7l5rSw0yVb/vlWAYkK/YBwk="); } @Test @@ -148,8 +146,7 @@ public void aync_xml_nonStreaming_unsignedEmptyPayload_with_Sha1_in_header() { assertThat(getAsyncRequest().firstMatchingHeader("Content-MD5")).isNotPresent(); //Note that content will be of form Hello world" - // TODO(sra-identity-and-auth): Uncomment once sra is set to true - // assertThat(getAsyncRequest().firstMatchingHeader("x-amz-checksum-sha1")).hasValue("2jmj7l5rSw0yVb/vlWAYkK/YBwk="); + assertThat(getAsyncRequest().firstMatchingHeader("x-amz-checksum-sha1")).hasValue("2jmj7l5rSw0yVb/vlWAYkK/YBwk="); } private SdkHttpRequest getSyncRequest() { diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/HttpChecksumRequiredTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/HttpChecksumRequiredTest.java index cc4f6ad7a357..511e3258e6a5 100644 --- a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/HttpChecksumRequiredTest.java +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/HttpChecksumRequiredTest.java @@ -106,53 +106,64 @@ public void setup() throws IOException { @Test public void syncJsonSupportsChecksumRequiredTrait() { jsonClient.operationWithRequiredChecksum(r -> r.stringMember("foo")); - assertThat(getSyncRequest().firstMatchingHeader("Content-MD5")).hasValue("g8VCvPTPCMoU01rBlBVt9w=="); + assertThat(getSyncRequest().firstMatchingHeader("Content-MD5")).isEmpty(); + assertThat(getSyncRequest().firstMatchingHeader("x-amz-checksum-crc32")).hasValue("tcUDMQ=="); } @Test public void syncStreamingInputJsonSupportsChecksumRequiredTrait() { jsonClient.streamingInputOperationWithRequiredChecksum(r -> {}, RequestBody.fromString("foo")); - assertThat(getSyncRequest().firstMatchingHeader("Content-MD5")).hasValue("rL0Y20zC+Fzt72VPzMSk2A=="); + assertThat(getSyncRequest().firstMatchingHeader("Content-MD5")).isEmpty(); + assertThat(getSyncRequest().firstMatchingHeader("x-amz-checksum-crc32")).hasValue("jHNlIQ=="); } @Test public void syncStreamingInputXmlSupportsChecksumRequiredTrait() { xmlClient.streamingInputOperationWithRequiredChecksum(r -> {}, RequestBody.fromString("foo")); - assertThat(getSyncRequest().firstMatchingHeader("Content-MD5")).hasValue("rL0Y20zC+Fzt72VPzMSk2A=="); + assertThat(getSyncRequest().firstMatchingHeader("Content-MD5")).isEmpty(); + assertThat(getSyncRequest().firstMatchingHeader("x-amz-checksum-crc32")).hasValue("jHNlIQ=="); } @Test public void syncXmlSupportsChecksumRequiredTrait() { xmlClient.operationWithRequiredChecksum(r -> r.stringMember("foo")); - assertThat(getSyncRequest().firstMatchingHeader("Content-MD5")).hasValue("vqm481l+Lv0zEvdu+duE6Q=="); + assertThat(getSyncRequest().firstMatchingHeader("Content-MD5")).isEmpty(); + assertThat(getSyncRequest().firstMatchingHeader("x-amz-checksum-crc32")).hasValue("YP74zg=="); } @Test public void asyncJsonSupportsChecksumRequiredTrait() { jsonAsyncClient.operationWithRequiredChecksum(r -> r.stringMember("foo")).join(); - assertThat(getAsyncRequest().firstMatchingHeader("Content-MD5")).hasValue("g8VCvPTPCMoU01rBlBVt9w=="); + assertThat(getAsyncRequest().firstMatchingHeader("Content-MD5")).isEmpty(); + assertThat(getAsyncRequest().firstMatchingHeader("x-amz-checksum-crc32")).hasValue("tcUDMQ=="); } @Test public void asyncXmlSupportsChecksumRequiredTrait() { xmlAsyncClient.operationWithRequiredChecksum(r -> r.stringMember("foo")).join(); - assertThat(getAsyncRequest().firstMatchingHeader("Content-MD5")).hasValue("vqm481l+Lv0zEvdu+duE6Q=="); + assertThat(getAsyncRequest().firstMatchingHeader("Content-MD5")).isEmpty(); + assertThat(getAsyncRequest().firstMatchingHeader("x-amz-checksum-crc32")).hasValue("YP74zg=="); } - @Test(expected = CompletionException.class) + @Test public void asyncStreamingInputJsonFailsWithChecksumRequiredTrait() { jsonAsyncClient.streamingInputOperationWithRequiredChecksum(r -> {}, AsyncRequestBody.fromString("foo")).join(); + assertThat(getAsyncRequest().firstMatchingHeader("Content-MD5")).isNotPresent(); + assertThat(getAsyncRequest().firstMatchingHeader("x-amz-checksum-crc32")).hasValue("jHNlIQ=="); } - @Test(expected = CompletionException.class) + @Test public void asyncStreamingInputXmlFailsWithChecksumRequiredTrait() { xmlAsyncClient.streamingInputOperationWithRequiredChecksum(r -> {}, AsyncRequestBody.fromString("foo")).join(); + assertThat(getAsyncRequest().firstMatchingHeader("Content-MD5")).isNotPresent(); + assertThat(getAsyncRequest().firstMatchingHeader("x-amz-checksum-crc32")).hasValue("jHNlIQ=="); } @Test public void syncJsonSupportsOperationWithRequestChecksumRequired() { jsonClient.operationWithRequestChecksumRequired(r -> r.stringMember("foo")); - assertThat(getSyncRequest().firstMatchingHeader("Content-MD5")).hasValue("g8VCvPTPCMoU01rBlBVt9w=="); + assertThat(getSyncRequest().firstMatchingHeader("Content-MD5")).isNotPresent(); + assertThat(getSyncRequest().firstMatchingHeader("x-amz-checksum-crc32")).hasValue("tcUDMQ=="); } @Test diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/HttpChecksumValidationTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/HttpChecksumValidationTest.java index 27b495c72008..340bea148a74 100644 --- a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/HttpChecksumValidationTest.java +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/HttpChecksumValidationTest.java @@ -32,19 +32,24 @@ import static software.amazon.awssdk.auth.signer.S3SignerExecutionAttribute.ENABLE_CHUNKED_ENCODING; import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder; -import com.github.tomakehurst.wiremock.junit.WireMockRule; +import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo; +import com.github.tomakehurst.wiremock.junit5.WireMockTest; import java.net.URI; +import java.util.Map; import java.util.concurrent.CompletionException; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; +import java.util.stream.Stream; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.ValueSource; import software.amazon.awssdk.auth.credentials.AnonymousCredentialsProvider; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.checksums.DefaultChecksumAlgorithm; import software.amazon.awssdk.core.ResponseBytes; import software.amazon.awssdk.core.async.AsyncResponseTransformer; -import software.amazon.awssdk.core.checksums.Algorithm; import software.amazon.awssdk.core.checksums.ChecksumValidation; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.core.interceptor.Context; @@ -60,20 +65,32 @@ import software.amazon.awssdk.services.protocolrestjson.model.ChecksumMode; import software.amazon.awssdk.services.protocolrestjson.model.GetOperationWithChecksumResponse; import software.amazon.awssdk.services.protocolrestjson.model.OperationWithChecksumNonStreamingResponse; +import software.amazon.awssdk.utils.ImmutableMap; +@WireMockTest public class HttpChecksumValidationTest { - @Rule - public WireMockRule wireMock = new WireMockRule(0); + private static final Map ALGORITHM_TO_VALUE = ImmutableMap.builder() + .put("crc32", "i9aeUg==") + .put("crc32c", "crUfeA==") + .put("sha1", "e1AsOh9IyGCa4hLN+2Od7jlnP14=") + .put("sha256", "ZOyIygCyaOW6GjVnihtTFtIS9PNmskdyMlNKiuyjfzw=") + .put("crc64nvme", "OOJZ0D8xKts=") + .build(); + private ProtocolRestJsonClient client; private ProtocolRestJsonAsyncClient asyncClient; - @Before - public void setupClient() { + public static Stream> checksumEntry() { + return ALGORITHM_TO_VALUE.entrySet().stream(); + } + + @BeforeEach + public void setupClient(WireMockRuntimeInfo wm) { client = ProtocolRestJsonClient.builder() .credentialsProvider(AnonymousCredentialsProvider.create()) .region(Region.US_EAST_1) - .endpointOverride(URI.create("http://localhost:" + wireMock.port())) + .endpointOverride(URI.create(wm.getHttpBaseUrl())) .overrideConfiguration( // TODO(sra-identity-and-auth): we should remove these // overrides once we set up codegen to set chunk-encoding to true @@ -88,51 +105,56 @@ public void setupClient() { .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create("akid", "skid"))) .region(Region.US_EAST_1) .overrideConfiguration(o -> o.addExecutionInterceptor(new CaptureChecksumValidationInterceptor())) - .endpointOverride(URI.create("http://localhost:" + wireMock.port())) + .endpointOverride(URI.create(wm.getHttpBaseUrl())) .build(); } - @After + @AfterEach public void clear() { CaptureChecksumValidationInterceptor.reset(); } + @ParameterizedTest + @MethodSource("checksumEntry") + public void syncClientStreamingResponse_shouldValidate(Map.Entry checksumToValue) { + stubWithSingleChecksum("Hello world", checksumToValue.getValue(), checksumToValue.getKey()); + ResponseBytes responseBytes = + client.getOperationWithChecksum(r -> r.checksumMode(ChecksumMode.ENABLED), ResponseTransformer.toBytes()); + assertThat(responseBytes.asUtf8String()).isEqualTo("Hello world"); + assertThat(CaptureChecksumValidationInterceptor.checksumValidation).isEqualTo(ChecksumValidation.VALIDATED); + assertThat(CaptureChecksumValidationInterceptor.expectedAlgorithm).isEqualTo(DefaultChecksumAlgorithm.fromValue(checksumToValue.getKey())); + } + @Test - public void syncClientValidateStreamingResponse() { - String expectedChecksum = "i9aeUg=="; - stubWithCRC32AndSha256Checksum("Hello world", expectedChecksum, "crc32"); - client.putOperationWithChecksum(r -> r - .checksumAlgorithm(ChecksumAlgorithm.CRC32), - RequestBody.fromString("Hello world"), ResponseTransformer.toBytes()); - verify(putRequestedFor(urlEqualTo("/")).withHeader("x-amz-trailer", equalTo("x-amz-checksum-crc32"))); - verify(putRequestedFor(urlEqualTo("/")).withRequestBody(containing("x-amz-checksum-crc32:" + expectedChecksum))); + public void syncClientValidateStreamingResponse_multipleChecksumInResponse_shouldChooseBasedOnPriority() { + stubWithMultipleChecksums("Hello world", ALGORITHM_TO_VALUE); ResponseBytes responseBytes = client.getOperationWithChecksum(r -> r.checksumMode(ChecksumMode.ENABLED), ResponseTransformer.toBytes()); assertThat(responseBytes.asUtf8String()).isEqualTo("Hello world"); assertThat(CaptureChecksumValidationInterceptor.checksumValidation).isEqualTo(ChecksumValidation.VALIDATED); - assertThat(CaptureChecksumValidationInterceptor.expectedAlgorithm).isEqualTo(Algorithm.CRC32); + assertThat(CaptureChecksumValidationInterceptor.expectedAlgorithm).isEqualTo(DefaultChecksumAlgorithm.CRC32C); } @Test public void syncClientValidateStreamingResponseZeroByte() { String expectedChecksum = "AAAAAA=="; - stubWithCRC32AndSha256Checksum("", expectedChecksum, "crc32"); + stubWithSingleChecksum("", expectedChecksum, "crc32"); client.putOperationWithChecksum(r -> r .checksumAlgorithm(ChecksumAlgorithm.CRC32), - RequestBody.fromString(""), ResponseTransformer.toBytes()); + RequestBody.fromString("")); verify(putRequestedFor(urlEqualTo("/")).withHeader("x-amz-trailer", equalTo("x-amz-checksum-crc32"))); verify(putRequestedFor(urlEqualTo("/")).withRequestBody(containing("x-amz-checksum-crc32:" + expectedChecksum))); ResponseBytes responseBytes = client.getOperationWithChecksum(r -> r.checksumMode(ChecksumMode.ENABLED), ResponseTransformer.toBytes()); assertThat(responseBytes.asUtf8String()).isEmpty(); assertThat(CaptureChecksumValidationInterceptor.checksumValidation).isEqualTo(ChecksumValidation.VALIDATED); - assertThat(CaptureChecksumValidationInterceptor.expectedAlgorithm).isEqualTo(Algorithm.CRC32); + assertThat(CaptureChecksumValidationInterceptor.expectedAlgorithm).isEqualTo(DefaultChecksumAlgorithm.CRC32); } @Test public void syncClientValidateNonStreamingResponse() { String expectedChecksum = "lzlLIA=="; - stubWithCRC32AndSha256Checksum("{\"stringMember\":\"Hello world\"}", expectedChecksum, "crc32"); + stubWithSingleChecksum("{\"stringMember\":\"Hello world\"}", expectedChecksum, "crc32"); client.operationWithChecksumNonStreaming( r -> r.stringMember("Hello world").checksumAlgorithm(ChecksumAlgorithm.CRC32) // TODO(sra-identity-and-auth): we should remove these @@ -145,13 +167,13 @@ public void syncClientValidateNonStreamingResponse() { client.operationWithChecksumNonStreaming(o -> o.checksumMode(ChecksumMode.ENABLED)); assertThat(operationWithChecksumNonStreamingResponse.stringMember()).isEqualTo("Hello world"); assertThat(CaptureChecksumValidationInterceptor.checksumValidation).isEqualTo(ChecksumValidation.VALIDATED); - assertThat(CaptureChecksumValidationInterceptor.expectedAlgorithm).isEqualTo(Algorithm.CRC32); + assertThat(CaptureChecksumValidationInterceptor.expectedAlgorithm).isEqualTo(DefaultChecksumAlgorithm.CRC32); } @Test public void syncClientValidateNonStreamingResponseZeroByte() { String expectedChecksum = "o6a/Qw=="; - stubWithCRC32AndSha256Checksum("{}", expectedChecksum, "crc32"); + stubWithSingleChecksum("{}", expectedChecksum, "crc32"); client.operationWithChecksumNonStreaming( r -> r.checksumAlgorithm(ChecksumAlgorithm.CRC32) // TODO(sra-identity-and-auth): we should remove these @@ -164,13 +186,13 @@ public void syncClientValidateNonStreamingResponseZeroByte() { client.operationWithChecksumNonStreaming(o -> o.checksumMode(ChecksumMode.ENABLED)); assertThat(operationWithChecksumNonStreamingResponse.stringMember()).isNull(); assertThat(CaptureChecksumValidationInterceptor.checksumValidation).isEqualTo(ChecksumValidation.VALIDATED); - assertThat(CaptureChecksumValidationInterceptor.expectedAlgorithm).isEqualTo(Algorithm.CRC32); + assertThat(CaptureChecksumValidationInterceptor.expectedAlgorithm).isEqualTo(DefaultChecksumAlgorithm.CRC32); } @Test public void syncClientValidateStreamingResponseForceSkip() { String expectedChecksum = "i9aeUg=="; - stubWithCRC32AndSha256Checksum("Hello world", expectedChecksum, "crc32"); + stubWithSingleChecksum("Hello world", expectedChecksum, "crc32"); ResponseBytes responseBytes = client.getOperationWithChecksum( r -> r.checksumMode(ChecksumMode.ENABLED).overrideConfiguration( @@ -183,7 +205,7 @@ public void syncClientValidateStreamingResponseForceSkip() { } @Test - public void syncClientValidateStreamingResponseNoAlgorithmInResponse() { + public void syncClientValidateStreamingResponse_noAlgorithmInResponse_shouldSkipValidation() { stubWithNoChecksum(); ResponseBytes responseBytes = client.getOperationWithChecksum( @@ -194,10 +216,11 @@ public void syncClientValidateStreamingResponseNoAlgorithmInResponse() { assertThat(CaptureChecksumValidationInterceptor.expectedAlgorithm).isNull(); } - @Test - public void syncClientValidateStreamingResponseNoAlgorithmFoundInClient() { + @ParameterizedTest + @ValueSource(strings = {"foobar1", "foobar2"}) + public void syncClientValidateStreamingResponse_noSupportedAlgorithmFoundInClient_shouldSkipValidation(String unsupportedAlgorithm) { String expectedChecksum = "someNewAlgorithmCalculatedValue"; - stubWithCRC32AndSha256Checksum("Hello world", expectedChecksum, "crc64"); + stubWithSingleChecksum("Hello world", expectedChecksum, unsupportedAlgorithm); ResponseBytes responseBytes = client.getOperationWithChecksum( r -> r.checksumMode(ChecksumMode.ENABLED), @@ -210,7 +233,7 @@ public void syncClientValidateStreamingResponseNoAlgorithmFoundInClient() { @Test public void syncClientValidateStreamingResponseWithValidationFailed() { String expectedChecksum = "i9aeUg="; - stubWithCRC32AndSha256Checksum("Hello world", expectedChecksum, "crc32"); + stubWithSingleChecksum("Hello world", expectedChecksum, "crc32"); assertThatExceptionOfType(SdkClientException.class) .isThrownBy(() -> client.getOperationWithChecksum( r -> r.checksumMode(ChecksumMode.ENABLED), @@ -218,13 +241,13 @@ public void syncClientValidateStreamingResponseWithValidationFailed() { .withMessage("Unable to unmarshall response (Data read has a different checksum than expected. Was i9aeUg==, " + "but expected i9aeUg=). Response Code: 200, Response Text: OK"); assertThat(CaptureChecksumValidationInterceptor.checksumValidation).isEqualTo(ChecksumValidation.VALIDATED); - assertThat(CaptureChecksumValidationInterceptor.expectedAlgorithm).isEqualTo(Algorithm.CRC32); + assertThat(CaptureChecksumValidationInterceptor.expectedAlgorithm).isEqualTo(DefaultChecksumAlgorithm.CRC32); } @Test public void syncClientSkipsValidationWhenFeatureDisabled() { String expectedChecksum = "i9aeUg=="; - stubWithCRC32AndSha256Checksum("Hello world", expectedChecksum, "crc32"); + stubWithSingleChecksum("Hello world", expectedChecksum, "crc32"); ResponseBytes responseBytes = client.getOperationWithChecksum(r -> r.stringMember("foo"), ResponseTransformer.toBytes()); assertThat(responseBytes.asUtf8String()).isEqualTo("Hello world"); @@ -232,33 +255,42 @@ public void syncClientSkipsValidationWhenFeatureDisabled() { assertThat(CaptureChecksumValidationInterceptor.expectedAlgorithm).isNull(); } - //Async + @ParameterizedTest + @MethodSource("checksumEntry") + public void asyncClientStreamingResponse_shouldValidate(Map.Entry checksumToValue) { + stubWithSingleChecksum("Hello world", checksumToValue.getValue(), checksumToValue.getKey()); + ResponseBytes responseBytes = + asyncClient.getOperationWithChecksum(r -> r.checksumMode(ChecksumMode.ENABLED), AsyncResponseTransformer.toBytes()).join(); + assertThat(responseBytes.asUtf8String()).isEqualTo("Hello world"); + assertThat(CaptureChecksumValidationInterceptor.checksumValidation).isEqualTo(ChecksumValidation.VALIDATED); + assertThat(CaptureChecksumValidationInterceptor.expectedAlgorithm).isEqualTo(DefaultChecksumAlgorithm.fromValue(checksumToValue.getKey())); + } + @Test - public void asyncClientValidateStreamingResponse() { - String expectedChecksum = "i9aeUg=="; - stubWithCRC32AndSha256Checksum("Hello world", expectedChecksum, "crc32"); + public void asyncClientValidateStreamingResponse_multipleChecksumInResponse_shouldChooseBasedOnPriority() { + stubWithMultipleChecksums("Hello world", ALGORITHM_TO_VALUE); ResponseBytes responseBytes = asyncClient.getOperationWithChecksum(r -> r.checksumMode(ChecksumMode.ENABLED), AsyncResponseTransformer.toBytes()).join(); assertThat(responseBytes.asUtf8String()).isEqualTo("Hello world"); assertThat(CaptureChecksumValidationInterceptor.checksumValidation).isEqualTo(ChecksumValidation.VALIDATED); - assertThat(CaptureChecksumValidationInterceptor.expectedAlgorithm).isEqualTo(Algorithm.CRC32); + assertThat(CaptureChecksumValidationInterceptor.expectedAlgorithm).isEqualTo(DefaultChecksumAlgorithm.CRC32C); } @Test public void asyncClientValidateStreamingResponseZeroByte() { String expectedChecksum = "AAAAAA=="; - stubWithCRC32AndSha256Checksum("", expectedChecksum, "crc32"); + stubWithSingleChecksum("", expectedChecksum, "crc32"); ResponseBytes responseBytes = asyncClient.getOperationWithChecksum(r -> r.checksumMode(ChecksumMode.ENABLED), AsyncResponseTransformer.toBytes()).join(); assertThat(responseBytes.asUtf8String()).isEmpty(); assertThat(CaptureChecksumValidationInterceptor.checksumValidation).isEqualTo(ChecksumValidation.VALIDATED); - assertThat(CaptureChecksumValidationInterceptor.expectedAlgorithm).isEqualTo(Algorithm.CRC32); + assertThat(CaptureChecksumValidationInterceptor.expectedAlgorithm).isEqualTo(DefaultChecksumAlgorithm.CRC32); } @Test public void asyncClientValidateNonStreamingResponse() { String expectedChecksum = "lzlLIA=="; - stubWithCRC32AndSha256Checksum("{\"stringMember\":\"Hello world\"}", expectedChecksum, "crc32"); + stubWithSingleChecksum("{\"stringMember\":\"Hello world\"}", expectedChecksum, "crc32"); OperationWithChecksumNonStreamingResponse response = asyncClient.operationWithChecksumNonStreaming( o -> o.checksumMode(ChecksumMode.ENABLED) @@ -268,13 +300,13 @@ public void asyncClientValidateNonStreamingResponse() { .overrideConfiguration(c -> c.putExecutionAttribute(ENABLE_CHUNKED_ENCODING, false))).join(); assertThat(response.stringMember()).isEqualTo("Hello world"); assertThat(CaptureChecksumValidationInterceptor.checksumValidation).isEqualTo(ChecksumValidation.VALIDATED); - assertThat(CaptureChecksumValidationInterceptor.expectedAlgorithm).isEqualTo(Algorithm.CRC32); + assertThat(CaptureChecksumValidationInterceptor.expectedAlgorithm).isEqualTo(DefaultChecksumAlgorithm.CRC32); } @Test public void asyncClientValidateNonStreamingResponseZeroByte() { String expectedChecksum = "o6a/Qw=="; - stubWithCRC32AndSha256Checksum("{}", expectedChecksum, "crc32"); + stubWithSingleChecksum("{}", expectedChecksum, "crc32"); OperationWithChecksumNonStreamingResponse operationWithChecksumNonStreamingResponse = asyncClient.operationWithChecksumNonStreaming( o -> o.checksumMode(ChecksumMode.ENABLED) @@ -284,13 +316,13 @@ public void asyncClientValidateNonStreamingResponseZeroByte() { .overrideConfiguration(c -> c.putExecutionAttribute(ENABLE_CHUNKED_ENCODING, false))).join(); assertThat(operationWithChecksumNonStreamingResponse.stringMember()).isNull(); assertThat(CaptureChecksumValidationInterceptor.checksumValidation).isEqualTo(ChecksumValidation.VALIDATED); - assertThat(CaptureChecksumValidationInterceptor.expectedAlgorithm).isEqualTo(Algorithm.CRC32); + assertThat(CaptureChecksumValidationInterceptor.expectedAlgorithm).isEqualTo(DefaultChecksumAlgorithm.CRC32); } @Test public void asyncClientValidateStreamingResponseForceSkip() { String expectedChecksum = "i9aeUg=="; - stubWithCRC32AndSha256Checksum("Hello world", expectedChecksum, "crc32"); + stubWithSingleChecksum("Hello world", expectedChecksum, "crc32"); ResponseBytes responseBytes = asyncClient.getOperationWithChecksum( r -> r.checksumMode(ChecksumMode.ENABLED).overrideConfiguration( @@ -314,10 +346,11 @@ public void asyncClientValidateStreamingResponseNoAlgorithmInResponse() { assertThat(CaptureChecksumValidationInterceptor.expectedAlgorithm).isNull(); } - @Test - public void asyncClientValidateStreamingResponseNoAlgorithmFoundInClient() { + @ParameterizedTest + @ValueSource(strings = {"foobar1", "foobar2"}) + public void asyncClientValidateStreamingResponseNoSupportedAlgorithmFoundInClient_shouldNotFail(String unsupportedAlgorithm) { String expectedChecksum = "someNewAlgorithmCalculatedValue"; - stubWithCRC32AndSha256Checksum("Hello world", expectedChecksum, "crc64"); + stubWithSingleChecksum("Hello world", expectedChecksum, unsupportedAlgorithm); ResponseBytes responseBytes = asyncClient.getOperationWithChecksum( r -> r.checksumMode(ChecksumMode.ENABLED), @@ -330,7 +363,7 @@ public void asyncClientValidateStreamingResponseNoAlgorithmFoundInClient() { @Test public void asyncClientValidateStreamingResponseWithValidationFailed() { String expectedChecksum = "i9aeUg="; - stubWithCRC32AndSha256Checksum("Hello world", expectedChecksum, "crc32"); + stubWithSingleChecksum("Hello world", expectedChecksum, "crc32"); assertThatExceptionOfType(CompletionException.class) .isThrownBy(() -> asyncClient.getOperationWithChecksum( r -> r.checksumMode(ChecksumMode.ENABLED), @@ -339,13 +372,13 @@ public void asyncClientValidateStreamingResponseWithValidationFailed() { .withMessage("software.amazon.awssdk.core.exception.SdkClientException: Data read has a different checksum" + " than expected. Was i9aeUg==, but expected i9aeUg="); assertThat(CaptureChecksumValidationInterceptor.checksumValidation).isEqualTo(ChecksumValidation.VALIDATED); - assertThat(CaptureChecksumValidationInterceptor.expectedAlgorithm).isEqualTo(Algorithm.CRC32); + assertThat(CaptureChecksumValidationInterceptor.expectedAlgorithm).isEqualTo(DefaultChecksumAlgorithm.CRC32); } @Test public void asyncClientSkipsValidationWhenFeatureDisabled() { String expectedChecksum = "i9aeUg=="; - stubWithCRC32AndSha256Checksum("Hello world", expectedChecksum, "crc32"); + stubWithSingleChecksum("Hello world", expectedChecksum, "crc32"); ResponseBytes responseBytes = asyncClient.getOperationWithChecksum(r -> r.stringMember("foo"), AsyncResponseTransformer.toBytes()).join(); assertThat(responseBytes.asUtf8String()).isEqualTo("Hello world"); @@ -353,7 +386,7 @@ public void asyncClientSkipsValidationWhenFeatureDisabled() { assertThat(CaptureChecksumValidationInterceptor.expectedAlgorithm).isNull(); } - private void stubWithCRC32AndSha256Checksum(String body, String checksumValue, String algorithmName) { + private void stubWithSingleChecksum(String body, String checksumValue, String algorithmName) { ResponseDefinitionBuilder responseBuilder = aResponse().withStatus(200) .withHeader("x-amz-checksum-" + algorithmName, checksumValue) .withHeader("content-length", @@ -364,6 +397,20 @@ private void stubWithCRC32AndSha256Checksum(String body, String checksumValue, S stubFor(post(anyUrl()).willReturn(responseBuilder)); } + private void stubWithMultipleChecksums(String body, Map checksums) { + ResponseDefinitionBuilder responseBuilder = aResponse().withStatus(200) + .withHeader("content-length", + String.valueOf(body.length())) + .withBody(body); + + + checksums.entrySet().forEach(checksum -> responseBuilder.withHeader("x-amz-checksum-" + checksum.getKey(), + checksum.getValue())); + stubFor(get(anyUrl()).willReturn(responseBuilder)); + stubFor(put(anyUrl()).willReturn(responseBuilder)); + stubFor(post(anyUrl()).willReturn(responseBuilder)); + } + private void stubWithNoChecksum() { ResponseDefinitionBuilder responseBuilder = aResponse().withStatus(200) .withHeader("content-length", @@ -375,7 +422,7 @@ private void stubWithNoChecksum() { } private static class CaptureChecksumValidationInterceptor implements ExecutionInterceptor { - private static Algorithm expectedAlgorithm; + private static software.amazon.awssdk.checksums.spi.ChecksumAlgorithm expectedAlgorithm; private static ChecksumValidation checksumValidation; public static void reset() { @@ -387,7 +434,7 @@ public static void reset() { @Override public void afterExecution(Context.AfterExecution context, ExecutionAttributes executionAttributes) { expectedAlgorithm = - executionAttributes.getOptionalAttribute(SdkExecutionAttribute.HTTP_CHECKSUM_VALIDATION_ALGORITHM).orElse(null); + executionAttributes.getOptionalAttribute(SdkExecutionAttribute.HTTP_CHECKSUM_VALIDATION_ALGORITHM_V2).orElse(null); checksumValidation = executionAttributes.getOptionalAttribute(SdkExecutionAttribute.HTTP_RESPONSE_CHECKSUM_VALIDATION).orElse(null); } @@ -395,7 +442,7 @@ public void afterExecution(Context.AfterExecution context, ExecutionAttributes e @Override public void onExecutionFailure(Context.FailedExecution context, ExecutionAttributes executionAttributes) { expectedAlgorithm = - executionAttributes.getOptionalAttribute(SdkExecutionAttribute.HTTP_CHECKSUM_VALIDATION_ALGORITHM).orElse(null); + executionAttributes.getOptionalAttribute(SdkExecutionAttribute.HTTP_CHECKSUM_VALIDATION_ALGORITHM_V2).orElse(null); checksumValidation = executionAttributes.getOptionalAttribute(SdkExecutionAttribute.HTTP_RESPONSE_CHECKSUM_VALIDATION).orElse(null); } diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/SyncHttpChecksumInTrailerTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/SyncHttpChecksumInTrailerTest.java index c115c18a8066..b5a77d2d0e4d 100644 --- a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/SyncHttpChecksumInTrailerTest.java +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/SyncHttpChecksumInTrailerTest.java @@ -78,8 +78,7 @@ public void setupClient() { public void sync_streaming_NoSigner_appends_trailer_checksum() { stubResponseWithHeaders(); - client.putOperationWithChecksum(r -> r.checksumAlgorithm(ChecksumAlgorithm.CRC32), RequestBody.fromString("Hello world") - , ResponseTransformer.toBytes()); + client.putOperationWithChecksum(r -> r.checksumAlgorithm(ChecksumAlgorithm.CRC32), RequestBody.fromString("Hello world")); verify(putRequestedFor(anyUrl()).withHeader(CONTENT_LENGTH, equalTo("52"))); verify(putRequestedFor(anyUrl()).withHeader(HttpChecksumConstant.HEADER_FOR_TRAILER_REFERENCE, equalTo("x-amz-checksum-crc32"))); verify(putRequestedFor(anyUrl()).withHeader("x-amz-content-sha256", equalTo("STREAMING-UNSIGNED-PAYLOAD-TRAILER"))); @@ -101,8 +100,7 @@ public void sync_streaming_NoSigner_appends_trailer_checksum_withContentEncoding client.putOperationWithChecksum(r -> r.checksumAlgorithm(ChecksumAlgorithm.CRC32) .contentEncoding("deflate"), - RequestBody.fromString("Hello world"), - ResponseTransformer.toBytes()); + RequestBody.fromString("Hello world")); verify(putRequestedFor(anyUrl()).withHeader("Content-Encoding", equalTo("aws-chunked"))); verify(putRequestedFor(anyUrl()).withHeader("Content-Encoding", equalTo("deflate"))); //b is hex value of 11. @@ -121,8 +119,7 @@ public void sync_streaming_specifiedLengthIsLess_NoSigner_appends_trailer_checks // length of 5 truncates to "Hello" RequestBody requestBody = RequestBody.fromContentProvider(provider, 5, "text/plain"); client.putOperationWithChecksum(r -> r.checksumAlgorithm(ChecksumAlgorithm.CRC32), - requestBody, - ResponseTransformer.toBytes()); + requestBody); verify(putRequestedFor(anyUrl()).withHeader(CONTENT_LENGTH, equalTo("46"))); verify(putRequestedFor(anyUrl()).withHeader(HttpChecksumConstant.HEADER_FOR_TRAILER_REFERENCE, equalTo("x-amz-checksum-crc32"))); verify(putRequestedFor(anyUrl()).withHeader("x-amz-content-sha256", equalTo("STREAMING-UNSIGNED-PAYLOAD-TRAILER"))); @@ -144,8 +141,7 @@ public void syncStreaming_withRetry_NoSigner_shouldContainChecksum_fromIntercept + "0" + CRLF + "x-amz-checksum-sha256:ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0=" + CRLF + CRLF; - client.putOperationWithChecksum(r -> r.checksumAlgorithm(ChecksumAlgorithm.SHA256), RequestBody.fromString("abc"), - ResponseTransformer.toBytes()); + client.putOperationWithChecksum(r -> r.checksumAlgorithm(ChecksumAlgorithm.SHA256), RequestBody.fromString("abc")); List requests = getRecordedRequests(); assertThat(requests.size()).isEqualTo(2); assertThat(requests.get(0).getBody()).contains(expectedRequestBody.getBytes()); diff --git a/test/crt-unavailable-tests/pom.xml b/test/crt-unavailable-tests/pom.xml index 559b2fcf1ef3..9301ba2135a4 100644 --- a/test/crt-unavailable-tests/pom.xml +++ b/test/crt-unavailable-tests/pom.xml @@ -20,7 +20,7 @@ aws-sdk-java-pom software.amazon.awssdk - 2.29.52 + 2.30.0 ../../pom.xml 4.0.0 @@ -45,7 +45,16 @@ software.amazon.awssdk http-auth-aws ${awsjavasdk.version} - test + + + software.amazon.awssdk + aws-json-protocol + ${awsjavasdk.version} + + + software.amazon.awssdk + aws-core + ${awsjavasdk.version} org.assertj @@ -53,8 +62,8 @@ test - org.hamcrest - hamcrest-all + org.mockito + mockito-core test @@ -87,11 +96,75 @@ log4j-slf4j-impl test + + io.reactivex.rxjava2 + rxjava + test + software.amazon.awssdk checksums ${awsjavasdk.version} - test + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + software.amazon.awssdk + codegen-maven-plugin + ${awsjavasdk.version} + + + generate-sources + + generate + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + generate-sources + + add-resource + + + + + ${project.build.directory}/generated-sources/sdk + + + + + + + + + com.github.spotbugs + spotbugs-maven-plugin + + true + + + + + org.apache.maven.plugins + maven-dependency-plugin + ${maven-dependency-plugin.version} + + false + false + + + + + diff --git a/test/crt-unavailable-tests/src/main/resources/codegen-resources/service-2.json b/test/crt-unavailable-tests/src/main/resources/codegen-resources/service-2.json new file mode 100644 index 000000000000..2a6c09074cd8 --- /dev/null +++ b/test/crt-unavailable-tests/src/main/resources/codegen-resources/service-2.json @@ -0,0 +1,1149 @@ +{ + "version":"2.0", + "metadata":{ + "apiVersion":"2016-03-11", + "endpointPrefix":"customresponsemetadata", + "jsonVersion":"1.1", + "protocol":"rest-json", + "serviceAbbreviation":"AmazonProtocolRestJson", + "serviceFullName":"Amazon Protocol Rest Json", + "serviceId":"AmazonProtocolRestJson", + "signatureVersion":"v4", + "targetPrefix":"ProtocolTestsService", + "timestampFormat":"unixTimestamp", + "uid":"restjson-2016-03-11" + }, + "operations":{ + "AllTypes":{ + "name":"AllTypes", + "http":{ + "method":"POST", + "requestUri":"/2016-03-11/allTypes" + }, + "input":{"shape":"AllTypesStructure"}, + "output":{"shape":"AllTypesStructure"}, + "errors":[ + {"shape":"EmptyModeledException"} + ] + }, + "DeleteOperation":{ + "name":"DeleteOperation", + "http":{ + "method":"DELETE", + "requestUri":"/2016-03-11/deleteOperation" + } + }, + "HeadOperation":{ + "name":"HeadOperation", + "http":{ + "method":"HEAD", + "requestUri":"/2016-03-11/headOperation" + } + }, + "IdempotentOperation":{ + "name":"IdempotentOperation", + "http":{ + "method":"POST", + "requestUri":"/2016-03-11/idempotentOperation/{PathParam}" + }, + "input":{"shape":"IdempotentOperationStructure"} + }, + "JsonValuesOperation":{ + "name":"JsonValuesOperation", + "http":{ + "method":"POST", + "requestUri":"/2016-03-11/JsonValuesStructure" + }, + "input":{"shape":"JsonValuesStructure"}, + "output":{"shape":"JsonValuesStructure"}, + "errors":[ + {"shape":"EmptyModeledException"} + ] + }, + "MapOfStringToListOfStringInQueryParams":{ + "name":"MapOfStringToListOfStringInQueryParams", + "http":{ + "method":"POST", + "requestUri":"/2016-03-11/mapOfStringToListOfStringInQueryParams" + }, + "input":{"shape":"MapOfStringToListOfStringInQueryParamsInput"} + }, + "MembersInHeaders":{ + "name":"MembersInHeaders", + "http":{ + "method":"POST", + "requestUri":"/2016-03-11/membersInHeaders" + }, + "input":{"shape":"MembersInHeadersInput"}, + "output":{"shape":"MembersInHeadersInput"} + }, + "MembersInQueryParams":{ + "name":"MembersInQueryParams", + "http":{ + "method":"POST", + "requestUri":"/2016-03-11/membersInQueryParams?StaticQueryParam=foo" + }, + "input":{"shape":"MembersInQueryParamsInput"} + }, + "MultiLocationOperation":{ + "name":"MultiLocationOperation", + "http":{ + "method":"POST", + "requestUri":"/2016-03-11/multiLocationOperation/{PathParam}" + }, + "input":{"shape":"MultiLocationOperationInput"} + }, + "NestedContainers":{ + "name":"NestedContainers", + "http":{ + "method":"POST", + "requestUri":"/2016-03-11/nestedContainers" + }, + "input":{"shape":"NestedContainersStructure"}, + "output":{"shape":"NestedContainersStructure"} + }, + "OperationWithExplicitPayloadBlob":{ + "name":"OperationWithExplicitPayloadBlob", + "http":{ + "method":"POST", + "requestUri":"/2016-03-11/operationWithExplicitPayloadBlob" + }, + "input":{"shape":"OperationWithExplicitPayloadBlobInput"}, + "output":{"shape":"OperationWithExplicitPayloadBlobInput"} + }, + "OperationWithExplicitPayloadString":{ + "name":"OperationWithExplicitPayloadString", + "http":{ + "method":"POST", + "requestUri":"/2016-03-11/operationWithExplicitPayloadString" + }, + "input":{"shape":"OperationWithExplicitPayloadStringInput"}, + "output":{"shape":"OperationWithExplicitPayloadStringInput"} + }, + "OperationWithExplicitPayloadStructure":{ + "name":"OperationWithExplicitPayloadStructure", + "http":{ + "method":"POST", + "requestUri":"/2016-03-11/operationWithExplicitPayloadStructure" + }, + "input":{"shape":"OperationWithExplicitPayloadStructureInput"}, + "output":{"shape":"OperationWithExplicitPayloadStructureInput"} + }, + "OperationWithGreedyLabel":{ + "name":"OperationWithGreedyLabel", + "http":{ + "method":"POST", + "requestUri":"/2016-03-11/operationWithGreedyLabel/{NonGreedyPathParam}/{GreedyPathParam+}" + }, + "input":{"shape":"OperationWithGreedyLabelInput"} + }, + "OperationWithModeledContentType":{ + "name":"OperationWithModeledContentType", + "http":{ + "method":"POST", + "requestUri":"/2016-03-11/operationWithModeledContentType" + }, + "input":{"shape":"OperationWithModeledContentTypeInput"} + }, + "OperationWithNoInputOrOutput":{ + "name":"OperationWithNoInputOrOutput", + "http":{ + "method":"POST", + "requestUri":"/2016-03-11/operationWithNoInputOrOutput" + } + }, + "PaginatedOperationWithResultKey": { + "name": "PaginatedOperationWithResultKey", + "http": { + "method": "POST", + "requestUri": "/" + }, + "input": { + "shape": "PaginatedOperationWithResultKeyRequest" + }, + "output": { + "shape": "PaginatedOperationWithResultKeyResponse" + }, + "documentation": "Some paginated operation with result_key in paginators.json file" + }, + "PaginatedOperationWithMoreResults": { + "name": "PaginatedOperationWithMoreResults", + "http": { + "method": "POST", + "requestUri": "/" + }, + "input": { + "shape": "PaginatedOperationWithMoreResultsRequest" + }, + "output": { + "shape": "PaginatedOperationWithMoreResultsResponse" + }, + "documentation": "Some paginated operation with more_results in paginators.json file" + }, + "QueryParamWithoutValue":{ + "name":"QueryParamWithoutValue", + "http":{ + "method":"POST", + "requestUri":"/2016-03-11/queryParamWithoutValue?param" + }, + "input":{"shape":"QueryParamWithoutValueInput"} + }, + "StreamingInputOperationWithRequiredChecksum":{ + "name":"OperationWithRequiredChecksum", + "http":{ + "method":"POST", + "requestUri":"/2016-03-11/allTypes" + }, + "input":{"shape":"StructureWithStreamingMember"}, + "output":{"shape":"AllTypesStructure"}, + "httpChecksumRequired": true + }, + "OperationWithRequiredChecksum":{ + "name":"OperationWithRequiredChecksum", + "http":{ + "method":"POST", + "requestUri":"/2016-03-11/allTypes" + }, + "input":{"shape":"AllTypesStructure"}, + "output":{"shape":"AllTypesStructure"}, + "httpChecksumRequired": true + }, + "OperationWithNoneAuthType":{ + "name":"OperationWithNoneAuthType", + "http":{ + "method":"POST", + "requestUri":"/2016-03-11/allTypes" + }, + "input":{"shape":"AllTypesStructure"}, + "output":{"shape":"AllTypesStructure"}, + "authtype": "none" + }, + "OperationWithRequestChecksumRequired":{ + "name":"OperationWithRequestChecksumRequired", + "http":{ + "method":"POST", + "requestUri":"/2016-03-11/allTypes" + }, + "input":{"shape":"AllTypesStructure"}, + "output":{"shape":"AllTypesStructure"}, + "httpChecksum" : { + "requestChecksumRequired" : true + } + }, + "OperationWithCustomRequestChecksum":{ + "name":"OperationWithRequestChecksumRequired", + "http":{ + "method":"POST", + "requestUri":"/2016-03-11/allTypes" + }, + "input":{"shape":"ChecksumStructure"}, + "output":{"shape":"ChecksumStructure"}, + "httpChecksum" : { + "requestChecksumRequired" : true, + "requestAlgorithmMember": "ChecksumAlgorithm", + "requestValidationModeMember" : "ChecksumMode", + "responseAlgorithms": ["crc64nvme","crc32", "crc32c", "sha256", "sha1"] + } + }, + "StreamingInputOperation":{ + "name":"StreamingInputOperation", + "http":{ + "method":"POST", + "requestUri":"/2016-03-11/streamingInputOperation" + }, + "input":{"shape":"StructureWithStreamingMember"} + }, + "StreamingOutputOperation":{ + "name":"StreamingOutputOperation", + "http":{ + "method":"POST", + "requestUri":"/2016-03-11/streamingOutputOperation" + }, + "output":{"shape":"StructureWithStreamingMember"} + }, + "EventStreamOperation": { + "name": "EventStreamOperation", + "http": { + "method": "POST", + "requestUri": "/2016-03-11/eventStreamOperation" + }, + "input": { + "shape": "EventStreamOperationRequest" + }, + "output": { + "shape": "EventStreamOutput" + } + }, + "OperationWithHostPrefix": { + "name": "OperationWithHostPrefix", + "http": { + "method": "POST", + "requestUri": "/2016-03-11/OperationWithHostPrefix" + }, + "endpoint": { + "hostPrefix": "{StringMember}-foo." + }, + "input": { + "shape": "AllTypesStructure" + } + }, + "PutOperationWithChecksum":{ + "name":"PutOperationWithChecksum", + "http":{ + "method":"PUT", + "requestUri":"/" + }, + "input":{"shape":"ChecksumStructureWithStreaming"}, + "httpChecksum" : { + "requestAlgorithmMember": "ChecksumAlgorithm" + } + }, + "PutOperationWithRequestCompression":{ + "name":"PutOperationWithRequestCompression", + "http":{ + "method":"PUT", + "requestUri":"/" + }, + "input":{"shape":"RequestCompressionStructure"}, + "output":{"shape":"RequestCompressionStructure"}, + "requestcompression": { + "encodings": ["gzip"] + } + }, + "PutOperationWithStreamingRequestCompression":{ + "name":"PutOperationWithStreamingRequestCompression", + "http":{ + "method":"PUT", + "requestUri":"/" + }, + "input":{"shape":"RequestCompressionStructureWithStreaming"}, + "output":{"shape":"RequestCompressionStructureWithStreaming"}, + "requestcompression": { + "encodings": ["gzip"] + }, + "authtype":"v4-unsigned-body" + }, + "GetOperationWithChecksum":{ + "name":"GetOperationWithChecksum", + "http":{ + "method":"GET", + "requestUri":"/" + }, + "input":{"shape":"ChecksumStructure"}, + "output":{"shape":"ChecksumStructureWithStreaming"}, + "httpChecksum" : { + "requestValidationModeMember": "ChecksumMode", + "responseAlgorithms": ["CRC64NVME","CRC32C", "CRC32", "SHA1", "SHA256"] + } + }, + "GetOperationWithMapEndpointParam":{ + "name":"GetOperationWithMapEndpointParam", + "http":{ + "method":"GET", + "requestUri":"/" + }, + "input":{"shape":"GetOperationWithMapEndpointParamInput"}, + "output":{"shape":"GetOperationWithMapEndpointParamOutput"} + }, + "OperationWithChecksumNonStreaming":{ + "name":"OperationWithChecksumNonStreaming", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "input":{"shape":"ChecksumStructure"}, + "output":{"shape":"ChecksumStructure"}, + "httpChecksum" : { + "requestChecksumRequired": true, + "requestAlgorithmMember": "ChecksumAlgorithm", + "requestValidationModeMember": "ChecksumMode", + "responseAlgorithms": ["CRC64NVME","CRC32C", "CRC32", "SHA1", "SHA256"] + } + }, + "QueryParameterOperation":{ + "name":"QueryParameterOperation", + "http":{ + "method":"DELETE", + "requestUri":"/2016-03-11/queryParameterOperation/{PathParam}" + }, + "input":{"shape":"QueryParameterOperationRequest"} + } + }, + "shapes":{ + "AllTypesStructure":{ + "type":"structure", + "members":{ + "StringMember":{"shape":"String"}, + "IntegerMember":{"shape":"Integer"}, + "BooleanMember":{"shape":"Boolean"}, + "FloatMember":{"shape":"Float"}, + "DoubleMember":{"shape":"Double"}, + "LongMember":{"shape":"Long"}, + "ShortMember":{"shape":"Short"}, + "EnumMember":{"shape":"EnumType"}, + "SimpleList":{"shape":"ListOfStrings"}, + "ListOfEnums":{"shape":"ListOfEnums"}, + "ListOfMaps":{"shape":"ListOfMapStringToString"}, + "ListOfListOfMapsOfStringToStruct":{"shape":"ListOfListOfMapOfStringToSimpleStruct"}, + "ListOfMapsOfStringToStruct":{"shape":"ListOfMapOfStringToSimpleStruct"}, + "ListOfStructs":{"shape":"ListOfSimpleStructs"}, + "MapOfStringToIntegerList":{"shape":"MapOfStringToIntegerList"}, + "MapOfStringToString":{"shape":"MapOfStringToString"}, + "MapOfStringToStruct":{"shape":"MapOfStringToSimpleStruct"}, + "MapOfEnumToEnum":{"shape":"MapOfEnumToEnum"}, + "TimestampMember":{"shape":"Timestamp"}, + "StructWithNestedTimestampMember":{"shape":"StructWithTimestamp"}, + "BlobArg":{"shape":"BlobType"}, + "StructWithNestedBlob":{"shape":"StructWithNestedBlobType"}, + "BlobMap":{"shape":"BlobMapType"}, + "ListOfBlobs":{"shape":"ListOfBlobsType"}, + "RecursiveStruct":{"shape":"RecursiveStructType"}, + "PolymorphicTypeWithSubTypes":{"shape":"BaseType"}, + "PolymorphicTypeWithoutSubTypes":{"shape":"SubTypeOne"}, + "SetPrefixedMember":{"shape":"String"}, + "UnionMember":{"shape":"AllTypesUnionStructure"} + } + }, + "AllTypesUnionStructure":{ + "type":"structure", + "union":true, + "members":{ + "StringMember":{"shape":"String"}, + "IntegerMember":{"shape":"Integer"}, + "BooleanMember":{"shape":"Boolean"}, + "FloatMember":{"shape":"Float"}, + "DoubleMember":{"shape":"Double"}, + "LongMember":{"shape":"Long"}, + "ShortMember":{"shape":"Short"}, + "EnumMember":{"shape":"EnumType"}, + "SimpleList":{"shape":"ListOfStrings"}, + "ListOfEnums":{"shape":"ListOfEnums"}, + "ListOfMaps":{"shape":"ListOfMapStringToString"}, + "ListOfListOfMapsOfStringToStruct":{"shape":"ListOfListOfMapOfStringToSimpleStruct"}, + "ListOfMapsOfStringToStruct":{"shape":"ListOfMapOfStringToSimpleStruct"}, + "ListOfStructs":{"shape":"ListOfSimpleStructs"}, + "MapOfStringToIntegerList":{"shape":"MapOfStringToIntegerList"}, + "MapOfStringToString":{"shape":"MapOfStringToString"}, + "MapOfStringToStruct":{"shape":"MapOfStringToSimpleStruct"}, + "MapOfEnumToEnum":{"shape":"MapOfEnumToEnum"}, + "TimestampMember":{"shape":"Timestamp"}, + "StructWithNestedTimestampMember":{"shape":"StructWithTimestamp"}, + "BlobArg":{"shape":"BlobType"}, + "StructWithNestedBlob":{"shape":"StructWithNestedBlobType"}, + "BlobMap":{"shape":"BlobMapType"}, + "ListOfBlobs":{"shape":"ListOfBlobsType"}, + "RecursiveStruct":{"shape":"RecursiveStructType"}, + "PolymorphicTypeWithSubTypes":{"shape":"BaseType"}, + "PolymorphicTypeWithoutSubTypes":{"shape":"SubTypeOne"}, + "SetPrefixedMember":{"shape":"String"}, + "UnionMember":{"shape":"AllTypesUnionStructure"} + } + }, + "BaseType":{ + "type":"structure", + "members":{ + "BaseMember":{"shape":"String"} + } + }, + "BlobMapType":{ + "type":"map", + "key":{"shape":"String"}, + "value":{"shape":"BlobType"} + }, + "BlobType":{"type":"blob"}, + "Boolean":{"type":"boolean"}, + "Double":{"type":"double"}, + "EmptyModeledException":{ + "type":"structure", + "members":{ + }, + "exception":true + }, + "Float":{"type":"float"}, + "IdempotentOperationStructure":{ + "type":"structure", + "required":["PathIdempotentToken"], + "members":{ + "PathIdempotentToken":{ + "shape":"String", + "idempotencyToken":true, + "location":"uri", + "locationName":"PathParam" + }, + "QueryIdempotentToken":{ + "shape":"String", + "idempotencyToken":true, + "location":"querystring", + "locationName":"QueryParam" + }, + "HeaderIdempotentToken":{ + "shape":"String", + "idempotencyToken":true, + "location":"header", + "locationName":"x-amz-idempotent-header" + } + } + }, + "Integer":{"type":"integer"}, + "JsonValuesStructure":{ + "type":"structure", + "members":{ + "JsonValueHeaderMember":{ + "shape":"String", + "jsonvalue":true, + "location":"header", + "locationName":"Encoded-Header" + }, + "JsonValueMember":{ + "shape":"String", + "jsonvalue":true + } + } + }, + "ListOfBlobsType":{ + "type":"list", + "member":{"shape":"BlobType"} + }, + "ListOfIntegers":{ + "type":"list", + "member":{"shape":"Integer"} + }, + "ListOfListOfListsOfStrings":{ + "type":"list", + "member":{"shape":"ListOfListsOfStrings"} + }, + "ListOfListsOfStrings":{ + "type":"list", + "member":{"shape":"ListOfStrings"} + }, + "ListOfMapStringToString":{ + "type":"list", + "member":{"shape":"MapOfStringToString"} + }, + "ListOfListOfMapOfStringToSimpleStruct":{ + "type":"list", + "member":{"shape":"ListOfMapOfStringToSimpleStruct"} + }, + "ListOfMapOfStringToSimpleStruct":{ + "type":"list", + "member":{"shape":"MapOfStringToSimpleStruct"} + }, + "ListOfSimpleStructs":{ + "type":"list", + "member":{"shape":"SimpleStruct"} + }, + "ListOfStrings":{ + "type":"list", + "member":{"shape":"String"} + }, + "ListOfEnums":{ + "type":"list", + "member":{"shape":"EnumType"} + }, + "Long":{"type":"long"}, + "Short":{"type":"short"}, + "MapOfStringToIntegerList":{ + "type":"map", + "key":{"shape":"String"}, + "value":{"shape":"ListOfIntegers"} + }, + "MapOfStringToListOfListsOfStrings":{ + "type":"map", + "key":{"shape":"String"}, + "value":{"shape":"ListOfListsOfStrings"} + }, + "MapOfStringToListOfStringInQueryParamsInput":{ + "type":"structure", + "members":{ + "MapOfStringToListOfStrings":{ + "shape":"MapOfStringToListOfStrings", + "location":"querystring" + } + } + }, + "MapOfStringToListOfStrings":{ + "type":"map", + "key":{"shape":"String"}, + "value":{"shape":"ListOfStrings"} + }, + "MapOfStringToSimpleStruct":{ + "type":"map", + "key":{"shape":"String"}, + "value":{"shape":"SimpleStruct"} + }, + "MapOfStringToString":{ + "type":"map", + "key":{"shape":"String"}, + "value":{"shape":"String"} + }, + "MapOfEnumToEnum":{ + "type":"map", + "key":{"shape":"EnumType"}, + "value":{"shape":"EnumType"} + }, + "MembersInHeadersInput":{ + "type":"structure", + "members":{ + "StringMember":{ + "shape":"String", + "location":"header", + "locationName":"x-amz-string" + }, + "BooleanMember":{ + "shape":"Boolean", + "location":"header", + "locationName":"x-amz-boolean" + }, + "IntegerMember":{ + "shape":"Integer", + "location":"header", + "locationName":"x-amz-integer" + }, + "LongMember":{ + "shape":"Long", + "location":"header", + "locationName":"x-amz-long" + }, + "ShortMember":{ + "shape":"Short", + "location":"header", + "locationName":"x-amz-short" + }, + "FloatMember":{ + "shape":"Float", + "location":"header", + "locationName":"x-amz-float" + }, + "DoubleMember":{ + "shape":"Double", + "location":"header", + "locationName":"x-amz-double" + }, + "TimestampMember":{ + "shape":"Timestamp", + "location":"header", + "locationName":"x-amz-timestamp" + } + } + }, + "MembersInQueryParamsInput":{ + "type":"structure", + "members":{ + "StringQueryParam":{ + "shape":"String", + "location":"querystring", + "locationName":"String" + }, + "BooleanQueryParam":{ + "shape":"Boolean", + "location":"querystring", + "locationName":"Boolean" + }, + "IntegerQueryParam":{ + "shape":"Integer", + "location":"querystring", + "locationName":"Integer" + }, + "LongQueryParam":{ + "shape":"Long", + "location":"querystring", + "locationName":"Long" + }, + "ShortQueryParam":{ + "shape":"Short", + "location":"querystring", + "locationName":"Short" + }, + "FloatQueryParam":{ + "shape":"Float", + "location":"querystring", + "locationName":"Float" + }, + "DoubleQueryParam":{ + "shape":"Double", + "location":"querystring", + "locationName":"Double" + }, + "TimestampQueryParam":{ + "shape":"Timestamp", + "location":"querystring", + "locationName":"Timestamp" + }, + "ListOfStrings":{ + "shape":"ListOfStrings", + "location":"querystring", + "locationName":"item" + }, + "MapOfStringToString":{ + "shape":"MapOfStringToString", + "location":"querystring" + } + } + }, + "MultiLocationOperationInput":{ + "type":"structure", + "required":["PathParam"], + "members":{ + "PathParam":{ + "shape":"String", + "location":"uri", + "locationName":"PathParam" + }, + "QueryParamOne":{ + "shape":"String", + "location":"querystring", + "locationName":"QueryParamOne" + }, + "QueryParamTwo":{ + "shape":"String", + "location":"querystring", + "locationName":"QueryParamTwo" + }, + "StringHeaderMember":{ + "shape":"String", + "location":"header", + "locationName":"x-amz-header-string" + }, + "TimestampHeaderMember":{ + "shape":"Timestamp", + "location":"header", + "locationName":"x-amz-timearg" + }, + "PayloadStructParam":{"shape":"PayloadStructType"} + } + }, + "NestedContainersStructure":{ + "type":"structure", + "members":{ + "ListOfListsOfStrings":{"shape":"ListOfListsOfStrings"}, + "ListOfListOfListsOfStrings":{"shape":"ListOfListOfListsOfStrings"}, + "MapOfStringToListOfListsOfStrings":{"shape":"MapOfStringToListOfListsOfStrings"} + } + }, + "OperationWithExplicitPayloadBlobInput":{ + "type":"structure", + "members":{ + "PayloadMember":{"shape":"BlobType"} + }, + "payload":"PayloadMember" + }, + "OperationWithExplicitPayloadStringInput":{ + "type":"structure", + "members":{ + "PayloadMember":{"shape":"String"} + }, + "payload":"PayloadMember" + }, + "OperationWithExplicitPayloadStructureInput":{ + "type":"structure", + "members":{ + "PayloadMember":{"shape":"SimpleStruct"} + }, + "payload":"PayloadMember" + }, + "OperationWithGreedyLabelInput":{ + "type":"structure", + "required":[ + "NonGreedyPathParam", + "GreedyPathParam" + ], + "members":{ + "NonGreedyPathParam":{ + "shape":"String", + "location":"uri", + "locationName":"NonGreedyPathParam" + }, + "GreedyPathParam":{ + "shape":"String", + "location":"uri", + "locationName":"GreedyPathParam" + } + } + }, + "OperationWithModeledContentTypeInput":{ + "type":"structure", + "members":{ + "ContentType":{ + "shape":"String", + "location":"header", + "locationName":"Content-Type" + } + } + }, + "PaginatedOperationWithResultKeyRequest": { + "type": "structure", + "members": { + "NextToken": { + "shape": "String", + "documentation": "

    Token for the next set of results

    " + }, + "MaxResults": { + "shape": "String", + "documentation": "

    Maximum number of results in a single page

    " + } + } + }, + "PaginatedOperationWithResultKeyResponse": { + "type": "structure", + "members": { + "NextToken": { + "shape": "String", + "documentation": "

    Token for the next set of results

    " + }, + "Items": { + "shape": "ListOfSimpleStructs", + "documentation": "

    Maximum number of results in a single page

    " + } + }, + "documentation": "

    Response type of a single page

    " + }, + "PaginatedOperationWithMoreResultsRequest": { + "type": "structure", + "required": [ + "NextToken" + ], + "members": { + "NextToken": { + "shape": "String", + "documentation": "

    Token for the next set of results

    " + }, + "MaxResults": { + "shape": "String", + "documentation": "

    Maximum number of results in a single page

    " + } + } + }, + "PaginatedOperationWithMoreResultsResponse": { + "type": "structure", + "members": { + "NextToken": { + "shape": "String", + "documentation": "

    Token for the next set of results

    " + }, + "Truncated":{ + "shape":"Boolean", + "documentation":"

    A flag that indicates whether there are more results in the list. When this value is true, the list in this response is truncated.

    " + } + }, + "documentation": "

    Response type of multiple pages

    " + }, + "PayloadStructType":{ + "type":"structure", + "members":{ + "PayloadMemberOne":{"shape":"String"}, + "PayloadMemberTwo":{"shape":"String"} + } + }, + "QueryParamWithoutValueInput":{ + "type":"structure", + "members":{ + } + }, + "RecursiveListType":{ + "type":"list", + "member":{"shape":"RecursiveStructType"} + }, + "RecursiveMapType":{ + "type":"map", + "key":{"shape":"String"}, + "value":{"shape":"RecursiveStructType"} + }, + "RecursiveStructType":{ + "type":"structure", + "members":{ + "NoRecurse":{"shape":"String"}, + "RecursiveStruct":{"shape":"RecursiveStructType"}, + "RecursiveList":{"shape":"RecursiveListType"}, + "RecursiveMap":{"shape":"RecursiveMapType"} + } + }, + "SimpleStruct":{ + "type":"structure", + "members":{ + "StringMember":{"shape":"String"} + } + }, + "StreamType":{ + "type":"blob", + "streaming":true + }, + "String":{"type":"string"}, + "StructWithNestedBlobType":{ + "type":"structure", + "members":{ + "NestedBlob":{"shape":"BlobType"} + } + }, + "StructWithTimestamp":{ + "type":"structure", + "members":{ + "NestedTimestamp":{"shape":"Timestamp"} + } + }, + "StructureWithStreamingMember":{ + "type":"structure", + "members":{ + "StreamingMember":{"shape":"StreamType"} + }, + "payload":"StreamingMember" + }, + "SubTypeOne":{ + "type":"structure", + "members":{ + "SubTypeOneMember":{"shape":"String"} + } + }, + "Timestamp":{"type":"timestamp"}, + "EnumType": { + "type":"string", + "enum": [ + "EnumValue1", "EnumValue2" + ] + }, + "EventStreamOperationRequest": { + "type": "structure", + "required": [ + "InputEventStream" + ], + "members": { + "InputEventStream": { + "shape": "InputEventStream" + } + }, + "payload":"InputEventStream" + }, + "EventStreamOutput": { + "type": "structure", + "required": [ + "EventStream" + ], + "members": { + "EventStream": { + "shape": "EventStream" + } + } + }, + "InputEventStream": { + "type": "structure", + "members": { + "InputEvent": { + "shape": "InputEvent" + } + }, + "eventstream": true + }, + "InputEvent": { + "type": "structure", + "members": { + "ExplicitPayloadMember": { + "shape":"ExplicitPayloadMember", + "eventpayload":true + } + }, + "event": true + }, + "ExplicitPayloadMember":{"type":"blob"}, + "EventStream": { + "type": "structure", + "members": { + "EventOne": { + "shape": "EventOne" + }, + "EventTwo": { + "shape": "EventTwo" + } + }, + "eventstream": true + }, + "EventOne": { + "type": "structure", + "members": { + "Foo": { + "shape": "String" + } + }, + "event": true + }, + "EventTwo": { + "type": "structure", + "members": { + "Bar": { + "shape": "String" + } + }, + "event": true + }, + "ChecksumAlgorithm":{ + "type":"string", + "enum":[ + "CRC32", + "CRC32C", + "SHA1", + "SHA256", + "CRC64NVME" + ] + }, + "ChecksumMode":{ + "type":"string", + "enum":["ENABLED"] + }, + "ChecksumStructureWithStreaming":{ + "type":"structure", + "members":{ + "Body":{ + "shape":"Body", + "documentation":"

    Object data.

    ", + "streaming":true + }, + "ChecksumMode":{ + "shape":"ChecksumMode", + "location":"header", + "locationName":"x-amz-checksum-mode" + }, + "ContentEncoding":{ + "shape":"String", + "location":"header", + "locationName":"Content-Encoding" + }, + "ChecksumAlgorithm":{ + "shape":"ChecksumAlgorithm", + "location":"header", + "locationName":"x-amz-checksum-algorithm" + } + }, + "payload":"Body" + }, + "Body":{"type":"blob"}, + "ChecksumStructure":{ + "type":"structure", + "members":{ + "stringMember":{"shape":"String"}, + "ChecksumMode":{ + "shape":"ChecksumMode", + "location":"header", + "locationName":"x-amz-checksum-mode" + }, + "ContentEncoding":{ + "shape":"String", + "location":"header", + "locationName":"Content-Encoding" + }, + "ChecksumAlgorithm":{ + "shape":"ChecksumAlgorithm", + "location":"header", + "locationName":"x-amz-checksum-algorithm" + } + } + }, + "NestedQueryParameterOperation":{ + "type":"structure", + "required":[ + "QueryParamOne" + ], + "members":{ + "QueryParamOne":{ + "shape":"String", + "location":"querystring", + "locationName":"QueryParamOne" + }, + "QueryParamTwo":{ + "shape":"String", + "location":"querystring", + "locationName":"QueryParamTwo" + } + } + }, + "QueryParameterOperationRequest":{ + "type":"structure", + "required":[ + "PathParam", + "QueryParamOne", + "StringHeaderMember", + "RequiredListQueryParams", + "RequiredMapQueryParams" + ], + "members":{ + "PathParam":{ + "shape":"String", + "location":"uri", + "locationName":"PathParam" + }, + "QueryParamOne":{ + "shape":"String", + "location":"querystring", + "locationName":"QueryParamOne" + }, + "QueryParamTwo":{ + "shape":"String", + "location":"querystring", + "locationName":"QueryParamTwo" + }, + "StringHeaderMember":{ + "shape":"String", + "location":"header", + "locationName":"x-amz-header-string" + }, + "NestedQueryParameterOperation":{ + "shape":"NestedQueryParameterOperation" + }, + "RequiredListQueryParams":{ + "shape":"ListOfIntegers", + "location":"querystring" + }, + "OptionalListQueryParams":{ + "shape":"ListOfStrings", + "location":"querystring" + }, + "RequiredMapQueryParams":{ + "shape":"MapOfStringToString", + "location":"querystring" + } + }, + "payload":"NestedQueryParameterOperation" + }, + "RequestCompressionStructure":{ + "type":"structure", + "members":{ + "Body":{ + "shape":"Body", + "documentation":"

    Object data.

    ", + "streaming":false + } + }, + "payload":"Body" + }, + "RequestCompressionStructureWithStreaming":{ + "type":"structure", + "members":{ + "Body":{ + "shape":"Body", + "documentation":"

    Object data.

    ", + "streaming":true + } + }, + "payload":"Body" + }, + "GetOperationWithMapEndpointParamInput": { + "type": "structure", + "required":["MapOfStrings"], + "members": { + "MapOfStrings":{ + "shape":"MapOfStrings" + } + } + }, + "GetOperationWithMapEndpointParamOutput": { + "type": "structure", + "members": { + "MapOfStrings":{ + "shape":"MapOfStrings" + } + } + }, + "MapOfStrings":{ + "type":"map", + "key":{"shape":"String"}, + "value":{"shape":"String"} + } + } +} diff --git a/test/crt-unavailable-tests/src/test/java/software/amazon/awssdk/checksumtest/Crc64NvmeNotAvailableTest.java b/test/crt-unavailable-tests/src/test/java/software/amazon/awssdk/checksumtest/Crc64NvmeNotAvailableTest.java new file mode 100644 index 000000000000..a5165acc186f --- /dev/null +++ b/test/crt-unavailable-tests/src/test/java/software/amazon/awssdk/checksumtest/Crc64NvmeNotAvailableTest.java @@ -0,0 +1,188 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.checksumtest; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static software.amazon.awssdk.auth.signer.S3SignerExecutionAttribute.ENABLE_CHUNKED_ENCODING; + +import io.reactivex.Flowable; +import java.io.IOException; +import java.util.concurrent.CompletableFuture; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import software.amazon.awssdk.auth.credentials.AnonymousCredentialsProvider; +import software.amazon.awssdk.core.SdkRequest; +import software.amazon.awssdk.core.async.AsyncResponseTransformer; +import software.amazon.awssdk.core.checksums.ChecksumValidation; +import software.amazon.awssdk.core.interceptor.Context; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; +import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; +import software.amazon.awssdk.core.interceptor.SdkExecutionAttribute; +import software.amazon.awssdk.core.sync.ResponseTransformer; +import software.amazon.awssdk.http.ExecutableHttpRequest; +import software.amazon.awssdk.http.HttpExecuteResponse; +import software.amazon.awssdk.http.SdkHttpClient; +import software.amazon.awssdk.http.SdkHttpFullResponse; +import software.amazon.awssdk.http.async.AsyncExecuteRequest; +import software.amazon.awssdk.http.async.SdkAsyncHttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.protocolrestjson.ProtocolRestJsonAsyncClient; +import software.amazon.awssdk.services.protocolrestjson.ProtocolRestJsonAsyncClientBuilder; +import software.amazon.awssdk.services.protocolrestjson.ProtocolRestJsonClient; +import software.amazon.awssdk.services.protocolrestjson.ProtocolRestJsonClientBuilder; +import software.amazon.awssdk.services.protocolrestjson.model.ChecksumAlgorithm; +import software.amazon.awssdk.services.protocolrestjson.model.ChecksumMode; +import software.amazon.awssdk.services.protocolrestjson.model.OperationWithCustomRequestChecksumRequest; +import software.amazon.awssdk.services.protocolrestjson.model.PutOperationWithChecksumRequest; + +public class Crc64NvmeNotAvailableTest { + private SdkHttpClient httpClient; + private SdkAsyncHttpClient httpAsyncClient; + private ProtocolRestJsonAsyncClient asyncClient; + private ProtocolRestJsonClient client; + + @BeforeEach + public void setup() throws IOException { + httpClient = Mockito.mock(SdkHttpClient.class); + httpAsyncClient = Mockito.mock(SdkAsyncHttpClient.class); + client = initializeSync().build(); + asyncClient = initializeAsync().build(); + } + + private void stubResponse(SdkHttpFullResponse.Builder responseBuilder) throws IOException { + SdkHttpFullResponse successfulHttpResponse = responseBuilder + .statusCode(200) + .putHeader("Content-Length", "0") + .build(); + + ExecutableHttpRequest request = Mockito.mock(ExecutableHttpRequest.class); + Mockito.when(request.call()).thenReturn(HttpExecuteResponse.builder() + .response(successfulHttpResponse) + .build()); + Mockito.when(httpClient.prepareRequest(any())).thenReturn(request); + + Mockito.when(httpAsyncClient.execute(any())).thenAnswer(invocation -> { + AsyncExecuteRequest asyncExecuteRequest = invocation.getArgument(0, AsyncExecuteRequest.class); + asyncExecuteRequest.responseHandler().onHeaders(successfulHttpResponse); + asyncExecuteRequest.responseHandler().onStream(Flowable.empty()); + return CompletableFuture.completedFuture(null); + }); + } + + private ProtocolRestJsonAsyncClientBuilder initializeAsync() { + return ProtocolRestJsonAsyncClient.builder().httpClient(httpAsyncClient) + .credentialsProvider(AnonymousCredentialsProvider.create()) + .overrideConfiguration( + // TODO(sra-identity-and-auth): we should remove these + // overrides once we set up codegen to set chunk-encoding to true + // for requests that are streaming and checksum-enabled + o -> o.addExecutionInterceptor(new EnableChunkedEncodingInterceptor()) + .addExecutionInterceptor(new CaptureChecksumValidationInterceptor())) + .region(Region.US_WEST_2); + } + + private ProtocolRestJsonClientBuilder initializeSync() { + return ProtocolRestJsonClient.builder().httpClient(httpClient) + .credentialsProvider(AnonymousCredentialsProvider.create()) + .overrideConfiguration( + // // TODO(sra-identity-and-auth): we should remove these + // // overrides once we set up codegen to set chunk-encoding to true + // // for requests that are streaming and checksum-enabled + o -> o.addExecutionInterceptor(new EnableChunkedEncodingInterceptor()) + .addExecutionInterceptor(new CaptureChecksumValidationInterceptor())) + .region(Region.US_WEST_2); + } + + @Test + public void asyncChecksumCalculation_crc64NvmeNotAvailable_shouldThrowException() throws IOException { + stubResponse(SdkHttpFullResponse.builder()); + assertThatThrownBy(() -> asyncClient.operationWithCustomRequestChecksum( + OperationWithCustomRequestChecksumRequest.builder() + .checksumAlgorithm(ChecksumAlgorithm.CRC64_NVME) + .build()).join()).hasMessageContaining("Add dependency on " + + "'software.amazon.awssdk" + + ".crt:aws-crt' module to " + + "enable CRC64NVME feature"); + } + + @Test + public void syncChecksumCalculation_crc64NvmeNotAvailable_shouldThrowException() throws IOException { + stubResponse(SdkHttpFullResponse.builder()); + assertThatThrownBy(() -> client.operationWithCustomRequestChecksum( + OperationWithCustomRequestChecksumRequest.builder() + .checksumAlgorithm(ChecksumAlgorithm.CRC64_NVME) + .build())).hasMessageContaining("Add dependency on " + + "'software.amazon.awssdk" + + ".crt:aws-crt' module to " + + "enable CRC64NVME feature"); + } + + @Test + public void syncChecksumValidation_onlyHasCrc64Nvme_shouldSkipValidation() throws IOException { + stubResponse(SdkHttpFullResponse.builder().putHeader("x-amz-checksum-crc64nvme", "foobar")); + + client.getOperationWithChecksum( + r -> r.checksumMode(ChecksumMode.ENABLED), + ResponseTransformer.toBytes()); + + assertThat(CaptureChecksumValidationInterceptor.checksumValidation).isEqualTo(ChecksumValidation.CHECKSUM_ALGORITHM_NOT_FOUND); + assertThat(CaptureChecksumValidationInterceptor.expectedAlgorithm).isNull(); + } + + @Test + public void asyncChecksumValidation_onlyHasCrc64Nvme_shouldSkipValidation() throws IOException { + stubResponse(SdkHttpFullResponse.builder().putHeader("x-amz-checksum-crc64nvme", "foobar")); + + asyncClient.getOperationWithChecksum( + r -> r.checksumMode(ChecksumMode.ENABLED), + AsyncResponseTransformer.toBytes()).join(); + + assertThat(CaptureChecksumValidationInterceptor.checksumValidation).isEqualTo(ChecksumValidation.CHECKSUM_ALGORITHM_NOT_FOUND); + assertThat(CaptureChecksumValidationInterceptor.expectedAlgorithm).isNull(); + } + + + private static final class EnableChunkedEncodingInterceptor implements ExecutionInterceptor { + public void beforeExecution(Context.BeforeExecution context, ExecutionAttributes executionAttributes) { + SdkRequest request = context.request(); + + if (request instanceof PutOperationWithChecksumRequest) { + executionAttributes.putAttributeIfAbsent(ENABLE_CHUNKED_ENCODING, true); + } + } + } + + private static class CaptureChecksumValidationInterceptor implements ExecutionInterceptor { + private static software.amazon.awssdk.checksums.spi.ChecksumAlgorithm expectedAlgorithm; + private static ChecksumValidation checksumValidation; + + public static void reset() { + expectedAlgorithm = null; + checksumValidation = null; + } + + @Override + public void afterExecution(Context.AfterExecution context, ExecutionAttributes executionAttributes) { + expectedAlgorithm = + executionAttributes.getOptionalAttribute(SdkExecutionAttribute.HTTP_CHECKSUM_VALIDATION_ALGORITHM_V2).orElse(null); + checksumValidation = + executionAttributes.getOptionalAttribute(SdkExecutionAttribute.HTTP_RESPONSE_CHECKSUM_VALIDATION).orElse(null); + } + } +} diff --git a/test/http-client-tests/pom.xml b/test/http-client-tests/pom.xml index b9cc0f2c2d18..5c94e4ccf3af 100644 --- a/test/http-client-tests/pom.xml +++ b/test/http-client-tests/pom.xml @@ -21,7 +21,7 @@ aws-sdk-java-pom software.amazon.awssdk - 2.29.52 + 2.30.0 ../../pom.xml http-client-tests diff --git a/test/module-path-tests/pom.xml b/test/module-path-tests/pom.xml index 39bf0c14f47f..4f80ca63e669 100644 --- a/test/module-path-tests/pom.xml +++ b/test/module-path-tests/pom.xml @@ -20,7 +20,7 @@ aws-sdk-java-pom software.amazon.awssdk - 2.29.52 + 2.30.0 ../../pom.xml 4.0.0 diff --git a/test/old-client-version-compatibility-test/pom.xml b/test/old-client-version-compatibility-test/pom.xml index 02fe9abfb699..549dcbd6ef13 100644 --- a/test/old-client-version-compatibility-test/pom.xml +++ b/test/old-client-version-compatibility-test/pom.xml @@ -21,7 +21,7 @@ aws-sdk-java-pom software.amazon.awssdk - 2.29.52 + 2.30.0 ../../pom.xml diff --git a/test/old-client-version-compatibility-test/src/it/resources/log4j2.properties b/test/old-client-version-compatibility-test/src/it/resources/log4j2.properties index 340e7c449d54..e5e68dd2faa4 100644 --- a/test/old-client-version-compatibility-test/src/it/resources/log4j2.properties +++ b/test/old-client-version-compatibility-test/src/it/resources/log4j2.properties @@ -20,7 +20,7 @@ appender.console.name = ConsoleAppender appender.console.layout.type = PatternLayout appender.console.layout.pattern = %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n%throwable -rootLogger.level = debug +rootLogger.level = info rootLogger.appenderRef.stdout.ref = ConsoleAppender # Uncomment below to enable more specific logging diff --git a/test/protocol-tests-core/pom.xml b/test/protocol-tests-core/pom.xml index c862e31e2cec..a3d7ab0519f4 100644 --- a/test/protocol-tests-core/pom.xml +++ b/test/protocol-tests-core/pom.xml @@ -20,7 +20,7 @@ aws-sdk-java-pom software.amazon.awssdk - 2.29.52 + 2.30.0 ../../pom.xml 4.0.0 diff --git a/test/protocol-tests/pom.xml b/test/protocol-tests/pom.xml index aa6e57e5f1ba..48d509e46e7a 100644 --- a/test/protocol-tests/pom.xml +++ b/test/protocol-tests/pom.xml @@ -20,7 +20,7 @@ aws-sdk-java-pom software.amazon.awssdk - 2.29.52 + 2.30.0 ../../pom.xml 4.0.0 diff --git a/test/region-testing/pom.xml b/test/region-testing/pom.xml index a24fe2343dd6..bd9462d87a2e 100644 --- a/test/region-testing/pom.xml +++ b/test/region-testing/pom.xml @@ -20,7 +20,7 @@ aws-sdk-java-pom software.amazon.awssdk - 2.29.52 + 2.30.0 ../../pom.xml 4.0.0 diff --git a/test/ruleset-testing-core/pom.xml b/test/ruleset-testing-core/pom.xml index ca167cdb1f91..4e290ac1dd6c 100644 --- a/test/ruleset-testing-core/pom.xml +++ b/test/ruleset-testing-core/pom.xml @@ -20,7 +20,7 @@ aws-sdk-java-pom software.amazon.awssdk - 2.29.52 + 2.30.0 ../../pom.xml 4.0.0 diff --git a/test/s3-benchmarks/pom.xml b/test/s3-benchmarks/pom.xml index c338c26e9689..37d31182734d 100644 --- a/test/s3-benchmarks/pom.xml +++ b/test/s3-benchmarks/pom.xml @@ -20,7 +20,7 @@ aws-sdk-java-pom software.amazon.awssdk - 2.29.52 + 2.30.0 ../../pom.xml 4.0.0 diff --git a/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/BaseCrtClientBenchmark.java b/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/BaseCrtClientBenchmark.java index 1a0ba864a7d3..f95a9db52251 100644 --- a/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/BaseCrtClientBenchmark.java +++ b/test/s3-benchmarks/src/main/java/software/amazon/awssdk/s3benchmarks/BaseCrtClientBenchmark.java @@ -60,7 +60,6 @@ protected BaseCrtClientBenchmark(TransferManagerBenchmarkConfig config) { .targetThroughputInGbps(config.targetThroughput() == null ? Double.valueOf(100.0) : config.targetThroughput()) - .checksumValidationEnabled(true) .build(); this.bucket = config.bucket(); diff --git a/test/sdk-benchmarks/pom.xml b/test/sdk-benchmarks/pom.xml index 69ee46025c6c..2762721f2359 100644 --- a/test/sdk-benchmarks/pom.xml +++ b/test/sdk-benchmarks/pom.xml @@ -19,7 +19,7 @@ software.amazon.awssdk aws-sdk-java-pom - 2.29.52 + 2.30.0 ../../pom.xml diff --git a/test/sdk-native-image-test/pom.xml b/test/sdk-native-image-test/pom.xml index 283a9d8dcf6f..54e92ace3fa6 100644 --- a/test/sdk-native-image-test/pom.xml +++ b/test/sdk-native-image-test/pom.xml @@ -20,7 +20,7 @@ aws-sdk-java-pom software.amazon.awssdk - 2.29.52 + 2.30.0 ../../pom.xml 4.0.0 diff --git a/test/service-test-utils/pom.xml b/test/service-test-utils/pom.xml index 393475345ae1..d8a5e4b76484 100644 --- a/test/service-test-utils/pom.xml +++ b/test/service-test-utils/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk aws-sdk-java-pom - 2.29.52 + 2.30.0 ../../pom.xml service-test-utils diff --git a/test/stability-tests/pom.xml b/test/stability-tests/pom.xml index 4cf28bb2a502..3e08c52fabc6 100644 --- a/test/stability-tests/pom.xml +++ b/test/stability-tests/pom.xml @@ -20,7 +20,7 @@ aws-sdk-java-pom software.amazon.awssdk - 2.29.52 + 2.30.0 ../../pom.xml 4.0.0 diff --git a/test/test-utils/pom.xml b/test/test-utils/pom.xml index e8eabbb88ffb..9589b30f2e73 100644 --- a/test/test-utils/pom.xml +++ b/test/test-utils/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk aws-sdk-java-pom - 2.29.52 + 2.30.0 ../../pom.xml test-utils diff --git a/test/tests-coverage-reporting/pom.xml b/test/tests-coverage-reporting/pom.xml index e09cc5c0926f..554f3d0199b8 100644 --- a/test/tests-coverage-reporting/pom.xml +++ b/test/tests-coverage-reporting/pom.xml @@ -20,7 +20,7 @@ aws-sdk-java-pom software.amazon.awssdk - 2.29.52 + 2.30.0 ../../pom.xml 4.0.0 diff --git a/test/v2-migration-tests/pom.xml b/test/v2-migration-tests/pom.xml index 00347ced9522..81f8db64e65c 100644 --- a/test/v2-migration-tests/pom.xml +++ b/test/v2-migration-tests/pom.xml @@ -22,7 +22,7 @@ software.amazon.awssdk aws-sdk-java-pom - 2.29.52 + 2.30.0 ../.. diff --git a/test/v2-migration-tests/src/test/resources/software/amazon/awssdk/v2migrationtests/maven/after/src/main/java/foo/bar/SdkBytes.java b/test/v2-migration-tests/src/test/resources/software/amazon/awssdk/v2migrationtests/maven/after/src/main/java/foo/bar/SdkBytes.java new file mode 100644 index 000000000000..a91289ce0254 --- /dev/null +++ b/test/v2-migration-tests/src/test/resources/software/amazon/awssdk/v2migrationtests/maven/after/src/main/java/foo/bar/SdkBytes.java @@ -0,0 +1,29 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package foo.bar; + +import java.nio.ByteBuffer; +import software.amazon.awssdk.services.sqs.model.MessageAttributeValue; + +public class SdkBytes { + + void sdkBytesGetters() { + MessageAttributeValue messageAttributeValue = MessageAttributeValue.builder() + .build(); + ByteBuffer binaryValue = messageAttributeValue.binaryValue().asByteBuffer(); + String binaryString = new String(messageAttributeValue.binaryValue().asByteBuffer().array()); + } +} diff --git a/test/v2-migration-tests/src/test/resources/software/amazon/awssdk/v2migrationtests/maven/before/src/main/java/foo/bar/SdkBytes.java b/test/v2-migration-tests/src/test/resources/software/amazon/awssdk/v2migrationtests/maven/before/src/main/java/foo/bar/SdkBytes.java new file mode 100644 index 000000000000..36bad73c8177 --- /dev/null +++ b/test/v2-migration-tests/src/test/resources/software/amazon/awssdk/v2migrationtests/maven/before/src/main/java/foo/bar/SdkBytes.java @@ -0,0 +1,28 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package foo.bar; + +import com.amazonaws.services.sqs.model.MessageAttributeValue; +import java.nio.ByteBuffer; + +public class SdkBytes { + + void sdkBytesGetters() { + MessageAttributeValue messageAttributeValue = new MessageAttributeValue(); + ByteBuffer binaryValue = messageAttributeValue.getBinaryValue(); + String binaryString = new String(messageAttributeValue.getBinaryValue().array()); + } +} diff --git a/third-party/pom.xml b/third-party/pom.xml index 71c5d6f0bad1..eca10a1e0c9e 100644 --- a/third-party/pom.xml +++ b/third-party/pom.xml @@ -21,7 +21,7 @@ aws-sdk-java-pom software.amazon.awssdk - 2.29.52 + 2.30.0 third-party diff --git a/third-party/third-party-jackson-core/pom.xml b/third-party/third-party-jackson-core/pom.xml index 1c50986fc03b..8f5cc07ba7f6 100644 --- a/third-party/third-party-jackson-core/pom.xml +++ b/third-party/third-party-jackson-core/pom.xml @@ -20,7 +20,7 @@ third-party software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 diff --git a/third-party/third-party-jackson-dataformat-cbor/pom.xml b/third-party/third-party-jackson-dataformat-cbor/pom.xml index 728127f60071..0a9eb87db323 100644 --- a/third-party/third-party-jackson-dataformat-cbor/pom.xml +++ b/third-party/third-party-jackson-dataformat-cbor/pom.xml @@ -20,7 +20,7 @@ third-party software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 diff --git a/third-party/third-party-slf4j-api/pom.xml b/third-party/third-party-slf4j-api/pom.xml index 68f16e72b8e9..ea80fe0a3323 100644 --- a/third-party/third-party-slf4j-api/pom.xml +++ b/third-party/third-party-slf4j-api/pom.xml @@ -20,7 +20,7 @@ third-party software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 diff --git a/utils/pom.xml b/utils/pom.xml index 9fcf43df49a4..032b30143fa1 100644 --- a/utils/pom.xml +++ b/utils/pom.xml @@ -20,7 +20,7 @@ aws-sdk-java-pom software.amazon.awssdk - 2.29.52 + 2.30.0 4.0.0 diff --git a/v2-migration/pom.xml b/v2-migration/pom.xml index 60ed123cb7f1..57890cd953d0 100644 --- a/v2-migration/pom.xml +++ b/v2-migration/pom.xml @@ -21,7 +21,7 @@ software.amazon.awssdk aws-sdk-java-pom - 2.29.52 + 2.30.0 ../pom.xml diff --git a/v2-migration/src/main/java/software/amazon/awssdk/v2migration/SdkBytesToByteBuffer.java b/v2-migration/src/main/java/software/amazon/awssdk/v2migration/SdkBytesToByteBuffer.java new file mode 100644 index 000000000000..a7d0445beebd --- /dev/null +++ b/v2-migration/src/main/java/software/amazon/awssdk/v2migration/SdkBytesToByteBuffer.java @@ -0,0 +1,88 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.v2migration; + +import java.nio.ByteBuffer; +import java.util.regex.Pattern; +import org.openrewrite.ExecutionContext; +import org.openrewrite.NlsRewrite; +import org.openrewrite.Recipe; +import org.openrewrite.TreeVisitor; +import org.openrewrite.java.JavaIsoVisitor; +import org.openrewrite.java.JavaTemplate; +import org.openrewrite.java.tree.J; +import org.openrewrite.java.tree.JavaType.FullyQualified; +import org.openrewrite.java.tree.JavaType.Method; +import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.v2migration.internal.utils.SdkTypeUtils; + +@SdkInternalApi +public class SdkBytesToByteBuffer extends Recipe { + private static final Pattern BYTE_BUFFER_PATTERN = Pattern.compile(ByteBuffer.class.getCanonicalName()); + + @Override + public @NlsRewrite.DisplayName String getDisplayName() { + return "Convert SdkBytes to ByteBuffer"; + } + + @Override + public @NlsRewrite.Description String getDescription() { + return "Convert SdkBytes to ByteBuffer by calling SdkBytes#asByteBuffer()"; + } + + @Override + public TreeVisitor getVisitor() { + return new SdkBytesToBufferVisitor(); + } + + private static boolean isV2ModelGetterReturningByteBuffer(J.MethodInvocation method) { + Method mt = method.getMethodType(); + + if (mt != null) { + FullyQualified declaringType = mt.getDeclaringType(); + boolean isByteBuffer = mt.getReturnType().isAssignableFrom(BYTE_BUFFER_PATTERN); + if (SdkTypeUtils.isV2ModelClass(declaringType) && isByteBuffer) { + return true; + } + } + return false; + } + + private static final class SdkBytesToBufferVisitor extends JavaIsoVisitor { + @Override + public J.MethodInvocation visitMethodInvocation(J.MethodInvocation originalMethod, + ExecutionContext executionContext) { + J.MethodInvocation method = + super.visitMethodInvocation(originalMethod, executionContext); + if (!isV2ModelGetterReturningByteBuffer(method)) { + return method; + } + + String methodName = method.getSimpleName(); + JavaTemplate template = JavaTemplate + .builder(method.getSelect() + "." + methodName + "()." + "asByteBuffer()") + .contextSensitive() + .build(); + + method = template.apply( + updateCursor(method), + method.getCoordinates().replace() + ); + + return method; + } + } +} diff --git a/v2-migration/src/main/resources/META-INF/rewrite/aws-sdk-java-v1-to-v2.yml b/v2-migration/src/main/resources/META-INF/rewrite/aws-sdk-java-v1-to-v2.yml index 575c06ed787c..84a2dee86556 100644 --- a/v2-migration/src/main/resources/META-INF/rewrite/aws-sdk-java-v1-to-v2.yml +++ b/v2-migration/src/main/resources/META-INF/rewrite/aws-sdk-java-v1-to-v2.yml @@ -37,4 +37,5 @@ recipeList: - software.amazon.awssdk.v2migration.V1GetterToV2 - software.amazon.awssdk.v2migration.HttpSettingsToHttpClient - software.amazon.awssdk.v2migration.WrapSdkClientBuilderRegionStr - - software.amazon.awssdk.v2migration.EnumCasingToV2 \ No newline at end of file + - software.amazon.awssdk.v2migration.EnumCasingToV2 + - software.amazon.awssdk.v2migration.SdkBytesToByteBuffer \ No newline at end of file diff --git a/v2-migration/src/main/resources/META-INF/rewrite/upgrade-sdk-dependencies.yml b/v2-migration/src/main/resources/META-INF/rewrite/upgrade-sdk-dependencies.yml index 38c5d38b95da..a27130d51c1f 100644 --- a/v2-migration/src/main/resources/META-INF/rewrite/upgrade-sdk-dependencies.yml +++ b/v2-migration/src/main/resources/META-INF/rewrite/upgrade-sdk-dependencies.yml @@ -21,2285 +21,2285 @@ recipeList: - org.openrewrite.java.dependencies.AddDependency: groupId: software.amazon.awssdk artifactId: apache-client - version: 2.29.51 + version: 2.29.52 onlyIfUsing: com.amazonaws.ClientConfiguration - org.openrewrite.java.dependencies.AddDependency: groupId: software.amazon.awssdk artifactId: netty-nio-client - version: 2.29.51 + version: 2.29.52 onlyIfUsing: com.amazonaws.ClientConfiguration - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-core newGroupId: software.amazon.awssdk newArtifactId: aws-core - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-bom newGroupId: software.amazon.awssdk newArtifactId: bom - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-iot newGroupId: software.amazon.awssdk newArtifactId: iotdataplane - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-oam newGroupId: software.amazon.awssdk newArtifactId: oam - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-iotwireless newGroupId: software.amazon.awssdk newArtifactId: iotwireless - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-forecast newGroupId: software.amazon.awssdk newArtifactId: forecast - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-licensemanagerlinuxsubscriptions newGroupId: software.amazon.awssdk newArtifactId: licensemanagerlinuxsubscriptions - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-docdbelastic newGroupId: software.amazon.awssdk newArtifactId: docdbelastic - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-emrcontainers newGroupId: software.amazon.awssdk newArtifactId: emrcontainers - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-timestreamwrite newGroupId: software.amazon.awssdk newArtifactId: timestreamwrite - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-codebuild newGroupId: software.amazon.awssdk newArtifactId: codebuild - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-iotdeviceadvisor newGroupId: software.amazon.awssdk newArtifactId: iotdeviceadvisor - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-ssmcontacts newGroupId: software.amazon.awssdk newArtifactId: ssmcontacts - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-pcaconnectorscep newGroupId: software.amazon.awssdk newArtifactId: pcaconnectorscep - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-paymentcryptographydata newGroupId: software.amazon.awssdk newArtifactId: paymentcryptographydata - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-codeguruprofiler newGroupId: software.amazon.awssdk newArtifactId: codeguruprofiler - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-kinesis newGroupId: software.amazon.awssdk newArtifactId: kinesis - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-kinesisvideo newGroupId: software.amazon.awssdk newArtifactId: kinesisvideo - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-pinpoint newGroupId: software.amazon.awssdk newArtifactId: pinpoint - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-chime newGroupId: software.amazon.awssdk newArtifactId: chime - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-iottwinmaker newGroupId: software.amazon.awssdk newArtifactId: iottwinmaker - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-organizations newGroupId: software.amazon.awssdk newArtifactId: organizations - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-licensemanager newGroupId: software.amazon.awssdk newArtifactId: licensemanager - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-shield newGroupId: software.amazon.awssdk newArtifactId: shield - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-ssm newGroupId: software.amazon.awssdk newArtifactId: ssm - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-mediastoredata newGroupId: software.amazon.awssdk newArtifactId: mediastoredata - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-sagemakerruntime newGroupId: software.amazon.awssdk newArtifactId: sagemakerruntime - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-signer newGroupId: software.amazon.awssdk newArtifactId: signer - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-servicecatalog newGroupId: software.amazon.awssdk newArtifactId: servicecatalog - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-timestreaminfluxdb newGroupId: software.amazon.awssdk newArtifactId: timestreaminfluxdb - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-lakeformation newGroupId: software.amazon.awssdk newArtifactId: lakeformation - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-pcs newGroupId: software.amazon.awssdk newArtifactId: pcs - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-licensemanagerusersubscriptions newGroupId: software.amazon.awssdk newArtifactId: licensemanagerusersubscriptions - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-secretsmanager newGroupId: software.amazon.awssdk newArtifactId: secretsmanager - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-mediaconnect newGroupId: software.amazon.awssdk newArtifactId: mediaconnect - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-mwaa newGroupId: software.amazon.awssdk newArtifactId: mwaa - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-kms newGroupId: software.amazon.awssdk newArtifactId: kms - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-quicksight newGroupId: software.amazon.awssdk newArtifactId: quicksight - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-workmail newGroupId: software.amazon.awssdk newArtifactId: workmail - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-eventbridge newGroupId: software.amazon.awssdk newArtifactId: eventbridge - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-sagemakergeospatial newGroupId: software.amazon.awssdk newArtifactId: sagemakergeospatial - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-frauddetector newGroupId: software.amazon.awssdk newArtifactId: frauddetector - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-elastictranscoder newGroupId: software.amazon.awssdk newArtifactId: elastictranscoder - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-elasticinference newGroupId: software.amazon.awssdk newArtifactId: elasticinference - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-lookoutequipment newGroupId: software.amazon.awssdk newArtifactId: lookoutequipment - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-pcaconnectorad newGroupId: software.amazon.awssdk newArtifactId: pcaconnectorad - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-pinpointsmsvoice newGroupId: software.amazon.awssdk newArtifactId: pinpointsmsvoice - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-securitylake newGroupId: software.amazon.awssdk newArtifactId: securitylake - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-cloudwatch newGroupId: software.amazon.awssdk newArtifactId: cloudwatch - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-cloudwatchmetrics newGroupId: software.amazon.awssdk newArtifactId: cloudwatch - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-glue newGroupId: software.amazon.awssdk newArtifactId: glue - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-costoptimizationhub newGroupId: software.amazon.awssdk newArtifactId: costoptimizationhub - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-servicequotas newGroupId: software.amazon.awssdk newArtifactId: servicequotas - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-s3 newGroupId: software.amazon.awssdk newArtifactId: s3 - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-appintegrations newGroupId: software.amazon.awssdk newArtifactId: appintegrations - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-sesv2 newGroupId: software.amazon.awssdk newArtifactId: sesv2 - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-arczonalshift newGroupId: software.amazon.awssdk newArtifactId: arczonalshift - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-emr newGroupId: software.amazon.awssdk newArtifactId: emr - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-controltower newGroupId: software.amazon.awssdk newArtifactId: controltower - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-iotfleethub newGroupId: software.amazon.awssdk newArtifactId: iotfleethub - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-personalize newGroupId: software.amazon.awssdk newArtifactId: personalize - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-outposts newGroupId: software.amazon.awssdk newArtifactId: outposts - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-workdocs newGroupId: software.amazon.awssdk newArtifactId: workdocs - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-networkmanager newGroupId: software.amazon.awssdk newArtifactId: networkmanager - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-omics newGroupId: software.amazon.awssdk newArtifactId: omics - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-mediapackage newGroupId: software.amazon.awssdk newArtifactId: mediapackage - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-medialive newGroupId: software.amazon.awssdk newArtifactId: medialive - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-mediaconvert newGroupId: software.amazon.awssdk newArtifactId: mediaconvert - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-marketplaceagreement newGroupId: software.amazon.awssdk newArtifactId: marketplaceagreement - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-cognitosync newGroupId: software.amazon.awssdk newArtifactId: cognitosync - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-sns newGroupId: software.amazon.awssdk newArtifactId: sns - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-datasync newGroupId: software.amazon.awssdk newArtifactId: datasync - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-sagemakeredgemanager newGroupId: software.amazon.awssdk newArtifactId: sagemakeredge - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-greengrassv2 newGroupId: software.amazon.awssdk newArtifactId: greengrassv2 - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-pinpointemail newGroupId: software.amazon.awssdk newArtifactId: pinpointemail - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-cleanroomsml newGroupId: software.amazon.awssdk newArtifactId: cleanroomsml - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-augmentedairuntime newGroupId: software.amazon.awssdk newArtifactId: sagemakera2iruntime - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-neptunedata newGroupId: software.amazon.awssdk newArtifactId: neptunedata - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-b2bi newGroupId: software.amazon.awssdk newArtifactId: b2bi - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-iotanalytics newGroupId: software.amazon.awssdk newArtifactId: iotanalytics - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-inspector2 newGroupId: software.amazon.awssdk newArtifactId: inspector2 - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-groundstation newGroupId: software.amazon.awssdk newArtifactId: groundstation - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-fis newGroupId: software.amazon.awssdk newArtifactId: fis - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-proton newGroupId: software.amazon.awssdk newArtifactId: proton - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-voiceid newGroupId: software.amazon.awssdk newArtifactId: voiceid - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-cloudhsm newGroupId: software.amazon.awssdk newArtifactId: cloudhsm - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-ecrpublic newGroupId: software.amazon.awssdk newArtifactId: ecrpublic - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-servermigration newGroupId: software.amazon.awssdk newArtifactId: sms - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-cloudtraildata newGroupId: software.amazon.awssdk newArtifactId: cloudtraildata - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-cognitoidentity newGroupId: software.amazon.awssdk newArtifactId: cognitoidentity - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-config newGroupId: software.amazon.awssdk newArtifactId: config - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-osis newGroupId: software.amazon.awssdk newArtifactId: osis - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-private5g newGroupId: software.amazon.awssdk newArtifactId: privatenetworks - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-memorydb newGroupId: software.amazon.awssdk newArtifactId: memorydb - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-inspector newGroupId: software.amazon.awssdk newArtifactId: inspector - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-translate newGroupId: software.amazon.awssdk newArtifactId: translate - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-mailmanager newGroupId: software.amazon.awssdk newArtifactId: mailmanager - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-paymentcryptography newGroupId: software.amazon.awssdk newArtifactId: paymentcryptography - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-chatbot newGroupId: software.amazon.awssdk newArtifactId: chatbot - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-fms newGroupId: software.amazon.awssdk newArtifactId: fms - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-ssmincidents newGroupId: software.amazon.awssdk newArtifactId: ssmincidents - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-vpclattice newGroupId: software.amazon.awssdk newArtifactId: vpclattice - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-s3control newGroupId: software.amazon.awssdk newArtifactId: s3control - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-qapps newGroupId: software.amazon.awssdk newArtifactId: qapps - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-rdsdata newGroupId: software.amazon.awssdk newArtifactId: rdsdata - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-kinesisanalyticsv2 newGroupId: software.amazon.awssdk newArtifactId: kinesisanalyticsv2 - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-qbusiness newGroupId: software.amazon.awssdk newArtifactId: qbusiness - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-marketplacecommerceanalytics newGroupId: software.amazon.awssdk newArtifactId: marketplacecommerceanalytics - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-synthetics newGroupId: software.amazon.awssdk newArtifactId: synthetics - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-apptest newGroupId: software.amazon.awssdk newArtifactId: apptest - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-costexplorer newGroupId: software.amazon.awssdk newArtifactId: costexplorer - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-iotsecuretunneling newGroupId: software.amazon.awssdk newArtifactId: iotsecuretunneling - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-cloudfront newGroupId: software.amazon.awssdk newArtifactId: cloudfront - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-location newGroupId: software.amazon.awssdk newArtifactId: location - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-wafv2 newGroupId: software.amazon.awssdk newArtifactId: wafv2 - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-opensearch newGroupId: software.amazon.awssdk newArtifactId: opensearch - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-ec2instanceconnect newGroupId: software.amazon.awssdk newArtifactId: ec2instanceconnect - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-iotthingsgraph newGroupId: software.amazon.awssdk newArtifactId: iotthingsgraph - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-repostspace newGroupId: software.amazon.awssdk newArtifactId: repostspace - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-route53recoveryreadiness newGroupId: software.amazon.awssdk newArtifactId: route53recoveryreadiness - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-health newGroupId: software.amazon.awssdk newArtifactId: health - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-workmailmessageflow newGroupId: software.amazon.awssdk newArtifactId: workmailmessageflow - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-comprehendmedical newGroupId: software.amazon.awssdk newArtifactId: comprehendmedical - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-iotfleetwise newGroupId: software.amazon.awssdk newArtifactId: iotfleetwise - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-route53profiles newGroupId: software.amazon.awssdk newArtifactId: route53profiles - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-bcmdataexports newGroupId: software.amazon.awssdk newArtifactId: bcmdataexports - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-accessanalyzer newGroupId: software.amazon.awssdk newArtifactId: accessanalyzer - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-glacier newGroupId: software.amazon.awssdk newArtifactId: glacier - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-lightsail newGroupId: software.amazon.awssdk newArtifactId: lightsail - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-cloudwatchrum newGroupId: software.amazon.awssdk newArtifactId: rum - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-inspectorscan newGroupId: software.amazon.awssdk newArtifactId: inspectorscan - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-imagebuilder newGroupId: software.amazon.awssdk newArtifactId: imagebuilder - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-sagemakermetrics newGroupId: software.amazon.awssdk newArtifactId: sagemakermetrics - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-bedrockagent newGroupId: software.amazon.awssdk newArtifactId: bedrockagent - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-migrationhub newGroupId: software.amazon.awssdk newArtifactId: migrationhub - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-simspaceweaver newGroupId: software.amazon.awssdk newArtifactId: simspaceweaver - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-elasticbeanstalk newGroupId: software.amazon.awssdk newArtifactId: elasticbeanstalk - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-freetier newGroupId: software.amazon.awssdk newArtifactId: freetier - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-cloudsearch newGroupId: software.amazon.awssdk newArtifactId: cloudsearchdomain - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-neptune newGroupId: software.amazon.awssdk newArtifactId: neptune - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-supportapp newGroupId: software.amazon.awssdk newArtifactId: supportapp - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-transfer newGroupId: software.amazon.awssdk newArtifactId: transfer - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-deadline newGroupId: software.amazon.awssdk newArtifactId: deadline - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-braket newGroupId: software.amazon.awssdk newArtifactId: braket - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-verifiedpermissions newGroupId: software.amazon.awssdk newArtifactId: verifiedpermissions - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-scheduler newGroupId: software.amazon.awssdk newArtifactId: scheduler - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-marketplacedeployment newGroupId: software.amazon.awssdk newArtifactId: marketplacedeployment - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-resourcegroups newGroupId: software.amazon.awssdk newArtifactId: resourcegroups - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-qldb newGroupId: software.amazon.awssdk newArtifactId: qldb - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-dms newGroupId: software.amazon.awssdk newArtifactId: databasemigration - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-ecr newGroupId: software.amazon.awssdk newArtifactId: ecr - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-dynamodb newGroupId: software.amazon.awssdk newArtifactId: dynamodb - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-resiliencehub newGroupId: software.amazon.awssdk newArtifactId: resiliencehub - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-qldbsession newGroupId: software.amazon.awssdk newArtifactId: qldbsession - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-route53 newGroupId: software.amazon.awssdk newArtifactId: route53domains - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-macie2 newGroupId: software.amazon.awssdk newArtifactId: macie2 - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-chimesdkmeetings newGroupId: software.amazon.awssdk newArtifactId: chimesdkmeetings - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-applicationautoscaling newGroupId: software.amazon.awssdk newArtifactId: applicationautoscaling - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-entityresolution newGroupId: software.amazon.awssdk newArtifactId: entityresolution - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-s3outposts newGroupId: software.amazon.awssdk newArtifactId: s3outposts - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-managedgrafana newGroupId: software.amazon.awssdk newArtifactId: grafana - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-storagegateway newGroupId: software.amazon.awssdk newArtifactId: storagegateway - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-recyclebin newGroupId: software.amazon.awssdk newArtifactId: rbin - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-ioteventsdata newGroupId: software.amazon.awssdk newArtifactId: ioteventsdata - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-route53recoverycluster newGroupId: software.amazon.awssdk newArtifactId: route53recoverycluster - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-ecs newGroupId: software.amazon.awssdk newArtifactId: ecs - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-elasticloadbalancing newGroupId: software.amazon.awssdk newArtifactId: elasticloadbalancing - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-connectcontactlens newGroupId: software.amazon.awssdk newArtifactId: connectcontactlens - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-chimesdkmediapipelines newGroupId: software.amazon.awssdk newArtifactId: chimesdkmediapipelines - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-kinesisvideosignalingchannels newGroupId: software.amazon.awssdk newArtifactId: kinesisvideosignaling - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-qconnect newGroupId: software.amazon.awssdk newArtifactId: qconnect - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-kendraranking newGroupId: software.amazon.awssdk newArtifactId: kendraranking - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-cloudsearch newGroupId: software.amazon.awssdk newArtifactId: cloudsearch - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-logs newGroupId: software.amazon.awssdk newArtifactId: cloudwatchlogs - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-appfabric newGroupId: software.amazon.awssdk newArtifactId: appfabric - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-lookoutforvision newGroupId: software.amazon.awssdk newArtifactId: lookoutvision - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-route53resolver newGroupId: software.amazon.awssdk newArtifactId: route53resolver - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-workspaces newGroupId: software.amazon.awssdk newArtifactId: workspaces - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-machinelearning newGroupId: software.amazon.awssdk newArtifactId: machinelearning - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-costandusagereport newGroupId: software.amazon.awssdk newArtifactId: costandusagereport - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-taxsettings newGroupId: software.amazon.awssdk newArtifactId: taxsettings - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-fsx newGroupId: software.amazon.awssdk newArtifactId: fsx - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-codepipeline newGroupId: software.amazon.awssdk newArtifactId: codepipeline - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-elasticloadbalancingv2 newGroupId: software.amazon.awssdk newArtifactId: elasticloadbalancingv2 - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-directory newGroupId: software.amazon.awssdk newArtifactId: directory - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-bedrockruntime newGroupId: software.amazon.awssdk newArtifactId: bedrockruntime - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-codestarnotifications newGroupId: software.amazon.awssdk newArtifactId: codestarnotifications - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-schemas newGroupId: software.amazon.awssdk newArtifactId: schemas - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-sqs newGroupId: software.amazon.awssdk newArtifactId: sqs - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-appregistry newGroupId: software.amazon.awssdk newArtifactId: servicecatalogappregistry - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-appmesh newGroupId: software.amazon.awssdk newArtifactId: appmesh - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-migrationhuborchestrator newGroupId: software.amazon.awssdk newArtifactId: migrationhuborchestrator - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-discovery newGroupId: software.amazon.awssdk newArtifactId: applicationdiscovery - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-iot newGroupId: software.amazon.awssdk newArtifactId: iot - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-kinesisvideowebrtcstorage newGroupId: software.amazon.awssdk newArtifactId: kinesisvideowebrtcstorage - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-ebs newGroupId: software.amazon.awssdk newArtifactId: ebs - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-amplify newGroupId: software.amazon.awssdk newArtifactId: amplify - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-cloudcontrolapi newGroupId: software.amazon.awssdk newArtifactId: cloudcontrol - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-wellarchitected newGroupId: software.amazon.awssdk newArtifactId: wellarchitected - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-marketplaceentitlement newGroupId: software.amazon.awssdk newArtifactId: marketplaceentitlement - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-bedrock newGroupId: software.amazon.awssdk newArtifactId: bedrock - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-redshift newGroupId: software.amazon.awssdk newArtifactId: redshift - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-connectcases newGroupId: software.amazon.awssdk newArtifactId: connectcases - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-appflow newGroupId: software.amazon.awssdk newArtifactId: appflow - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-gamelift newGroupId: software.amazon.awssdk newArtifactId: gamelift - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-cloudtrail newGroupId: software.amazon.awssdk newArtifactId: cloudtrail - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-supplychain newGroupId: software.amazon.awssdk newArtifactId: supplychain - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-pipes newGroupId: software.amazon.awssdk newArtifactId: pipes - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-cloudwatchevidently newGroupId: software.amazon.awssdk newArtifactId: evidently - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-amplifyuibuilder newGroupId: software.amazon.awssdk newArtifactId: amplifyuibuilder - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-managedblockchainquery newGroupId: software.amazon.awssdk newArtifactId: managedblockchainquery - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-applicationinsights newGroupId: software.amazon.awssdk newArtifactId: applicationinsights - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-chimesdkmessaging newGroupId: software.amazon.awssdk newArtifactId: chimesdkmessaging - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-mediatailor newGroupId: software.amazon.awssdk newArtifactId: mediatailor - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-mediapackagev2 newGroupId: software.amazon.awssdk newArtifactId: mediapackagev2 - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-resourceexplorer2 newGroupId: software.amazon.awssdk newArtifactId: resourceexplorer2 - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-pi newGroupId: software.amazon.awssdk newArtifactId: pi - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-emrserverless newGroupId: software.amazon.awssdk newArtifactId: emrserverless - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-appconfig newGroupId: software.amazon.awssdk newArtifactId: appconfig - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-networkmonitor newGroupId: software.amazon.awssdk newArtifactId: networkmonitor - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-sagemakerfeaturestoreruntime newGroupId: software.amazon.awssdk newArtifactId: sagemakerfeaturestoreruntime - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-chimesdkidentity newGroupId: software.amazon.awssdk newArtifactId: chimesdkidentity - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-computeoptimizer newGroupId: software.amazon.awssdk newArtifactId: computeoptimizer - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-connectparticipant newGroupId: software.amazon.awssdk newArtifactId: connectparticipant - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-mgn newGroupId: software.amazon.awssdk newArtifactId: mgn - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-applicationcostprofiler newGroupId: software.amazon.awssdk newArtifactId: applicationcostprofiler - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-new-service-template newGroupId: software.amazon.awssdk newArtifactId: new-service-template - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-keyspaces newGroupId: software.amazon.awssdk newArtifactId: keyspaces - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-iam newGroupId: software.amazon.awssdk newArtifactId: iam - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-networkfirewall newGroupId: software.amazon.awssdk newArtifactId: networkfirewall - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-redshiftdataapi newGroupId: software.amazon.awssdk newArtifactId: redshiftdata - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-mediastore newGroupId: software.amazon.awssdk newArtifactId: mediastore - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-cloud9 newGroupId: software.amazon.awssdk newArtifactId: cloud9 - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-connectwisdom newGroupId: software.amazon.awssdk newArtifactId: wisdom - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-sso newGroupId: software.amazon.awssdk newArtifactId: sso - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-auditmanager newGroupId: software.amazon.awssdk newArtifactId: auditmanager - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-snowball newGroupId: software.amazon.awssdk newArtifactId: snowball - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-kinesis newGroupId: software.amazon.awssdk newArtifactId: kinesisanalytics - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-route53recoverycontrolconfig newGroupId: software.amazon.awssdk newArtifactId: route53recoverycontrolconfig - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-opsworks newGroupId: software.amazon.awssdk newArtifactId: opsworks - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-identitystore newGroupId: software.amazon.awssdk newArtifactId: identitystore - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-connectcampaign newGroupId: software.amazon.awssdk newArtifactId: connectcampaigns - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-textract newGroupId: software.amazon.awssdk newArtifactId: textract - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-redshiftserverless newGroupId: software.amazon.awssdk newArtifactId: redshiftserverless - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-eks newGroupId: software.amazon.awssdk newArtifactId: eks - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-support newGroupId: software.amazon.awssdk newArtifactId: support - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-mechanicalturkrequester newGroupId: software.amazon.awssdk newArtifactId: mturk - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-apigatewayv2 newGroupId: software.amazon.awssdk newArtifactId: apigatewayv2 - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-devopsguru newGroupId: software.amazon.awssdk newArtifactId: devopsguru - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-prometheus newGroupId: software.amazon.awssdk newArtifactId: amp - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-drs newGroupId: software.amazon.awssdk newArtifactId: drs - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-migrationhubconfig newGroupId: software.amazon.awssdk newArtifactId: migrationhubconfig - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-kafkaconnect newGroupId: software.amazon.awssdk newArtifactId: kafkaconnect - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-kafka newGroupId: software.amazon.awssdk newArtifactId: kafka - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-gluedatabrew newGroupId: software.amazon.awssdk newArtifactId: databrew - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-codedeploy newGroupId: software.amazon.awssdk newArtifactId: codedeploy - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-cloudhsmv2 newGroupId: software.amazon.awssdk newArtifactId: cloudhsmv2 - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-batch newGroupId: software.amazon.awssdk newArtifactId: batch - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-savingsplans newGroupId: software.amazon.awssdk newArtifactId: savingsplans - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-migrationhubstrategyrecommendations newGroupId: software.amazon.awssdk newArtifactId: migrationhubstrategy - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-appsync newGroupId: software.amazon.awssdk newArtifactId: appsync - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-backupgateway newGroupId: software.amazon.awssdk newArtifactId: backupgateway - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-dlm newGroupId: software.amazon.awssdk newArtifactId: dlm - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-amplifybackend newGroupId: software.amazon.awssdk newArtifactId: amplifybackend - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-datazoneexternal newGroupId: software.amazon.awssdk newArtifactId: datazone - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-billingconductor newGroupId: software.amazon.awssdk newArtifactId: billingconductor - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-workspacesthinclient newGroupId: software.amazon.awssdk newArtifactId: workspacesthinclient - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-ssmsap newGroupId: software.amazon.awssdk newArtifactId: ssmsap - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-budgets newGroupId: software.amazon.awssdk newArtifactId: budgets - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-mainframemodernization newGroupId: software.amazon.awssdk newArtifactId: m2 - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-finspace newGroupId: software.amazon.awssdk newArtifactId: finspace - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-detective newGroupId: software.amazon.awssdk newArtifactId: detective - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-lambda newGroupId: software.amazon.awssdk newArtifactId: lambda - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-ssooidc newGroupId: software.amazon.awssdk newArtifactId: ssooidc - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-panorama newGroupId: software.amazon.awssdk newArtifactId: panorama - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-iotevents newGroupId: software.amazon.awssdk newArtifactId: iotevents - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-managedblockchain newGroupId: software.amazon.awssdk newArtifactId: managedblockchain - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-servicediscovery newGroupId: software.amazon.awssdk newArtifactId: servicediscovery - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-waf newGroupId: software.amazon.awssdk newArtifactId: waf - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-ivs newGroupId: software.amazon.awssdk newArtifactId: ivs - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-directconnect newGroupId: software.amazon.awssdk newArtifactId: directconnect - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-mq newGroupId: software.amazon.awssdk newArtifactId: mq - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-pinpointsmsvoicev2 newGroupId: software.amazon.awssdk newArtifactId: pinpointsmsvoicev2 - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-internetmonitor newGroupId: software.amazon.awssdk newArtifactId: internetmonitor - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-artifact newGroupId: software.amazon.awssdk newArtifactId: artifact - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-iotsitewise newGroupId: software.amazon.awssdk newArtifactId: iotsitewise - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-lexmodelsv2 newGroupId: software.amazon.awssdk newArtifactId: lexmodelsv2 - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-lexruntimev2 newGroupId: software.amazon.awssdk newArtifactId: lexruntimev2 - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-serverlessapplicationrepository newGroupId: software.amazon.awssdk newArtifactId: serverlessapplicationrepository - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-eksauth newGroupId: software.amazon.awssdk newArtifactId: eksauth - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-snowdevicemanagement newGroupId: software.amazon.awssdk newArtifactId: snowdevicemanagement - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-clouddirectory newGroupId: software.amazon.awssdk newArtifactId: clouddirectory - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-mediapackagevod newGroupId: software.amazon.awssdk newArtifactId: mediapackagevod - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-codestarconnections newGroupId: software.amazon.awssdk newArtifactId: codestarconnections - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-codeartifact newGroupId: software.amazon.awssdk newArtifactId: codeartifact - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-guardduty newGroupId: software.amazon.awssdk newArtifactId: guardduty - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-worklink newGroupId: software.amazon.awssdk newArtifactId: worklink - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-cleanrooms newGroupId: software.amazon.awssdk newArtifactId: cleanrooms - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-customerprofiles newGroupId: software.amazon.awssdk newArtifactId: customerprofiles - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-trustedadvisor newGroupId: software.amazon.awssdk newArtifactId: trustedadvisor - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-dax newGroupId: software.amazon.awssdk newArtifactId: dax - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-opsworkscm newGroupId: software.amazon.awssdk newArtifactId: opsworkscm - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-docdb newGroupId: software.amazon.awssdk newArtifactId: docdb - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-acmpca newGroupId: software.amazon.awssdk newArtifactId: acmpca - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-kinesis newGroupId: software.amazon.awssdk newArtifactId: firehose - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-ivschat newGroupId: software.amazon.awssdk newArtifactId: ivschat - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-globalaccelerator newGroupId: software.amazon.awssdk newArtifactId: globalaccelerator - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-ses newGroupId: software.amazon.awssdk newArtifactId: ses - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-codegurureviewer newGroupId: software.amazon.awssdk newArtifactId: codegurureviewer - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-lexmodelbuilding newGroupId: software.amazon.awssdk newArtifactId: lexmodelbuilding - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-medicalimaging newGroupId: software.amazon.awssdk newArtifactId: medicalimaging - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-account newGroupId: software.amazon.awssdk newArtifactId: account - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-robomaker newGroupId: software.amazon.awssdk newArtifactId: robomaker - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-lex newGroupId: software.amazon.awssdk newArtifactId: lexruntime - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-autoscaling newGroupId: software.amazon.awssdk newArtifactId: autoscaling - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-nimblestudio newGroupId: software.amazon.awssdk newArtifactId: nimble - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-iotjobsdataplane newGroupId: software.amazon.awssdk newArtifactId: iotjobsdataplane - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-appconfigdata newGroupId: software.amazon.awssdk newArtifactId: appconfigdata - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-controlcatalog newGroupId: software.amazon.awssdk newArtifactId: controlcatalog - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-greengrass newGroupId: software.amazon.awssdk newArtifactId: greengrass - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-securityhub newGroupId: software.amazon.awssdk newArtifactId: securityhub - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-timestreamquery newGroupId: software.amazon.awssdk newArtifactId: timestreamquery - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-backup newGroupId: software.amazon.awssdk newArtifactId: backup - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-opensearchserverless newGroupId: software.amazon.awssdk newArtifactId: opensearchserverless - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-cloudformation newGroupId: software.amazon.awssdk newArtifactId: cloudformation - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-kendra newGroupId: software.amazon.awssdk newArtifactId: kendra - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-connect newGroupId: software.amazon.awssdk newArtifactId: connect - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-elasticache newGroupId: software.amazon.awssdk newArtifactId: elasticache - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-stepfunctions newGroupId: software.amazon.awssdk newArtifactId: sfn - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-cognitoidp newGroupId: software.amazon.awssdk newArtifactId: cognitoidentityprovider - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-chimesdkvoice newGroupId: software.amazon.awssdk newArtifactId: chimesdkvoice - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-workspacesweb newGroupId: software.amazon.awssdk newArtifactId: workspacesweb - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-comprehend newGroupId: software.amazon.awssdk newArtifactId: comprehend - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-applicationsignals newGroupId: software.amazon.awssdk newArtifactId: applicationsignals - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-marketplacemeteringservice newGroupId: software.amazon.awssdk newArtifactId: marketplacemetering - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-devicefarm newGroupId: software.amazon.awssdk newArtifactId: devicefarm - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-rekognition newGroupId: software.amazon.awssdk newArtifactId: rekognition - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-appstream newGroupId: software.amazon.awssdk newArtifactId: appstream - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-polly newGroupId: software.amazon.awssdk newArtifactId: polly - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-rds newGroupId: software.amazon.awssdk newArtifactId: rds - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-pricing newGroupId: software.amazon.awssdk newArtifactId: pricing - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-simpleworkflow newGroupId: software.amazon.awssdk newArtifactId: swf - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-events newGroupId: software.amazon.awssdk newArtifactId: cloudwatchevents - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-ssmquicksetup newGroupId: software.amazon.awssdk newArtifactId: ssmquicksetup - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-autoscalingplans newGroupId: software.amazon.awssdk newArtifactId: autoscalingplans - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-datapipeline newGroupId: software.amazon.awssdk newArtifactId: datapipeline - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-transcribe newGroupId: software.amazon.awssdk newArtifactId: transcribe - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-ivsrealtime newGroupId: software.amazon.awssdk newArtifactId: ivsrealtime - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-personalizeruntime newGroupId: software.amazon.awssdk newArtifactId: personalizeruntime - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-elasticsearch newGroupId: software.amazon.awssdk newArtifactId: elasticsearch - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-codecommit newGroupId: software.amazon.awssdk newArtifactId: codecommit - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-resourcegroupstaggingapi newGroupId: software.amazon.awssdk newArtifactId: resourcegroupstaggingapi - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-forecastquery newGroupId: software.amazon.awssdk newArtifactId: forecastquery - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-healthlake newGroupId: software.amazon.awssdk newArtifactId: healthlake - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-iamrolesanywhere newGroupId: software.amazon.awssdk newArtifactId: rolesanywhere - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-personalizeevents newGroupId: software.amazon.awssdk newArtifactId: personalizeevents - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-apigatewaymanagementapi newGroupId: software.amazon.awssdk newArtifactId: apigatewaymanagementapi - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-launchwizard newGroupId: software.amazon.awssdk newArtifactId: launchwizard - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-xray newGroupId: software.amazon.awssdk newArtifactId: xray - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-ssoadmin newGroupId: software.amazon.awssdk newArtifactId: ssoadmin - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-api-gateway newGroupId: software.amazon.awssdk newArtifactId: apigateway - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-migrationhubrefactorspaces newGroupId: software.amazon.awssdk newArtifactId: migrationhubrefactorspaces - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-ram newGroupId: software.amazon.awssdk newArtifactId: ram - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-codeconnections newGroupId: software.amazon.awssdk newArtifactId: codeconnections - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-efs newGroupId: software.amazon.awssdk newArtifactId: efs - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-bedrockagentruntime newGroupId: software.amazon.awssdk newArtifactId: bedrockagentruntime - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-dataexchange newGroupId: software.amazon.awssdk newArtifactId: dataexchange - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-sts newGroupId: software.amazon.awssdk newArtifactId: sts - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-sagemaker newGroupId: software.amazon.awssdk newArtifactId: sagemaker - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-finspacedata newGroupId: software.amazon.awssdk newArtifactId: finspacedata - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-marketplacecatalog newGroupId: software.amazon.awssdk newArtifactId: marketplacecatalog - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-acm newGroupId: software.amazon.awssdk newArtifactId: acm - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-athena newGroupId: software.amazon.awssdk newArtifactId: athena - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-route53 newGroupId: software.amazon.awssdk newArtifactId: route53 - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-codegurusecurity newGroupId: software.amazon.awssdk newArtifactId: codegurusecurity - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-tnb newGroupId: software.amazon.awssdk newArtifactId: tnb - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-ec2 newGroupId: software.amazon.awssdk newArtifactId: ec2 - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-apprunner newGroupId: software.amazon.awssdk newArtifactId: apprunner - newVersion: 2.29.51 + newVersion: 2.29.52 - org.openrewrite.java.dependencies.ChangeDependency: oldGroupId: com.amazonaws oldArtifactId: aws-java-sdk-lookoutmetrics newGroupId: software.amazon.awssdk newArtifactId: lookoutmetrics - newVersion: 2.29.51 \ No newline at end of file + newVersion: 2.29.52 \ No newline at end of file